壳常用函数定位 OEP

使用工具

  • OllyDbg修改版,简称OD
  • OD 汉化插件均来自互联网;
  • UnPackMe来自互联网,仅供学习使用;
  • 文中特殊数字均是HEX,为了书写方便采用DEC

分析思路

GetProcAddress
  1. 将程序导入 OD,goto 到 GetProcAddress 函数的行首,设置 F2 断点,然后运行程序;

  2. 程序中断在函数的行首,使用shift + F4设置条件记录断点:

    设置条件记录断点

    表达式的值填写[esp],表示获取 ESP 中的数据,同时勾选记录表达式的值以及函数参数选项;

  3. 清空 log 窗口,然后运行程序,条件记录断点会在 log 窗口记录每次调用 GetProcAddress 函数的调用地址及参数:

    记录每次调用

    通过查看内存窗口得知,外壳程序对 GetProcAddress 的最后一次调用位于:0047009A:

    外壳程序的最后一次调用

  4. 重载程序,编辑条件记录断点:

    编辑条件记录断点

    勾选按条件中断选项,同时将条件设置为[ESP] == 0047009A,表示当 ESP 的值为 0047009A 时中断;

  5. 运行程序后,程序中断在条件记录断点位置,来到内存窗口,给代码段设置内存执行断点:

    内存执行断点

  6. 多次运行程序后,程序到达 OEP:

    程序到达 OEP

    这里需要运行太多次了,所以这种方法因程序而异,灵活使用;

    其实,设置了内存执行断点后,就可以将条件访问断点取消了,取消之后就和异常法大同小异了,好处是可以绕过部分反调试;

ExitThread

因为本例中有终止线程的动作,且位于代码段之外,可以使用 ExitThread;

  1. 将程序导入 OD,F9运行程序后,打开日志窗口:

    打开日志窗口

    可以看到,在一堆异常中,有一个线程结束日志,位于最后一次异常之前;

  2. 打开 OD 调试设置菜单,事件选项卡,选中中断于线程结束选项:

    中断于线程结束

  3. 重载并运行程序,程序中断:

    提示信息

    看提示信息可以得知,中断原因是某个线程结束了;

  4. 在内存窗口,给代码段设置内存执行断点,然后运行程序:

    程序中断在 OEP

    程序到达 OEP;