魔改CobaltStrike:beacon浅析(下)
本帖最后由 mai1zhi2 于 2021-7-11 16:18 编辑一、 概述
前文再续书接上回,之前写了1-50号功能分析,这次50-100功能号写得会细致点,若有错还请大伙指出,谢谢大伙。
二、50-100功能号分析
Rportfwd任务号50,端口转发数据先获取到监听的端口号:
然后bind sockattr 0.0.0.0:8888和开始listen:
任务号51,rportfwd stopport 停止指定端口转发有关于rportfwd 所涉及到的任务号有15、16、50、51,cs和msf应该是根据portfwd开源项目https://github.com/rssnsj/portfwd/进行整合的。
Ls任务号53,调用FindFirstFileA()、FindNextFileA()相关Api遍历当前文件夹,调用FileTimeToSystemTime()获取文件的文件修改时间大小等信息并通过SystemTimeToTzSpecificLocalTime()转换,最后进行相应的拼接返回给teamserver端:
把获取到的相关文件信息返回给teamserver:
Mkdir任务号54,createDirectoryA()创建目录
drives 任务号55,GetLogicalDrivers()列出目标机上所有的磁盘盘符
Rm任务号56,删除文件先用GetFileAttributesA()获取到文件属性,进行判断是文件还是文件夹:
如果是文件夹就遍历删除里面文件再删文件夹:
如果是文件则直接删:
One-liner任务号59,简单来说就是开启服务器,让执行相应的ps命令,返回一个会话。绑定端口,新建线程进行监听:
执行ps脚本返回会话:
用管道执行 %COMSPEC% /c echo 配合pth hash 发送给对应dll首先调用CreateaNamePipeA()创建管道:
创建新线程,等待另一端连接该管道:
调用connectNamePipe()等待另一端来连接该管道,同时线程阻塞:
接着aggressor端会发送mimikatz.dll进行挂起注入并调用执行,过程与spawn一致,下面是mimikatz.dll内容:
mimikatz.dll进行挂起注入并调用执行:
恢复线程并执行:
在内存中Dump下来mimikatz.dll,里面保存着两条管道名字,负责mimikatz与beacon通信用的:\pipe\8f5879是beacon生成的,mimikatz调用peekNamedPipe去连接:
\pipe\2c67bfba是mimikatz生成的,beacon调用peekNamedPipe去连接:
aggressor会发送任务号61来建立进行与mimikatz.dll的通信,并进行后续的模拟高权限token。mimikatz执行后aggressor回传通信管道信息,任务号61:
调用peekNamedPipe链接mimikatz生成的管道\pipe\2c67bfba:
一旦停止阻塞,就会调用ImpersonateNamedPipeClient来模拟高权限客户端的token,并调用openTreadToken()获得当前线程token:
ImpersonateLoggedOnUser()让当前线程模拟登陆用户进行操作,并保存token值为全局tokenHandle:
Mimikatz Job执行后数据的回传任务号62,流程与任务号40一样。
link 连接SMB Beacon
任务号68,link通过管道连接SMB形式的Beacon Aggress端在生成link方式的stagless 时,会加载windows/ beacon_bind_pipe中pviot.dll的数据:
在link之前,需要建立连接:shell net use \\10.10.10.165\c$/user:"administrator" "!@#Q123"
再执行jump psexec64 10.10.10.165 Test_SMB:
在执行jump命令过程中会调用到link,下面看jump指令的执行过程分析:先调用任务号9 upload上传文件:
将文件保存在目标ip的ADMIN\$下,名字问f9febc5.exe
然后通过任务号100 inline-execute调用该文件。
再调用55任务号rm去删除上传的文件:
接着再调用47任务号pause暂停1秒:
最后调用任务号68 link Beacon:
调用createFIle()打开命名管道:
调用SetNamedPipeHandleState()切换管道为读模式:
循环调用ReadFile()读服务端返回的数据:
将数据返回给teamserver端上线:
Spawnto (x64)
任务号69,spawnto x64,设置Beacon派生会话时使用的程序,执行流程与任务号13 spawnto x86一样。
execute-assembly (x86)
任务号70,内存执行C#的可执行文件,首先传输invokeassembly.dll并注入到rundll32.exe,实现了在其内存中创建CLR环境,然后通过管道再将C#可执行文件读取到内存中,最后执行。
Msf、cs的execute-assembly与开源的https://github.com/b4rtik/metasploit-execute-assembly/大同小异,我们大概了解下其执行流程:当execute-assembly的dll注入到相应进程后先后调用ICLRMetaHost::EnumerateLoadedRuntimes、ICLRMetaHost::GetRuntime方法以获取有效的ICLRRuntimeInfo指针:
调用ICLRRuntimeInfo::GetInterface方法获取接口并使用:这里使用的是ICorRuntimeHost:· 需指定CLSID_CorRuntimeHost为rclsid参数· 需指定IID_ICorRuntimeHost为RIID参数
当获取到_AppDomainPtr后,使用其Load_3(...)从内存中读取并加载.NET程序集
获取参数后调用静态方法。
execute-assembly (x64)
任务号71,流程与任务号70一样,区别只是传输dll的版本是x64的。 Setenv任务号72,putenv()设置环境变量
Cp
任务号73,调用CopyFileA()复制文件
Mv
任务号74,调用MoveFileA()移动文件:
ppid
任务号75,伪造子进程(jobs)的父进程为指定进程,jobs是指portscan等操作,不是派生会话操作。
首先我们设置指定jobs的父进程为18360“
我们设置了注入calc.exe,该进程pid为35752:
查询calc.exe的父进程pid为我们设置好的父进程:
runu
任务号76,父进程欺骗,即指定所创建程序的父进程pid值,并执行该进程:我们设置伪装的父进程pid18360,先用openprocess()以PROCESS_ALL_ACCESS全部权限根据pid打开要伪装的父进程,获取其进程句柄:
调用UpdateProcThreadAttribute(),传入父进程的句柄,指定可继承的句柄:
接着用已构造的属性结构体更新属性表:
最后使用createprocess()传入已跟换父进程属性表STARTUPINFOEX来创建新程序:
getprivs
任务号77,getprivs,启用当前访问令牌所拥有的特权命令窗口输入getprivs后,受控端会受到一系列的特权信息:
当使用hash传递后,tokenhandle会有相应的令牌信息,否则走else流程,流程中先使用GetCurrentProcess()获取当前进程的句柄,再使用OpenProcessToken()打开与进程相关的令牌:
传入指定特权的名称调用LookupPrivilegeValue()函数查看系统权限的特权值,函数调用成功后,信息存入第三个类型为LUID的结构体中,并且函数返回非0。接着调用AdjustTokenPrivileges()并传入新特权信息的指针PTOKEN_PRIVILEGES启用当前访问令牌所拥有的特权。
Run/shell
任务号78,在目标上执行程序(输出回显)调用createProcess()或CreateProcessAsUserA()创建程序,当相关令牌token时(该token是在pth或AdjustTokenPrivileges()提权后获得的),会调用CreateProcessAsUserA(),否则调用createProcess(),
shell会在启动程序的命令前加上cmd.exe:
执行完返回的数据:
没有token时调用createProcess():
Beacon TCP PIVOT 将受感染系统用作内网中其他Beacon会话的中转器。
任务号82,当在Pivoting->Listener(Reserve TCP Beacon)或oneliner,创建完成后再执行一条命令rportfwd 4444 windows/beacon_reverse_tcp,会调用此任务号,原理与rportfwd一致:
调用此任务后,会监听相应的端口:
生成stagless方式的后门时,能选择相应的listen:
选择了windows/beacon_reverse_tcp后,agressor端会读取pviot.dll:
读取到的pviot.dll与beacon.dll是有一定区别的。执行上线:
Argue进程参数欺骗
任务号83是增加欺骗的参数,
任务号84是删除欺骗的参数,
任务号85是查询设置了哪些参数,
我们主要看增加的操作:先调用ExpandEnvironmentString() 扩展环境变量字符串并以定义值替换:
当启动程序进行挂起,然后会替换对应程序的命令:
然后修改该程序进程块的信息
:
Connect
任务号86,Connect连接bind形式的TCP Beacon Aggress端在生成bind方式的stagless 时,会加载windows/beacon_bind_tcp中pviot.dll的数据:
当受到端受到connect指令后,会调用connect函数去连接相应地址及端口:
Bind设置监听的端口:
连接目标ip 的bind端口:
执行上线:
execute-assembly (x86) 任务号87流程与任务号70一样,作用也是内存执行C#的可执行文件,流程一样:首先传输invokeassembly.dll并注入到rundll32.exe,实现了在其内存中创建CLR环境,然后通过管道再将C#可执行文件读取到内存中,最后调用执行。区别是,不使用ImpersonateLoggedOnUser()当前线程模拟登陆用户进行操作,TokenHandle要在pth后才会生成并保存:
execute-assembly (x64)
任务号88流程与任务号71一样,区别是不使用ImpersonateLoggedOnUser()当前线程模拟登陆用户进行操作,TokenHandle要在pth后才会生成并保存:
Portscan等传输反射dll(x86)
任务号89,传输并执行portscan、hashdump等反射dll,即job,原理也是挂起线程rundll32线程注入dll,流程也是一样的,区别是不使用ImpersonateLoggedOnUser()当前线程模拟登陆用户进行操作,TokenHandle要在pth后才会生成并保存:
当相应的job执行完后,会通过管道把数据返回beacon,触发40、62任务号,后面数据传输详见40任务号。Portscan等传输反射dll(x64)任务号90,同89任务号流程一样的,只是在Syswow64的在rundll32.exe
desktop VNC
任务号91,x64 desktopVNC远程桌面(不注入进程),需要由vnc的dll
Blockdlls
任务号92,设置相关策略使创建的子进程加载非微软签名的dll时会被阻止。(win10才生效)
Spawnas (x86)
任务号93,以其他用户身份派生会话,具体流程与任务号1 spawn (x86)一致,区别在注入时启动进程用了CreateProcessWithLogonW()可以指定其他用户身份:
新进程在指定凭据(用户,域和密码)的安全上下文中运行指定的可执行文件:
Spawnas (x64)
任务号94,以其他用户身份派生会话,具体流程与任务号93 spawn (x86)一致,也是在注入时启动进程用了CreateProcessWithLogonW()可以指定其他用户身份,区别只是启动程序的位数不同。
Spawnu (x86)
任务号98,spawnu指令是在指定派生会话进程的父进程,作用与runu指令类似,容易与spawnto混淆了。总体流程时先用openprocess传入要设置为父进程pid值获得相应的进程句柄,然后再用UpdateProcThreadAttribute()更新属性表:
先用openprocess()以PROCESS_ALL_ACCESS全部权限根据pid打开要伪装的父进程,获取其进程句柄:
调用UpdateProcThreadAttribute(),传入父进程的句柄,指定可继承的句柄:
调用DuplicateHandle()复制句柄的目的主要是对句柄权限赋值和修改:
最后调用createProcess()启动rundll32.exe后续进行相应的注入:
派生后的会话进程信息:
派生后的会话进程的父进程信息:
可见新创建的rundll32.exe的父进程指向了所指定的进程。
Spawnu (x64)
任务号99,流程与任务号98一样,只是传输的x64的反射dll。
inline-execute任务号100, 在Beacon会话中执行Beacon Object File (BOF), obj File也就是编译后但未链接的目标文件, Cobalt Strike会先对这个obj文件进行一些处理,比如解析obj文件中一些需要的段.text,.data,在处理一些表比如IMAGE_RELOCATION,IMAGE_SYMBOL等等,然后在经过一系列的处理后,会把需要的部分按照一定格式打包起来随后在发送给Beacon,这时Beacon接收到的是CobaltStrike已经解析处理过的obj文件数据,并非是原本的obj文件,所以Beacon主要做的是必须是在进程内才能确定并完成的事情比如处理重定位,填充函数指针等等,最后去执行go入口点。关于inline-execute执行BOF可参考wbglil的文章https://wbglil.gitbook.io/cobalt ... jie-shao/untitled-3。
三、小结
这次我们分析了beacon约100个功能号,下次我们再一起来重写beacon。若有错误还请师傅指出,最后谢谢大家观看。。
很好的文章,也想要自己用IDA分析一下shellcode,但是不知是用的什么方法在IDA里反汇编了shellcode得到伪代码,CS生成的beacon.exe程序反汇编后只是一个加载shellcode的壳子。。。直接读汇编代码又功力不够。。。 cq2002 发表于 2021-7-12 10:05
表示看不懂。但确实膜拜,能发个完整的魔改成品就好了
haode1111 思路不错,加油。。。
楼主真厉害 学习了,楼主是大拿啊 老大厉害,感谢分享 虽然看不懂,应该很厉害的,膜拜大佬。。 表示看不懂。但确实膜拜,能发个完整的魔改成品就好了 感谢分享,学习下 一脸懵逼的看完。唯一得到的结论是。。。大佬威武 这个魔改后有流量特征吗?