GKLBB

当你经历了暴风雨,你也就成为了暴风雨

导航

应用安全 --- 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!

⚠️ 注意事项

  1. 不同版本差异:

    • VMP 2.0x 相对简单
    • VMP 2.13 可能有多层虚拟化
  2. 多次虚拟机嵌套:

    • 可能需要多次使用方法
    • 注意识别真假OEP
  3. STOLEN BYTES:

    • OEP前几个字节可能被偷取
    • 需要从虚拟机中提取还原
  4. 后续工作:

    • 找到OEP只是第一步
    • 还需Dump内存、修复IAT
    • 使用Scylla或ImportREC修复导入表

🔧 完整脱壳流程

text
1. 找OEP (上述方法)
2. Dump内存 (OllyDumpEx)
3. 修复IAT (Scylla)
4. 测试脱壳后程序
5. 如有问题,检查Stolen Bytes

需要具体某个样本的详细演示吗?

posted on 2025-10-29 05:53  GKLBB  阅读(6)  评论(0)    收藏  举报