应用安全 --- vmp流程
VMP (2.0.3-2.13) 寻找OEP详细教程
📋 前置准备
- 工具: OllyDbg / x64dbg / IDA Pro
- 插件: OllyDumpEx、Scylla(用于后续dump)
- 目标: 被VMP保护的程序
🎯 方法一:VirtualProtect断点法(经典方法)
第一步:设置VirtualProtect断点
text
1. 打开调试器,加载目标程序
2. Ctrl+G 跳转到 VirtualProtect 函数
3. 在VirtualProtect入口处下断点(F2)
第二步:分析区段保护修改
assembly
运行程序(F9),每次断在VirtualProtect时:
- 查看堆栈参数:
参数1: lpAddress (要修改的内存地址)
参数2: dwSize (大小)
参数3: flNewProtect (新保护属性)
参数4: lpflOldProtect (旧保护属性指针)
- 记录修改的是哪个区段:
.text - 代码段
.data - 数据段
.rdata - 只读数据段
关键点:当VirtualProtect修改 .text段 的属性为可执行(如PAGE_EXECUTE_READ)时,说明即将执行原始代码!
第三步:寻找VM_RETN
text
1. 最后一次VirtualProtect后,不要按F9
2. 单步跟踪(F8),寻找特征:
- PUSHAD/PUSHFD (保存寄存器)
- 大量垃圾代码
- 寻找RETN指令
3. 在关键RETN处下断点
4. F9运行到RETN
第四步:.text段内存断点
text
1. 查看内存映射(M键或View->Memory)
2. 找到.text段基址
3. 右键 -> Breakpoint -> Memory, on access(访问断点)
4. F9运行
5. 断下时查看EIP,可能已在OEP或附近
🎯 方法二:ESP定律法(更简单)
完整步骤:
assembly
1. 程序停在入口点
2. 记录ESP的值(例如:0012FFA4)
3. 右键ESP寄存器 -> Follow in Dump
4. 在数据窗口,选中前4字节 -> Breakpoint -> Hardware, on access -> DWORD
5. F9运行
6. 断下后,单步几下(F8),通常会到达OEP
特征识别:
- 看到PUSH ebp / MOV ebp, esp
- 或 PUSH ebx / PUSH esi / PUSH edi
- 标准的函数序言 = OEP!
🎯 方法三:内存镜像法(针对2.0x版本)
text
步骤:
1. Ctrl+G -> ImageBase(程序基址,如00400000)
2. 右键 -> Follow in Dump
3. 在数据窗口,右键 -> Breakpoint -> Memory, on execution
4. F9运行
5. 第一次断下继续F9
6. 第二/三次断下,查看附近代码,可能是OEP
🎯 方法四:StrongOD插件自动化
text
使用OllyDbg + StrongOD插件:
1. 加载程序
2. 插件 -> StrongOD -> VMP
3. 选择版本(2.0x)
4. 点击"查找OEP"
5. 自动停在OEP或附近
手动验证:
- 查看代码是否正常
- 是否有标准函数序言
- 交叉引用是否合理
✅ OEP识别特征
真正的OEP通常有这些特征:
assembly
典型C/C++程序:
00401000 PUSH EBP
00401001 MOV EBP, ESP
00401003 SUB ESP, XXX
或Delphi程序:
00401000 PUSH EBX
00401001 PUSH ESI
00401002 PUSH EDI
或简单程序:
00401000 CALL XXXXXXXX ; 调用初始化函数
00401005 MOV EAX, XXX
错误的位置特征:
- 大量垃圾指令
- 不正常的跳转
- 没有函数调用
- 全是NOP或重复指令
📊 调试示例(实战)
assembly
假设目标:test.exe (VMP 2.08)
1. OD加载,停在: 00D51000
2. 下VirtualProtect断点
3. F9运行,第1次断下:修改.data段
4. F9运行,第2次断下:修改.rsrc段
5. F9运行,第3次断下:修改.text段 ← 关键!
堆栈参数显示:
00401000 ; lpAddress (.text段基址)
00003000 ; dwSize
00000020 ; PAGE_EXECUTE_READ
6. F8单步几下,看到:
00D52341 POPAD
00D52342 POPFD
00D52343 RETN
7. F8执行RETN后,跳到:00401000
8. 查看00401000处代码:
00401000 55 PUSH EBP
00401001 8BEC MOV EBP, ESP
00401003 6AFF PUSH -1
✅ 这就是OEP!
⚠️ 注意事项
-
不同版本差异:
- VMP 2.0x 相对简单
- VMP 2.13 可能有多层虚拟化
-
多次虚拟机嵌套:
- 可能需要多次使用方法
- 注意识别真假OEP
-
STOLEN BYTES:
- OEP前几个字节可能被偷取
- 需要从虚拟机中提取还原
-
后续工作:
- 找到OEP只是第一步
- 还需Dump内存、修复IAT
- 使用Scylla或ImportREC修复导入表
🔧 完整脱壳流程
text
1. 找OEP (上述方法)
2. Dump内存 (OllyDumpEx)
3. 修复IAT (Scylla)
4. 测试脱壳后程序
5. 如有问题,检查Stolen Bytes
需要具体某个样本的详细演示吗?
浙公网安备 33010602011771号