Windows逆向之脱壳-定位OEP
字数 2079 2025-08-24 16:48:16
Windows逆向之脱壳-定位OEP 教学文档
1. 前置知识
OEP (Original Entry Point) - 原始入口点
- 定义:描述可执行文件在没有被壳保护情况下的正常执行起点
- 加壳后变化:
- 执行起点被改为壳的代码段
- 原始程序代码被加密/压缩存放在其他位置
- 在适当时机才会被解密和加载执行
- 重要性:找到OEP是分析加壳软件的关键步骤,只有找到OEP才能分析程序原始逻辑
2. 定位OEP的方法
2.1 单步追踪法
原理
- 通过单步步过(F8)、单步步入(F7)和运行到指定代码(F4)跟踪自脱壳过程
- 在脱壳模块运行完毕后到达OEP,然后dump程序
操作技巧
- 循环/回跳操作:在循环下一指令处F4
- Call指令处理:
- 先F8
- 若程序运行,记录地址后F7跟踪
- 熟练后可使用F2和F9加速定位
- 注意CC断点检测
案例:UPX加壳程序
- 导入OllyDbg开始单步跟踪
- 遇到回跳(如0x00409CA1跳回0x00409C90)时,在0x00409CA3处F4
- 执行到0x00409D45处JMP指令时,在下一条指令F4
- 继续执行到POP ESI
- 看到POPAD和JMP 00401000时,表示解压成功
- F8执行到达OEP
案例:ASPack加壳程序
- 导入OllyDbg开始追踪
- 对0x00408002处Call指令F7步入
- 遇到回跳时(如0x00408140)在下一指令F4
- 关键指令:
004083AF 61 POPAD 004083B0 75 08 JNZ SHORT CRACKME-.004083BA 004083B2 B8 01000000 MOV EAX,1 004083B7 C2 0C00 RETN 0C 004083BA 68 00104000 PUSH CRACKME-.00401000 004083BF C3 RETN - 执行POPAD和跳转后到达OEP
2.2 ESP定律法
堆栈平衡概念
- 函数执行过程:
- 寄存器入栈
- 函数参数入栈(从右向左)
- 函数调用(返回地址压栈)
- 计算结果
- 函数参数出栈
- 返回地址出栈跳转
原理
- 压缩/加密壳通常:
- 开始:PUSHAD压入寄存器
- 结束:POPAD弹出寄存器
- 方法:记录初始ESP值,设置硬件访问断点,F9运行
特殊规律
- WinXP:OEP时ESP≈0x0012FFC4,对0x0012FFC0设断点
- Win10:OEP时ESP≈0x0019FF74,对0x0019FF70设断点
操作步骤
- 记录加载时ESP值
- 数据窗口→转到内存地址→右键→断点→硬件访问→双字
- 快捷命令:HW 内存地址
2.3 二次断点法
原理
- 对.rsrc和.text/.code区域设置断点
- 前提:OllyDbg需忽略所有异常
步骤
- 对.rsrc区域设置断点
- Shift+F9/F9运行,中断后对.text/.code段设断点
- 再次Shift+F9/F9运行
- 剩余部分使用单步追踪法
案例:UPX加壳程序
- 对.rsrc设断点,F9运行中断于0x00409D9A
- 对UPX0设断点,F9运行中断于0x00409DA1
- 使用单步追踪法
案例:ASPack加壳程序
- 对.rsrc设断点,F9运行中断于0x0040875F
- 对.code设断点,F9运行中断于0x00401000
2.4 内存镜像法(特殊OD)
特点
- 特殊OD设置的内存访问断点只在执行(ON EXECUTE)时中断
- 实际是二次断点法的变种
案例:UPX加壳程序
- 在UPX0设内存访问断点
- F9运行等待中断于OEP
案例:ASPack加壳程序
- F9运行首次中断于0x00401000(非OEP)
- 再次F9到达OEP
2.5 特殊方法定位OEP
一步直达法
- 原理:搜索特定指令机器码
- JMP指令:E9(长跳转)、EB(短跳转)、FF25(间接寻址)
- CALL指令:E8(直接调用)、FF96(间接调用)
- POPAD(61):与PUSHAD对应
- 操作:
- Ctrl+B查找二进制字符串
- Ctrl+L查找下一个
- 右键→查找→所有命令
SFX法
- 原理:利用自解压文件特性
- 设置:
- 忽略异常:Options→Debugging options→Exceptions→全选
- SFX选项:
- Trace real entry blockwise(速度快)
- Trace real entry bytewise(速度慢但精确)
- 注意:EP必须在代码段(BaseOfCode)之外才适用
末次异常法
- 适用场景:程序产生大量异常时
- 手工定位步骤:
- 取消所有异常忽略
- CTRL+F2重载
- SHIFT+F9直到程序运行,记录次数m
- 重载后按SHIFT+F9(m-1次)
- 对code段设断点,F9运行中断于OEP
- 异常插件定位:
- 使用ExCounter.dll插件
- 开始计数
- 带我到OEP
- 必要时在CODE段设断点
VB特征脱壳
- VB程序OEP特征:
68 PUSH 指针地址 E8 F0FFFFFF CALL ThunRTMain地址 - 方法:
- 对MSVBVM60.dll的.text设断点
- F9运行,中断后从堆栈获取地址
- 转到该地址找到OEP
3. 总结
方法选择指南
- 新手推荐:单步追踪法(基础)、ESP定律法(高效)
- 复杂壳:二次断点法、内存镜像法
- 大量异常:末次异常法
- VB程序:VB特征脱壳法
注意事项
- 不同操作系统ESP值不同
- 某些壳有反调试措施(如CC断点检测)
- 特殊OD的内存断点行为与常规OD不同
- 异常处理设置会影响多种方法的有效性
通过系统掌握这些方法,可以高效定位各类加壳程序的OEP,为后续逆向分析奠定基础。