PE文件代码注入
字数 1641 2025-08-22 12:23:30
PE文件代码注入技术详解
前言
本教程将详细介绍如何在64位Windows系统下对PE文件进行代码注入,实现修改扫雷程序使其弹出自定义消息框的功能。与传统的32位PE注入不同,本教程针对64位程序并考虑了地址随机化(ASLR)的情况。
前置知识
Win64调用约定
-
寄存器传参:
- 前四个整数或指针参数通过RCX、RDX、R8和R9寄存器传递
- 前四个浮点参数通过XMM0、XMM1、XMM2和XMM3寄存器传递
-
栈传参:
- 超过四个的参数通过栈传递,从右至左依次入栈
-
Shadow Space:
- 调用者需在栈上为前四个参数预留32字节空间
- 即使被调用函数参数少于四个,仍需预留此空间
-
返回值处理:
- 整型或指针返回值通过RAX寄存器
- 浮点返回值通过XMM0寄存器
- 大返回值(如结构体)通过RCX传递指针,RAX返回该指针
-
其他规则:
- 非易失性寄存器(RBX、RBP、RDI、RSI、R12-R15)使用时必须保护
- 调用者负责清理调用栈
- 寄存器中整型参数右对齐
注入目标
构造并调用以下MessageBoxA函数:
MessageBoxA(0LL, "You are injected!", "PE injected", 0x1040u);
详细步骤
1. 准备工作
- 备份原始程序文件
- 准备工具:
- IDA Pro(用于分析和修改)
- 010 Editor(用于二进制编辑)
- 目标程序(扫雷.exe)
2. 写入字符串
-
定位.rdata段末尾:
- 在IDA中查看.rdata段的结束地址
- 或搜索字符串"InitializeSListHead"定位.rdata段
-
使用010 Editor添加字符串:
- 在.rdata段末尾添加两个字符串:
- "PE injected"(标题)
- "You are injected!"(内容)
- 在.rdata段末尾添加两个字符串:
-
确认字符串位置:
- 重新用IDA打开,检查字符串是否成功添加
- 记录字符串的实际地址
3. 处理地址随机化(ASLR)
由于程序启用了ASLR,不能直接使用绝对地址,需要使用RIP相对寻址:
-
观察原程序如何引用.rdata段变量:
- 例如:
movdqa xmm0, cs:xmmword_140005820 - 对应字节码:
66 0F 6F 05 DE 40 00 00
- 例如:
-
计算相对偏移:
- 偏移量 = 目标地址 - (指令地址 + 指令长度)
4. 添加MessageBoxA函数
原程序只有MessageBoxA的导入表项,没有函数实现:
-
参考exit函数实现:
- exit函数通过跳转到.idata段的对应函数实现
- 字节码示例:
FF 25 ...(jmp指令)
-
在.text段末尾添加跳转代码:
- 使用010 Editor添加跳转指令的字节码
- 跳转目标为.idata段中的MessageBoxA地址
-
调整跳转地址:
- 先用任意有效地址添加代码
- 在IDA中使用"Change Byte"功能调整具体地址
5. 注入调用代码
-
选择注入位置:
- 在开栈操作(
sub rsp, 0E0h)之后注入 - 确保堆栈平衡
- 在开栈操作(
-
构造汇编代码:
mov r9, 1040h ; uType = 0x1040
lea r8, [rip + 0x5662] ; lpCaption = "PE injected"
lea rdx, [rip + 0x5663] ; lpText = "You are injected!"
mov rcx, 0 ; hWnd = NULL
call MessageBoxA
- 转换为字节码:
49 c7 c1 40 10 00 00 ; mov r9, 1040h
4c 8d 05 62 56 00 00 ; lea r8, [rip + 0x5662]
48 8d 15 63 56 00 00 ; lea rdx, [rip + 0x5663]
48 c7 c1 00 00 00 00 ; mov rcx, 0
-
使用IDA修改:
- 使用"Change Byte"功能写入字节码
- 使用"Assemble"功能添加call指令
-
调整偏移量:
- 根据实际字符串位置调整RIP相对偏移
- 可能需要多次尝试才能正确定位
6. 验证结果
- 在IDA中反编译注入的代码,确认是否生成预期的MessageBoxA调用
- 运行修改后的程序,检查是否弹出预期消息框
注意事项
- 备份原始文件:修改前务必备份
- 地址对齐:确保添加的内容正确对齐
- 段大小调整:如果添加内容超出段大小,需要调整PE头中的段大小信息
- 校验和:修改后可能需要更新PE头的校验和
- 调试技巧:可以使用调试器动态调试,验证地址计算是否正确
总结
本教程详细介绍了64位PE文件代码注入的全过程,重点解决了ASLR带来的地址定位问题。通过RIP相对寻址和正确的调用约定实现,可以在现代64位Windows系统上成功注入代码并实现自定义功能。这种方法不仅适用于消息框注入,也可用于其他类型的代码注入场景。