脱壳技术——寻找OEP

1、根据栈平衡原理寻找OEP

在编写加壳软件时,必须保证外壳初始化的现场环境(各寄存器的值)与原程序的现场环境是相同的。加壳程序在初始化时保存各寄存器的值,待外壳执行完毕恢复各寄存器的内容,最后跳转到原程序执行。通常用pushad/popad,pushfd/popfd指令对来保存与恢复现场环境。下面我们来脱一下示例文件RebPE的壳。
程序刚加载时的寄存器和堆栈。

在执行pushad指令后,各寄存器的值将被压入19FF54h~19FF70h的栈中。

此时esp指向19FF54h。对这个地址设置硬件访问断点:hr 19FF54。
按“F9”键运行程序。外壳代码处理结束后,再调用popad指令恢复现场环境。

在按“F8”单步来到401130h这一行,会发现寄存器恢复pushad前的状态。执行完retn指令后,跳转到OEP。

2、用内存访问断点寻找OEP

外壳先将压缩的代码并释放到对应的区块上,处理完毕再跳转到代码段执行。当对代码段设置内存访问断点时,一定会中断在外壳对代码进行读取的那句指令上。
按“Alt+M”组合键打开内存模块,对代码段按F2键设置内存访问断点。

对.txt区块设置内存访问断点后,按“F9”键运行程序,程序将中断在如下代码处。
GIQ59g.png
上面这段代码是解压函数,走出这个函数,将来到外壳代码处,具体如下。
GIQocj.png
这段代码依次将区块解压并放到正确位置。将代码段全部解压后,对代码段(.txt区块)设置内存访问断点。按“F9”键执行程序,程序将在OEP处中断。

还可以通过先在.rdata、.data等区块处设置内存访问断点,待程序中断,代码已解压,再对代码段设置内存访问断点,到达OEP。