首页
社区
课程
招聘
[原创]魔改CobaltStrike:beacon浅析(下)
发表于: 2021-7-11 16:08 14879

[原创]魔改CobaltStrike:beacon浅析(下)

2021-7-11 16:08
14879

前文再续书接上回,之前写了1-50号功能分析,这次来看看50-100功能号,若有错还请大伙指出,谢谢大伙。

Rportfwd
任务号50,端口转发数据
先获取到监听的端口号:


然后bind sockattr 0.0.0.0:8888和开始listen:

任务号51,rportfwd stop port 停止指定端口转发
有关于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 desktop VNC远程桌面(不注入进程),需要由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接收到的是Cobalt Strike已经解析处理过的obj文件数据,并非是原本的obj文件,所以Beacon主要做的是必须是在进程内才能确定并完成的事情比如处理重定位,填充函数指针等等,最后去执行go入口点。关于inline-execute执行BOF可参考wbglil的文章https://wbglil.gitbook.io/cobalt-strike/cobalt-strike-yuan-li-jie-shao/untitled-3。


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2021-7-11 16:13 被快乐鸡哥编辑 ,原因:
收藏
免费 4
支持
分享
最新回复 (3)
雪    币: 43
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
很完善  写的很很好
2021-7-12 15:28
0
雪    币: 70
活跃值: (2118)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
追。。。。。。。。。。。。。。。。。。。。。
2021-7-12 16:03
0
雪    币: 3255
活跃值: (1921)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
IBD 发下?
2021-8-4 12:40
0
游客
登录 | 注册 方可回帖
返回
//