在我們開始討論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指向的是我們壓入棧中的位址。這也就是著名的「堆疊平衡」原理!
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 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載入後當前顯示的esp值)
2、hr esp(關鍵標誌下一行**所指示的esp值(單步通過))
現在我們可以輕鬆的回答一些問題了。
1.esp定律的原理是什麼?
堆疊平衡原理。
2.esp定律的適用範圍是什麼?
幾乎全部的壓縮殼,部分加密殼。只要是在jmp到oep後,esp=0012ffc4的殼,理論上我們都可以使用。但是在何時下斷點避開校驗,何時下斷od才能斷下來,這還需要多多總結和多多積累。
3.是不是只能下斷0012ffa4的訪問斷點?
當然不是,那只是esp定律的乙個體現,我們運用的是esp定律的原理,而不應該是他的具體數值,不能說0012ffa4,或者0012ffc0就是esp定律,他們只是esp定律的乙個應用罷了!
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這一行的時候,那麼他就大有作用了!
總結一下:記憶體斷點不修改原**,不會像普通斷點那樣因為修改**被程式校驗而導致中斷失敗;對於區段的訪問只是區域大了一點,其原理和上面分析的三行**是一樣的。
要回答這個問題首先要回答這乙個問題:殼是如何解壓**的?
正如我們知道的,殼如果要把原來加密或壓縮的**執行起來就必須要解壓和解密原來的**。而這乙個過程我們難道不能將他看做是對**段(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次記憶體斷點去找,如果還不行就用多次記憶體斷點。總之明白了原理在多次的記憶體斷點其實都一樣。從這個過程中我們了解的是殼在對區段解碼的順序!
AOP的適用範圍
authentication 許可權 caching快取 context passing內容傳遞 error handling 錯誤處理 lazy loading 延時載入 debugging 除錯 logging,tracing,profiling and monitoring 記錄跟蹤 優化 校...
B tree索引的適用範圍
指和索引中的所有列進行匹配。即查詢條件中完全使用索引中的鍵,並且都為等於條件 指條件中使用的列最左匹配索引中的列,並且都為等於條件。指只匹配某一列的開頭部分,如col1 aaa 但是必須滿足上面提到的匹配最左字首。如 col1 aaa and col2 like k 但是必須滿足上面提到的匹配最左字...
WebAPI常見的鑑權方法,及其適用範圍
在談這個問題之前,我們先來說說在webapi中保障介面請求合法性的常見辦法 當然還有很多其它的,比如 openid connect oauth 2.0協議之上的簡單身份層 basic auth digest auth 不一一例舉了 1 api key api secret resource api ...