一.準備知識
在我們開始討論esp定律之前,我先給你講解一下一些簡單的彙編知識。
1.call
這個命令是訪問子程式的乙個彙編基本指令。也許你說,這個我早就知道了!別急請繼續看完。call真正的意義是什麼呢?我們可以這樣來理解:
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.
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幫助我們中斷下來。
小結:我們可以把殼假設為乙個子程式,當殼把**解壓前和解壓後,他必須要做的是遵循堆疊平衡的原理。
1、在命令列下斷hr esp-4(此時的esp就是od載入後當前顯示的值)
2、hr esp(關鍵標誌下一行**所指示的esp值(單步通過))
5.總結
現在我們可以輕鬆的回答一些問題了。
1.esp定律的原理是什麼?
堆疊平衡原理。
2.esp定律的適用範圍是什麼?
幾乎全部的壓縮殼,部分加密殼。只要是在jmp到oep後,esp=0012ffc4的殼,理論上我們都可以使用。但是在何時下斷點避開校驗,何時下斷od才能斷下來,這還需要多多總結和多多積累。
3.是不是只能下斷12ffa4的訪問斷點?
當然不是,那只是esp定律的乙個體現,我們運用的是esp定律的原理,而不應該是他的具體數值,不能說12ffa4,或者12ffc0就是esp定律,他們只是esp定律的乙個應用罷了!
記憶體斷點
1、要解決的問題是:
1.什麼是記憶體斷點?
2.如何在尋找oep時使用記憶體斷點。
2、記憶體斷點尋找oep的原理
i. 首先,在od中記憶體斷點和普通斷點(f2下斷)是有本質區別的。
記憶體斷點等效於命令bpm,他的中斷要用到dr0-dr7的除錯暫存器,也就是說od通過這些dr0-dr7的除錯暫存器來判斷是否斷下普通斷點(f2下斷)等效於bpx,他是在所執行的**的當前位址的乙個位元組修改為cc(int3)。當程式執行到int3的時候就會產生乙個異常,而這個異常將交給od處理,把這個異常給eip-1以後,就正好停在了需要的中斷的地方(這個根據系統不同會不一樣),同時od在把上面的int3修改回原來的**。
記憶體斷點分為:記憶體訪問斷點,記憶體寫入斷點。
我們知道,在程式執行的時候會有3種基本的狀態產生:讀取-->寫入-->執行。
004ae242 a1 00104000 mov eax,dword ptr ds:[004ae24c] //004ae24c處的記憶體讀取
004ae247 a3 00104000 mov dword ptr ds:[004ae24c],eax //004ae24c處的記憶體寫入
004ae24c 83c0 01 add eax,1 //004ae24c處的記憶體執行
1.當對004ae24c下記憶體訪問斷點的時候,可以中斷在004ae242也可以中斷在004ae247。
2.當對004ae24c下記憶體寫入斷點的時候,只能中斷在004ae247。
3.當執行004ae24c的時候,只能中斷在004ae24c
到這裡你可能不明白了,為什麼記憶體訪問斷點能中斷在004ae247這一句對004ae24c的寫入,而且還能中斷在004ae24c的執行呢?其實很簡單,我們只要仔細體會一下「記憶體訪問」這四個字的含義遍可以知道,當我們對004ae24c進行讀取的時候需要「訪問」他吧,當我對004ae24c進行寫入的時候也需要「訪問」他吧!!當然我們要執行記憶體位址004ae24c的**的時候也是還是要「訪問」他的!
所以我們不難得出下面的結論:
1.記憶體寫入中斷的地方,一定是也可以用記憶體訪問中斷。
2.記憶體執行的地方,也可以用記憶體訪問中斷。
如果這時你認為,那麼記憶體寫入豈不是沒用了。呵呵~那我要告訴你當然不是,如果你想快速的準確的定位到004ae247這一行的時候,那麼他就大有作用了!
總結一下:記憶體斷點不修改原**,
不會像普通斷點那樣因為修改**被程式校驗而導致中斷失敗;
對於區段的訪問只是區域大了一點,其原理和上面分析的三行**是一樣的。
ii.如何使用記憶體斷點來尋找oep呢?
要回答這個問題首先要回答這乙個問題:殼是如何解壓**的?
正如我們知道的,殼如果要把原來加密或壓縮的**執行起來就必須要解壓和解密原來的**。而這乙個過程我們難道不能將他看做是對**段(code段)的寫入嗎?好了,解壓完畢了。我們要從殼**的區段jmp到原來的**段的時候,難道不正是對**段(code段)的執行嗎?
理清了上面的關係就好辦了,那麼如果載入od後,我們直接對code段下記憶體訪問斷點的時候,一定會中斷在殼對code段的寫入的**的上面,就像上面的004ae247的這一行。而如果當他把code段的**全部解壓解密完畢了以後,jmp到oep的時候,我們是不是還可以停在oep的**上面呢?而且每按下f9都會中斷,因為這時code段在執行中哦!
而如果你還要繼續問我為什麼一定要到那個地方才可以下斷呢?我難道不可以一開始就下斷嗎?
正入我上面所說的,如果你在前面下斷很可能殼對code段還沒解壓完畢呢,這時如果你不停的按f9,你將會看到od的下方不斷的在提示你,「對401000寫入中斷」「對401002寫入中斷」「對401004寫入中斷」.......如果你不介意按f9到他把正個code段寫完的話,我除了同情你的「f9」以外,沒什麼其他的意見!
那麼我們就沒有別更快一點的辦法了嗎?
有的!那就是我們呼之欲出的兩次記憶體斷點辦法。
怎麼理解兩次記憶體斷點呢?
讓我來做乙個假設吧,假設我是乙個殼的作者。乙個exe檔案的有code段,data段,rsrc段.....依次排列在你的記憶體空間中,那麼我會怎麼解碼呢?呵呵~我比較笨一點,我會先將code段解碼,然後再將data段解壓,接著是rsrc段......那麼你不難發現,只要你在data斷或者rsrc段下記憶體訪問斷點,那麼中斷的時候code段就已經解壓完畢了。這時我們再對code段下記憶體訪問斷點,不就可以到達oep了嗎?
這裡注意上面雖然下了兩次記憶體訪問斷點,但是本質是不一樣的,目的也是不一樣的。
1.對data段下記憶體訪問斷點而中斷是因為記憶體寫入中斷,目的是斷在對對data段的解壓時,這時殼要對data段寫資料,但是code段已經解壓 完畢。
2.對code段下記憶體訪問斷點而中斷是因為記憶體執行中斷,目的當然就是尋找oep了。
總結一下:如果我們知道殼在什麼地方對code
段解壓完畢我們就可以使用記憶體斷點,找到
oep。如果不知道,那麼我們就依靠
2次記憶體斷點去找,如果還不行就用多次記憶體斷點。總之明白了原理在多次的記憶體斷點其實都一樣。從這個過程中我們了解的是殼在對區段解碼的順序!
脫殼 esp定律原理
本帖最後由 zf616545 於 2014 10 2 22 14 編輯 esp定律算是我們在脫殼當中最常使用的方法之一,也特別適合像我一樣的新手!而今天文章說的是esp脫殼的原理和分析!只有知道原理了,我們的技術才能走得列遠!一.準備知識 在我們開始討論esp定律之前,我先給你講解一下一些簡單的彙編...
ESP定律的原理
殼 在一開始會使用pushad指令將所有的暫存器入棧,此時esp所指向的記憶體記錄著某乙個暫存器的值。然後我們esp指向的記憶體處下乙個硬體記憶體訪問斷點 執行完殼 後會將所有的暫存器值出棧以平衡堆疊popad,cpu需要訪問原esp記錄的值,殼 解壓完程式 後,最後平衡堆疊時必然要從esp所指向的...
記憶體斷點和硬體斷點
32位邏輯位址 16位段選擇器 偏移位址 16位段選擇器 13位全域性描述符表 區域性描述符表索引 1位gdt ldtflag 2位的訪問控制許可權 由16位得到段選擇器索引到全域性描述符表得到64位的段描述符,段描述符中包含了線性段基址 線性段基址 偏移位址 邏輯位址後半段 得到線性位址空間的乙個...