这次我们来探究
beacon
里每个功能点是如何实现的,以便日后更好地实现自定义
beacon
。因为有近百个相关功能点,所以文章就分了上下两部分。
项目地址如下:
https://github.com/mai1zhi2/CobaltstrikeSource
我们从上篇协议剖析得文章中知道当
beacon
发送心跳包后,
teamserver
会返回相应的任务号,并返回相应得任务信息,
beacon
接收到任务信息后,会进入循环处理:
在
AllCase_10007F19()
里面就是
beacon
得全部命令功能,我们按反编译循环中的
case
号从低向高写,
case
号与发送数据包的任务号是大同小异的。
spawn
(
x86
)
case1
,派生会话,原理是挂起方式启动
rundll32
并注入
dll
接收到的数据:
Createprocess()
以挂起方式启动
rundll32.exe
:
注意输入的标志
0x00000004
CREATE_SUSPENDED
:
使用
VirtualAllocEx()
在目标
rundll32
进程申请内存空间:
WriteProcessMemory()
在申请的内存空间写入
dll
:
使用
VirtualProtectEx()
设置内存属性,
PAGE_EXECUTE_READWRITE
设置
context
上下文,并恢复线程:
exit
退出
case3
,
Exit
退出功能,修改
dwMilliseconds
时间为
0
:
如果为
0
就调用
sub_10009BB0()
退出程序:
Sleep
case4
,
Sleep
设置
beacon
睡眠时间
接收数据包,取得修改的时间并进行修改
dwMilliseconds
Cd
切换目录
case 5
,切换目录使用
S
etCurrentDirectory
切换当前进程的当前工作目录。
Inject(x86)
case9
,指定已打开进程来注入会话,原理就是远程线程注入,
dllinject
、
shinject
之类也会走这个
case
。
先用
openprocess()
打开目标进程:
目标申请空间后写入
dll
文件:
最后调用
CreateRemoteThread()
进行远程线程注入:
Upload
上传文件
case10
,
upload
上传文件,
首先分割
teamserver
回传的数据,得到上传的文件名,然后
wb
模式打开文件:
然后获得数据长度和内容,调用
fwrite
写入:
download
下载文件
case11
,
download
下载文件,先分割数据包获得需要下载的文件名,然后打开文件,不断读取文件内容,然后加密返回给
teamserver
:
execute
执行程序
case12
,
execute
执行程序,但不回显
直接使用
createprocess()
启动相应进程:
Spawnto(x86)
case13
,
spawnto
,设置
Beacon
派生会话时使用的程序
当再执行
spawn
时,会判断启用哪个程序进行注入,而不是再注入默认的
rundll32.exe
:
端口转发数据回传
(
没有命令参数
)
case15
,
case16
,
这两个是与
rportfwd
端口转发相关的
case
,首先接收到访问目标机器的请求信息:
然后发送给目标机器,然后中转机通过
select
模型等待信息返回:
最后把
rportfwd
端口转发的信息返回:
desktopVNC
远程桌面
case18
,
x86 desktopVNC
远程桌面(不注入其他进程),不建议用
vnc
download_cancel
取消相关下载文件
case19
,命令
beacon
取消相关的文件下载:
中转子
beacon
所发送的数据
(
没有相关命令参数
)
case22
,没有相关命令行,负责中转子
beacon
的数据传输(注意,不是端口转发的数据):
Unlink
case23
,调用
shutdow()
断开与子
Beacon
的连接
Getuid
case27
,获取当前令牌关联的用户
ID
使用
GetTokenInformation
检索令牌信息和
LookuoAccountSid
获取令牌
SID
:
最后拼接输出:
rev2self
case28
,恢复
Beacon
原始令牌
调用
RevertToSelf()
终止当前用户标识的模拟并返回原始线程标记
:
steal_token
case31
,从目标进程中窃取访问令牌
先打开进程,获取指定进程的句柄令牌,再用
ImpersonateLoggedOnUser
模拟一个登陆用户的访问令牌的安全上下文,最后用
DuplicateTokenEx
拷贝一个当前令牌相同权限的令牌
ps
case32
,显示进程列表
使用
CreateToolhelp32Snapshot()
、
Process32Next()
相关函数遍历系统进程信息,然后进行发送给服务器:
Kill
case33
,结束指定进程
调用
TerminateProcess()
结束指定进程:
powershell-import
case37
,导入
Powershell
脚本
导入相关的
ps
脚本(如
nishang
)以便后续调用
Runas
case38
,以其他用户权限执行程序
调用
CreateProcessWithLogonW()
函数,以某用户身份执行指定程序
Pwd
case39
,显示当前所在目录
直接用
GetCurrentDirectoryA()
得到当前目录并返回:
Job
执行后数据的回传(没有相关命令)
case40
,当
job(PortScan
之类的
)
执行后产生数据会用管道回传给
beacon
:
Createfile()
创建管道:
SetNamedPipeHandleState()
设置管道
PIPE_READMODE_BYTE
模式:
调用
PeekNamedPipe()
读取管道内的数据:
Jobs
case41
,查看
Beacon
中的所有任务,在
list
读取后台进行中的任务
jobkill
case42
,结束一个在后台运行
调用
DisconnectNamedPipe()
与后台进程终止链接:
Inject(x64)
case43
,指定已打开进程来注入会话,原理就是远程线程注入,
dllinject
、
shinject
之类也会走这个
case
,流程与
case9
一样。
Spawn(x64)
case44
,派生会话(
x64
),原理也是挂起线程