1

[原创]找寻OEP的两种通用方法

amzilun 2018-5-13 11:06 647

本次我们将了解找寻OEP的两种通用方法,希望能起到抛砖引玉的作用~

调试器:OD

环境:winXP SP3 虚拟机



一.最后一次异常法

壳代码有时主动抛出异常,比如利用异常处理机制做反调试。但是CODE段没有异常。  所以最后一次异常距离真OEP应该很近了。

首先要忽略所有异常,并且配置好反反调试。

F9运行后,点击L来到日志窗口。

这里面一定有一行:程序入口点,它是EP(entry point),不是OEP(original entry point),是带壳的入口点,这是程序最先开始执行的地方。

假设最后一次异常发生在40E88F

重新载入,这次我们不忽略异常,每次当执行到异常被断下时,都按下shift+f9手动忽略异常,直到断到最后一次发生在40e88f的异常。

在代码段设置内存访问断点,按下shift+f9,断到OEP。

注:考虑到过早在代码段设置内存执行断点,就可能被检测到。等到离OEP很近时下断就比较安全了。


二.利用壳常用函数定位OEP
壳代码经常需要调用一些关键函数,跟踪这些关键函数的执行,在合适时机给CODE段下断,到达OEP。
壳最常见的三个函数,GetProcAddress,LoadLibrary,ExitTherad。前2个肯定用到,最后一个未必。
依然使用特殊OD导入,该OD特殊在能给代码段设置内存执行断点。
首先配置OD:忽略所有异常。
因为没有command窗口,不能使用命令下断。于是我们Ctrl+G输入函数的名称 GetProcAddress 后,在段首设置条件记录断点。在expression里填写[esp],也就是记录函数的返回地址。我们记录下返回地址。壳代码最后一次调用,其返回地址就是离OEP很近的地方。
我们要找的是壳代码的最后一次调用,并非程序的最后一次调用。
通过观察 GetProcAddress 的返回地址在哪个区段,可以判断在执行壳代码还是程序代码。同时,它一定在程序入口点之后发生,也许在最后一次异常的附近。
思路有了,怎么才能断在壳代码最后一次调用处呢?借助条件记录断点。
我们在GetProcAddress段首添加条件[esp]==47009a(最后一次调用该函数后返回的地址)
点击F9运行,之后在.text代码段设置内存访问断点(特殊OD里等价于执行断点),重复调用导致系统反复返回到这里。一直不松手按住F9,就可以到达OEP了。
还有一种办法是
利用exitthread函数,因为本例有终止进程的动作。
thread 00000DA8 terminated,exit code 46fe79(4652665)
我们利用这点,让程序断在线程终止的地方。
在调试选项里,来到事件选项卡,点击“Break on thread end”中断在线程结束的位置。
此时再给代码段设置内存访问断点。也可以达到目的。
如果其中一种方法失效,可以尝试第二种方法,也可以尝试最后一次异常法。

最后于 3小时前 被amzilun编辑 ,原因:
最新回复 (2)
张新琪 2018-5-15 09:18
2
你知不知道,GetProcAddress可以重写.如果重写情况下是不是要对导出表做内存访问找到关键代码.不过还是赞一个.
amzilun 2018-5-16 21:22
3
是的,这个是最理想的状况;  实际情况比这个要麻烦的
返回