菜鸟脱壳之脱壳的基础知识(四)——利用ESP定律来寻找OEP

时间:2021-07-04 07:04:52

.上节说的是单步跟踪法,这节讲的是利用堆栈平衡(ESP定律)来进行脱壳!想必大家都听说过ESP定律这个大名吧!ESP定律运用的就是堆栈平衡原理!
一般的加壳软件在执行时,首先要初始化,保存环境(保存各个寄存器的值),一般利用PUSHAD(相当于把eax,ecx,edx,ebx,esp,ebp,esi,edi都压栈),当加壳程序的外壳执行完毕以后,再来恢复各个寄存器的内容,通常会用POPAD(相当与把eax,ecx,edx,ebx,esp,ebp,esi,edi都出栈),通过跨区段的转移来跳到程序的OEP来执行原程序!
在脱壳的时候,我们可以根据堆栈平衡来对ESP进行下断,进而快速到达OEP!
我们用OD来载入上节课加了UPX的壳的Delphi7.0的程序,当单步过pushad以后,会把各个寄存器的值压入堆栈中!

004629D0 >  60                      PUSHAD   // 把所有的寄存器压栈!
004629D1    BE 00F04300            MOV ESI,0043F000
004629D6    8DBE 0020FCFF         LEA EDI,DWORD PTR DS:[ESI+FFFC2000]

这个为寄存器窗口各个寄存器的值:

菜鸟脱壳之脱壳的基础知识(四)——利用ESP定律来寻找OEP

这个为没有步过pushad语句的堆栈窗口的值:

菜鸟脱壳之脱壳的基础知识(四)——利用ESP定律来寻找OEP

这个为步过pushad语句的堆栈窗口的值:

很明显,经过pushad语句以后,所有的寄存器的值都进行了压栈,也就是保存环境!
此时的ESP指向是 0012FF6C,我们来对它下硬件访问断点,我们在寄存器窗口,右键==》数据窗口跟随,在数据窗口的前四个字节,下硬件访问断点 ==》 dword断点!

按F9运行程序,外壳代码处理结束以后,调用popad指令来恢复环境,在访问这些堆栈的时候,会被OD捕获并中断下来,此时,已经离程序的OEP不再遥远了!

00462B75    61               POPAD
00462B76    8D4424 80       LEA EAX,DWORD PTR SS:[ESP-80]            ; 断在了这里
00462B7A    6A 00            PUSH 0
00462B7C    39C4            CMP ESP,EAX
00462B7E  ^ 75 FA            JNZ SHORT 00462B7A
00462B80    83EC 80          SUB ESP,-80
00462B83  ^ E9 109FFEFF      JMP 0044CA98  //经过上节的分析,得知这个跨区段的转移是跳向OEP的!

ESP定律不一定非得在ESP的值为0012FFA4的时候才能运用,合理的运用会使脱壳变得很简单!再告诉大家一个经验吧!ESP定律不只是适用于压缩壳,ESP定律灵活的运用,同样的适用于加密壳(类似VMP等!)。下面我引用看雪论坛的Lenus在他的广义ESP定律里说过的几句话(顺便PS下,我把堆栈平衡原理放到了附录):
“ 首先,告诉你一条经验也是事实---当PE文件运行开始的时候,也就是进入壳的第一行代码的时候。寄存器的值总是上面的那些值,不信你自己去试试!而当到达OEP后,绝大多的程序都第一句都是压栈!(除了BC编写的程序,BC一般是在下面几句压栈)
  现在,根据上面的ESP原理,我们知道多数壳在运行到OEP的时候ESP=0012FFC4。这就是说程序的第一句是对0012FFC0进行写入操作!
最后我们得到了广义的ESP定律,对只要在0012FFC0下,硬件写入断点,我们就能停在OEP的第二句处! ”
附下载版文章:
http://www.2cto.com/uploadfile/2012/1205/20121205071227412.zip