Windows Shellcode开发
字数 2062 2025-08-30 06:50:35
Windows Shellcode开发完全指南
一、Shellcode基础概念
1.1 什么是Shellcode
- 一段精心编写的机器代码,具有位置无关、紧凑高效、直接在CPU上执行等特性
- 无需编译即可运行
- 在攻防对抗中常用于网络操作、权限提升、文件操作等
1.2 开发Shellcode的必要性
- 避免使用公开工具生成的固定特征Shellcode
- 扩展自定义功能
- 规避AV/EDR查杀
- 安全开发人员必备技能
二、汇编基础
2.1 寄存器
x86架构
| 寄存器 | 名称 | 用途 |
|---|---|---|
| EAX | 累加器 | 算术运算和函数返回值 |
| EBX | 基址寄存器 | 内存寻址 |
| ECX | 计数器 | 循环计数 |
| EDX | 数据寄存器 | I/O操作 |
| ESI | 源索引 | 字符串/数组操作源指针 |
| EDI | 目的索引 | 字符串/数组操作目的指针 |
| EBP | 基址指针 | 栈帧指针 |
| ESP | 栈指针 | 栈顶指针 |
x64架构
- 扩展了x86的8个通用寄存器(R开头的寄存器)
- 新增r8-r15寄存器
2.2 常用指令
| 指令 | 功能 |
|---|---|
| mov | 数据传输 |
| xor | 寄存器清零或数据解密 |
| push/pop | 栈操作 |
| jmp | 无条件跳转 |
| call | 函数调用 |
| lea | 计算内存地址 |
| cmp | 比较指令 |
2.3 调用约定
__stdcall (WINAPI)
- 参数顺序: 右→左
- 堆栈清理: 被调用者
- 典型应用: Windows API
__cdecl
- 参数顺序: 右→左
- 堆栈清理: 调用者
- 支持变参
__fastcall
- 部分参数通过寄存器传递
三、开发环境配置
3.1 Visual Studio配置
- 关闭安全检查: 避免使用security cookie全局变量
- 关闭优化: 最小优化可使Shellcode体积减小
- 启用MASM: 项目→生成依赖性→生成自定义→勾选masm
3.2 注意事项
- 32位项目需使用低版本工具集(如VS2017)
- 64位项目需使用汇编文件(MSVC不支持内联汇编)
四、Shellcode开发关键点
4.1 必须避免的操作
- 不使用.rdata节中的全局变量/常量
- 不使用导入表
- 不使用C++异常
- 不使用导入延迟表
4.2 动态获取API的方法
-
获取PEB地址: 通过FS/GS寄存器
mov edx, fs:[30h] ; 32位获取PEB -
遍历模块列表:
- 通过PEB→Ldr→InMemoryOrderModuleList
- 比较BaseDllName与目标DLL名称
-
解析导出表:
- 从DLL基地址获取PE头
- 定位导出表(DataDirectory[0])
- 遍历导出函数名称
4.3 位置无关代码技巧
-
字符串存储在栈中:
CHAR str[] = {'H','e','l','l','o','\0'}; // 栈存储 -
避免绝对地址引用
五、Shellcode开发实例
5.1 弹窗Shellcode (MessageBox)
纯汇编实现
; 计算API哈希值
compute_hash:
xor edi, edi
xor eax, eax
lodsb
test al, al
jz compute_hash_finished
ror edi, 0Dh
add edi, eax
jmp compute_hash
compute_hash_finished:
ret
; 动态获取API地址
GetProcAddressByHash:
pushad
push eax ; 保存目标hash
mov edx, fs:[30h] ; 获取PEB
; ... 完整代码见原文 ...
ret
关键步骤
- 计算kernel32.dll和MessageBoxA的哈希值
- 动态获取LoadLibrary和GetProcAddress
- 加载user32.dll并获取MessageBoxA地址
- 调用MessageBoxA
5.2 远程下载Shellcode
实现流程
- VirtualAlloc创建缓存
- InternetOpenA初始化会话
- InternetConnectA连接服务器
- HttpOpenRequestA创建请求
- HttpSendRequestA发送请求
- InternetReadFile读取数据
- InternetCloseHandle关闭句柄
所需API
- WinINet API: InternetOpenA, InternetConnectA等
- 内存管理: VirtualAlloc
六、Shellcode提取与测试
6.1 提取.text节
- 使用010 Editor打开PE文件
- 选择.text节区
- 导出为二进制文件(.bin)
6.2 测试方法
- 使用pe_to_shellcode工具
- 转换为C数组格式
- 通过线程注入执行
七、高级主题
7.1 反射式DLL注入
- 实现自加载的DLL
- 不依赖Windows加载器
7.2 引导程序(Bootstrap)
- 定位ReflectiveLoader函数
- 实现DLL的自加载
八、总结与建议
- 纯汇编Shellcode体积最小但开发难度高
- C/C++开发需注意避免全局变量和导入表
- 熟练掌握PEB遍历和导出表解析是关键
- 反射式DLL注入是高级Shellcode的常见技术
- 建议从简单功能开始逐步扩展
附录:参考资源
- Stephen Fewer的Shellcode开发框架
- Metasploit的block_api.asm和block_reverse_http.asm
- PE文件结构文档
- Windows API文档