夫天地者,万物之逆旅;光阴者,百代之过客。

0%

一些有关脱壳的较为浅显的笔记(持续更新)

队里的ljzjsc大佬近期在研究脱壳,而我自己反思了一下,开学两个月以来,基本没有学太多东西,一直在玩《我的世界》(有些自闭症的我第一次在网上结交了一些朋友),太颓废了。今天开始着手研究脱壳。萌新一个,笔记比较浅显,望大佬们指教~~

单步调试法

善用ctrl+f8和f4多次调试,善于跳出循环,直到找到OEP(original entry point,程序入口)。

对于简单的壳,如果善于静态调试的话,我个人认为哪怕错过了OEP,只要程序完全解压了,完全可以把任意一处当作OEP,然后把程序dump出来,放到ida中静态分析。缺点是程序无法运行,无法动态调试。

以《加密与解密》第十六章的随书文件RebPE.exe为例。

将文件拖进OD:

1586076232964

f8运行到413001处按f7进入函数:

1586076324838

ctrl+f8自动单步步过运行,直到看到一个大循环,按f8停止自动单步步过运行。

此时手动f8运行一遍这个循环,找一下循环出口。

下图蓝色标记处即为循环出口。单击此处,f4运行到此处。

1586076495538

然后f8一直运行到401130.

1586077022071

这里就是OEP.

工作区内右键 -> 用ollydump脱壳调试程序

1586077347367

即可完成脱壳。

两次内存断点法

一般的壳会依次对.text(代码)、.rdata、.data、.rsrc(资源)区块进行解压处理,所以可以现在比如.rsrc区块处设置内存访问断点,当程序中断时,便已经完成了对.text的解压。

然后此时我们再对.text区块设断点,当外壳跳到OEP返回代码段时即可触发内存访问断点。

仍然以RebPE.exe为例。

alt+m来到内存页,点击图中蓝色处(RebPE的.rsrc区段),按下f2设置断点。

1586077762109

f9(运行)或者shift+f9(忽略错误运行),中断在此处:

1586077851757

再次alt+m来到内存页,点击图中蓝色处(RebPE的.text区段),按下f2设置断点。

1586077879595

再次f9(运行)或者shift+f9(忽略错误运行),中断在此处:

1586077941776

按两次f8,来到此处:

1586077978881

这就是OEP.

ESP定律

原理:外壳初始化的现场环境(各寄存器的值)与原程序的现场环境要相同(主要是esp,ebp等重要的寄存器值)。

通常用pushad/popad(push/pop eax,ecx,edx,ebx,esp,ebp,esi,edi)和pushfd/popfd(push/pop 各标志寄存器)来保存和恢复现场环境,标志寄存器不太重要,一般不处理它。

用法:把esp入栈时的地址设硬件断点,之后恢复现场的时候寄存器的值一定是从栈中恢复的,当访问栈中此处时,运行中断,此处离OEP不远了。

下面是做法,仍以RebPE为例。

程序拖进OD:

1586079213664

f8一次,pushad,各寄存器入栈:

1586079444954

此时的ESP为19ff54,我们在此处设置硬件访问断点,在下图箭头处输入hr 19ff54并回车,hr是硬件访问断点,hw是硬件写断点。

1586079502442

如果你想取消该断点,可以:调试 -> 硬件断点

设置好断点后f9,中断在此处:

1586079126981

然后f8两次,到达OEP.