GetProcAddress/LoadLibrary/ExitThread函数脱壳寻找OEP
前言:通用的GetProcAddress/LoadLibrary/ExitThread定位脱壳寻找OEP
参考文章:https://bbs.pediy.com/thread-226716.htm
原理分析
如果是一个加密壳的话,那么大概率的话原程序的导入表,导出表,重定位表都被加密,然后加密壳会自己创建一个属于自己的导入表,导出表,重定位来进行使用,而在加密壳恢复的时候那么最后肯定还是会回到OEP的,那么其中就需要进行修复相关的IAT表,重定位表等,而修复IAT表是根据INT表中的函数名称的,就需要遍历GetProcAddress函数名称来获取函数地址,最终填充回IAT表中。
有些情况就是壳进行解密的时候会创建线程,而当线程结束的时候,那么这个时候也就是到OEP的地方了
所以壳最常见的三个函数,GetProcAddress,LoadLibrary,ExitThread,其中前2个肯定用到,最后一个未必。
那么其中肯定有人有问题,难道程序里面的
脱壳分析
首先配置OD,忽略所有异常,如下图所示,这里依然使用特殊OD导入,因为该OD特殊在能给代码段设置内存执行断点
GetProcAddress寻找OEP
因为没有command窗口,不能使用命令下断。于是我们Ctrl+G输入函数的名称 GetProcAddress 后,在段首设置条件记录断点。在expression里填写[esp],也就是记录函数的返回地址。我们记录下返回地址。壳代码最后一次调用,其返回地址就是离OEP很近的地方
我们要找的是壳代码的最后一次调用,并非程序的最后一次调用,通过观察 GetProcAddress 的返回地址在哪个区段,可以判断在执行壳代码还是程序代码。
下面红标,第一处红框是壳代码区段的最后一次调用,后面红框是代码段的第一次调用
如何判断壳程序代码区段的最后一次调用?原因就是你可以看到记录 -> 数据, 条目 250 地址=7C80AE40 消息=COND: 0047009A,它的[ESP] = 0047009A,那么就意味着该CALL返回的地址是0x47009A,而该0x47009A地址是位于当前壳区段的,如下图所示,0x47009A是位于当前壳程序的代码段,而图中的0x428C2B则是已经位于原程序的代码段了
同时,它一定在程序入口点之后发生,也许在最后一次异常的附近。怎么才能断在壳代码最后一次调用处呢?借助条件记录断点,如下图所示
这里还需要考虑一点就是那我什么时候才停下的问题,要不然就直接跑飞了不是吗?所以这里还需要先提前在原程序的.text代码段设置内存访问断点(特殊OD里等价于内存执行断点),这样F9的话到时候也会在原程序OEP的上下地方停下
一直不松手按住F9,直到反汇编窗口有变动然后就放开手,最后从模块中分析代码,就到达OEP附近了,如下图所示
LoadLibrary寻找OEP
LoadLibrary也是一样,如下图所示
ExitThread
这种方法不通用,但是有些壳的话进行解密的话可能只会创建进程来进行解密,这个时候ExitThread就会派上用场了
这里可以通过OD自带的结束进程时断点的设置来进行定位OEP,如下图所示
重新F9运行程序,可以看到此时线程结束的时候就会断下来
接着在code代码段中进行设置内存执行断点,就能来到OEP
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY