脫殼_esp定律原理
阿新 • • 發佈:2019-01-25
一.準備知識
在我們開始討論ESP定律之前,我先給你講解一下一些簡單的彙編知識。
1.call
這個命令是訪問子程式的一個彙編基本指令。也許你說,這個我早就知道了!別急請繼續看完。call真正的意義是什麼呢?我們可以這樣來理解:
1.向堆疊中壓入下一行程式的地址;
2.JMP到call的子程式地址處。
例如:
程式碼:
00401029.E8 DA240A00 call 004A3508
0040102E.5A pop edx
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值(單步通過))