队里的ljzjsc大佬近期在研究脱壳,而我自己反思了一下,开学两个月以来,基本没有学太多东西,一直在玩《我的世界》(有些自闭症的我第一次在网上结交了一些朋友),太颓废了。今天开始着手研究脱壳。萌新一个,笔记比较浅显,望大佬们指教~~
单步调试法
善用ctrl+f8和f4多次调试,善于跳出循环,直到找到OEP(original entry point,程序入口)。
对于简单的壳,如果善于静态调试的话,我个人认为哪怕错过了OEP,只要程序完全解压了,完全可以把任意一处当作OEP,然后把程序dump出来,放到ida中静态分析。缺点是程序无法运行,无法动态调试。
以《加密与解密》第十六章的随书文件RebPE.exe为例。
将文件拖进OD:
f8运行到413001处按f7进入函数:
ctrl+f8自动单步步过运行,直到看到一个大循环,按f8停止自动单步步过运行。
此时手动f8运行一遍这个循环,找一下循环出口。
下图蓝色标记处即为循环出口。单击此处,f4运行到此处。
然后f8一直运行到401130.
这里就是OEP.
工作区内右键 -> 用ollydump脱壳调试程序
即可完成脱壳。
两次内存断点法
一般的壳会依次对.text(代码)、.rdata、.data、.rsrc(资源)区块进行解压处理,所以可以现在比如.rsrc区块处设置内存访问断点,当程序中断时,便已经完成了对.text的解压。
然后此时我们再对.text区块设断点,当外壳跳到OEP返回代码段时即可触发内存访问断点。
仍然以RebPE.exe为例。
alt+m来到内存页,点击图中蓝色处(RebPE的.rsrc区段),按下f2设置断点。
f9(运行)或者shift+f9(忽略错误运行),中断在此处:
再次alt+m来到内存页,点击图中蓝色处(RebPE的.text区段),按下f2设置断点。
再次f9(运行)或者shift+f9(忽略错误运行),中断在此处:
按两次f8,来到此处:
这就是OEP.
ESP定律
原理:外壳初始化的现场环境(各寄存器的值)与原程序的现场环境要相同(主要是esp,ebp等重要的寄存器值)。
通常用pushad/popad
(push/pop eax,ecx,edx,ebx,esp,ebp,esi,edi)和pushfd/popfd
(push/pop 各标志寄存器)来保存和恢复现场环境,标志寄存器不太重要,一般不处理它。
用法:把esp入栈时的地址设硬件断点,之后恢复现场的时候寄存器的值一定是从栈中恢复的,当访问栈中此处时,运行中断,此处离OEP不远了。
下面是做法,仍以RebPE为例。
程序拖进OD:
f8一次,pushad,各寄存器入栈:
此时的ESP为19ff54,我们在此处设置硬件访问断点,在下图箭头处输入hr 19ff54并
回车,hr是硬件访问断点,hw是硬件写断点。
如果你想取消该断点,可以:调试 -> 硬件断点
设置好断点后f9,中断在此处:
然后f8两次,到达OEP.