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加壳程序

  1. 导入OllyDbg开始单步跟踪
  2. 遇到回跳(如0x00409CA1跳回0x00409C90)时,在0x00409CA3处F4
  3. 执行到0x00409D45处JMP指令时,在下一条指令F4
  4. 继续执行到POP ESI
  5. 看到POPAD和JMP 00401000时,表示解压成功
  6. F8执行到达OEP

案例:ASPack加壳程序

  1. 导入OllyDbg开始追踪
  2. 对0x00408002处Call指令F7步入
  3. 遇到回跳时(如0x00408140)在下一指令F4
  4. 关键指令:
    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
    
  5. 执行POPAD和跳转后到达OEP

2.2 ESP定律法

堆栈平衡概念

  • 函数执行过程:
    1. 寄存器入栈
    2. 函数参数入栈(从右向左)
    3. 函数调用(返回地址压栈)
    4. 计算结果
    5. 函数参数出栈
    6. 返回地址出栈跳转

原理

  • 压缩/加密壳通常:
    • 开始:PUSHAD压入寄存器
    • 结束:POPAD弹出寄存器
  • 方法:记录初始ESP值,设置硬件访问断点,F9运行

特殊规律

  • WinXP:OEP时ESP≈0x0012FFC4,对0x0012FFC0设断点
  • Win10:OEP时ESP≈0x0019FF74,对0x0019FF70设断点

操作步骤

  1. 记录加载时ESP值
  2. 数据窗口→转到内存地址→右键→断点→硬件访问→双字
  3. 快捷命令:HW 内存地址

2.3 二次断点法

原理

  • 对.rsrc和.text/.code区域设置断点
  • 前提:OllyDbg需忽略所有异常

步骤

  1. 对.rsrc区域设置断点
  2. Shift+F9/F9运行,中断后对.text/.code段设断点
  3. 再次Shift+F9/F9运行
  4. 剩余部分使用单步追踪法

案例:UPX加壳程序

  1. 对.rsrc设断点,F9运行中断于0x00409D9A
  2. 对UPX0设断点,F9运行中断于0x00409DA1
  3. 使用单步追踪法

案例:ASPack加壳程序

  1. 对.rsrc设断点,F9运行中断于0x0040875F
  2. 对.code设断点,F9运行中断于0x00401000

2.4 内存镜像法(特殊OD)

特点

  • 特殊OD设置的内存访问断点只在执行(ON EXECUTE)时中断
  • 实际是二次断点法的变种

案例:UPX加壳程序

  1. 在UPX0设内存访问断点
  2. F9运行等待中断于OEP

案例:ASPack加壳程序

  1. F9运行首次中断于0x00401000(非OEP)
  2. 再次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)之外才适用

末次异常法

  • 适用场景:程序产生大量异常时
  • 手工定位步骤:
    1. 取消所有异常忽略
    2. CTRL+F2重载
    3. SHIFT+F9直到程序运行,记录次数m
    4. 重载后按SHIFT+F9(m-1次)
    5. 对code段设断点,F9运行中断于OEP
  • 异常插件定位:
    1. 使用ExCounter.dll插件
    2. 开始计数
    3. 带我到OEP
    4. 必要时在CODE段设断点

VB特征脱壳

  • VB程序OEP特征:
    68 PUSH 指针地址
    E8 F0FFFFFF CALL ThunRTMain地址
    
  • 方法:
    1. 对MSVBVM60.dll的.text设断点
    2. F9运行,中断后从堆栈获取地址
    3. 转到该地址找到OEP

3. 总结

方法选择指南

  • 新手推荐:单步追踪法(基础)、ESP定律法(高效)
  • 复杂壳:二次断点法、内存镜像法
  • 大量异常:末次异常法
  • VB程序:VB特征脱壳法

注意事项

  1. 不同操作系统ESP值不同
  2. 某些壳有反调试措施(如CC断点检测)
  3. 特殊OD的内存断点行为与常规OD不同
  4. 异常处理设置会影响多种方法的有效性

通过系统掌握这些方法,可以高效定位各类加壳程序的OEP,为后续逆向分析奠定基础。

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 关键指令: 执行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特征: 方法: 对MSVBVM60.dll的.text设断点 F9运行,中断后从堆栈获取地址 转到该地址找到OEP 3. 总结 方法选择指南 新手推荐:单步追踪法(基础)、ESP定律法(高效) 复杂壳:二次断点法、内存镜像法 大量异常:末次异常法 VB程序:VB特征脱壳法 注意事项 不同操作系统ESP值不同 某些壳有反调试措施(如CC断点检测) 特殊OD的内存断点行为与常规OD不同 异常处理设置会影响多种方法的有效性 通过系统掌握这些方法,可以高效定位各类加壳程序的OEP,为后续逆向分析奠定基础。