ESP定律和記憶體斷點

2021-06-19 03:23:45 字數 4671 閱讀 9980

一.準備知識

在我們開始討論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位的段描述符,段描述符中包含了線性段基址 線性段基址 偏移位址 邏輯位址後半段 得到線性位址空間的乙個...