1. 程式人生 > >脫殼_esp定律原理

脫殼_esp定律原理

本帖最後由 zf616545 於 2014-10-2 22:14 編輯ESP定律算是我們在脫殼當中最常使用的方法之一,也特別適合像我一樣的新手!而今天文章說的是ESP脫殼的原理和分析!只有知道原理了,我們的技術才能走得列遠!
一.準備知識
在我們開始討論ESP定律之前,我先給你講解一下一些簡單的彙編知識。
1.call
這個命令是訪問子程式的一個彙編基本指令。也許你說,這個我早就知道了!別急請繼續看完。call真正的意義是什麼呢?我們可以這樣來理解:
1.向堆疊中壓入下一行程式的地址;
2.JMP到call的子程式地址處。
例如:
程式碼:
00401029.E8 DA240A00 call 004A3508

0040102E.5A pop edx
在執行了00401029以後,程式會將0040102E壓入堆疊,然後JMP到004A3508地址處!
2.RETN
與call對應的就是RETN了。對於RETN我們可以這樣來理解:
1.將當前的ESP中指向的地址出棧;
2.JMP到這個地址。

這個就完成了一次呼叫子程式的過程。在這裡關鍵的地方是:如果我們要返回父程式,則當我們在堆疊中進行堆疊的操作的時候,

一定要保證在RETN這條指令之前,ESP指向的是我們壓入棧中的地址。這也就是著名的“堆疊平衡”原理!

3.狹義ESP定律
ESP定律的原理就是“堆疊平衡”原理。
讓我們來到程式的入口處看看吧!
1.這個是加了ASPACK殼的入口時各個暫存器的值!
程式碼:
EAX 00000000
ECX 0012FFB0
EDX 7FFE0304 //堆疊值
EBX 7FFDF000 //堆疊值
ESP 0012FFC4
EBP 0012FFF0
ESI 77F57D70 ntdll.77F57D70
EDI 77F944A8 ntdll.77F944A8
EIP 0040D000 ASPACK.<ModuleEntryPoint>

2.這個是ASPACK殼JMP到OEP後的暫存器的值!
程式碼:
EAX 004010CC ASPACK.004010CC
ECX 0012FFB0
EDX 7FFE0304 //堆疊值
EBX 7FFDF000 //堆疊值
ESP 0012FFC4
EBP 0012FFF0
ESI 77F57D70 ntdll.77F57D70
EDI 77F944A8 ntdll.77F944A8
EIP 004010CC ASPACK.004010CC

呵呵~是不是除了EIP不同以外,eax儲存當前OEP值,其他都一模一樣啊!
為什麼會這樣呢?我們來看看
0040D000 A> 60 pushad //注意這裡ESP=0012FFC4
0040D001 E8 00000000 call ASPACK.0040D006 //ESP=0012FFA4

PUSHAD就是把所有暫存器壓棧!我們在到殼的最後看看:
程式碼:
0040D558 61 popad //ESP=0012FFA4
0040D559 75 08 jnz short ASPACK.0040D563 //注意這裡ESP=0012FFC4

也就是說當我們對ESP的0012FFA4下硬體訪問斷點之後。當程式要通過堆疊訪問這些值,從而恢復原來暫存器的值,

準備跳向苦苦尋覓的OEP的時候,OD幫助我們中斷下來。

小結:我們可以把殼假設為一個子程式,當殼把程式碼解壓前和解壓後,他必須要做的是遵循堆疊平衡的原理。
因為大家對ESP理解各有異同,但是,大同小異!一般理解可以為:
1、在命令列下斷hr esp-4(此時的ESP就是OD載入後當前顯示的值)
2、hr ESP(關鍵標誌下一行程式碼所指示的ESP值(單步通過))