尋找真正的入口(OEP)--廣義ESP定律

/*

還沒學習脫殼,但還是要接觸ESP定律的。

來自看雪可轉載文章:http://www.pediy.com/kssd/pediy06/pediy6083.htm

*/

尋找真正的入口(OEP)--廣義ESP定律

作者:Lenus
FROM: poptown.gamewan.com/bbs
E-MAIL:[email protected]

1.前言
  
  在論壇上看到很多朋友,不知道什麼是ESP定律,ESP的適用範圍是什麼,ESP定律的原理是什麼,如何使用ESP定律?看到了我在

http://poptown.gamewan.com/dispbbs.asp?boardID=5&ID=54&page=1

調查結果發現,大家對ESP定律很感興趣,當然因爲實在是太好用了,現在我就來告訴大傢什麼是ESP定律,它的原理是什麼!!

BTW:在看完了手動脫殼入門十八篇了以後,再看這篇文章也許會對你更有幫助!

在下面地址下載:

http://soft.winzheng.com/SoftView/SoftView_23125.htm

2.準備知識

  在我們開始討論ESP定律之前,我先給你講解一下一些簡單的彙編知識。
  1.call
  這個命令是訪問子程序的一個彙編基本指令。也許你說,這個我早就知道了!別急請繼續看完。
  call真正的意義是什麼呢?我們可以這樣來理解:1.向堆棧中壓入下一行程序的地址;2.JMP到call的子程序地址處。例如:

00401029    .  E8 DA240A00    call 004A3508
0040102E    .  5A             pop edx
在執行了00401029以後,程序會將0040102E壓入堆棧,然後JMP到004A3508地址處!
   
  2.RET
  與call對應的就是RET了。對於RET我們可以這樣來理解:1.將當前的ESP中指向的地址出棧;2.JMP到這個地址。
  
  這個就完成了一次調用子程序的過程。在這裏關鍵的地方是:如果我們要返回父程序,則當我們在堆棧中進行堆棧的操作的時候,一定要保證在RET這條指令之前,ESP指向的是我們壓入棧中的地址。這也就是著名的“堆棧平衡”原理!

3.狹義ESP定律
  
  ESP定律的原理就是“堆棧平衡”原理。
  
  讓我們來到程序的入口處看看吧!
  
  1.這個是加了UPX殼的入口時各個寄存器的值!
EAX 00000000
ECX 0012FFB0
EDX 7FFE0304
EBX 7FFDF000
ESP 0012FFC4
EBP 0012FFF0
ESI 77F51778 ntdll.77F51778
EDI 77F517E6 ntdll.77F517E6
EIP 0040EC90 note-upx.<ModuleEntryPoint>
C 0  ES 0023 32bit 0(FFFFFFFF)
P 1  CS 001B 32bit 0(FFFFFFFF)
A 0  SS 0023 32bit 0(FFFFFFFF)
Z 0  DS 0023 32bit 0(FFFFFFFF)
S 1  FS 0038 32bit 7FFDE000(FFF)
T 0  GS 0000 NULL
D 0
O 0  LastErr ERROR_MOD_NOT_FOUND (0000007E)

  2.這個是UPX殼JMP到OEP後的寄存器的值!
EAX 00000000
ECX 0012FFB0
EDX 7FFE0304
EBX 7FFDF000
ESP 0012FFC4
EBP 0012FFF0
ESI 77F51778 ntdll.77F51778
EDI 77F517E6 ntdll.77F517E6
EIP 004010CC note-upx.004010CC
C 0  ES 0023 32bit 0(FFFFFFFF)
P 1  CS 001B 32bit 0(FFFFFFFF)
A 0  SS 0023 32bit 0(FFFFFFFF)
Z 1  DS 0023 32bit 0(FFFFFFFF)
S 0  FS 0038 32bit 7FFDE000(FFF)
T 0  GS 0000 NULL
D 0
O 0  LastErr ERROR_MOD_NOT_FOUND (0000007E)

呵呵~是不是除了EIP不同以外,其他都一模一樣啊!

爲什麼會這樣呢?
我們來看看UPX的殼的第一行:

0040EC90 n>  60               pushad      //****注意這裏*****
0040EC91     BE 15B04000      mov esi,note-upx.0040B015
  
PUSHAD就是把所有寄存器壓棧!我們在到殼的最後看看:

0040EE0F     61               popad      //****注意這裏*****
0040EE10   - E9 B722FFFF      jmp note-upx.004010CC   //JMP到OEP

POP就是將所有寄存器出棧!


而當我們PUSHAD的時候,ESP將寄存器壓入了0012FFC0--0012FFA4的堆棧中!如下:

0012FFA4   77F517E6  返回到 ntdll.77F517E6 來自 ntdll.77F78C4E           //EDI 
0012FFA8   77F51778  返回到 ntdll.77F51778 來自 ntdll.77F517B5          //ESI
0012FFAC   0012FFF0                                                    //EBP
0012FFB0   0012FFC4                                                   //ESP
0012FFB4   7FFDF000                                                  //EBX
0012FFB8   7FFE0304                                                 //EDX
0012FFBC   0012FFB0                                                //ECX
0012FFC0   00000000                                               //EAX

所以這個時候,在教程上面就告訴我們對ESP的0012FFA4下硬件訪問斷點。也就是說當程序要訪問這些堆棧,從而恢復原來寄存器的值,準備跳向苦苦尋覓的OEP的時候,OD幫助我們中斷下來。

於是我們停在0040EE10這一行!
  
總結:我們可以把殼假設爲一個子程序,當殼把代碼解壓前和解壓後,他必須要做的是遵循堆棧平衡的原理,讓ESP執行到OEP的時候,使ESP=0012FFC4。

4.廣義ESP定律

  很多人看完了教程就會問:ESP定律是不是就是0012FFA4,ESP定律的適用範圍是不是隻能是壓縮殼!
  
  我的回答是:NO!

  看完了上面你就知道你如果用0012FFA8也是可以的,ESP定律不僅用於壓縮殼他也可以用於加密殼!!!

  首先,告訴你一條經驗也是事實---當PE文件運行開始的時候,也就是進入殼的第一行代碼的時候。寄存器的值總是上面的那些值,不信你自己去試試!而當到達OEP後,絕大多的程序都第一句都是壓棧!(除了BC編寫的程序,BC一般是在下面幾句壓棧)

  現在,根據上面的ESP原理,我們知道多數殼在運行到OEP的時候ESP=0012FFC4。這就是說程序的第一句是對0012FFC0進行寫入操作!
  
  最後我們得到了廣義的ESP定律,對只要在0012FFC0下,硬件寫入斷點,我們就能停在OEP的第二句處!!

下面我們來舉個例子,就脫殼進階第一篇吧!

  載入OD後,來到這裏:

0040D042 N>  B8 00D04000      mov eax,Notepad.0040D000 //停在這裏
0040D047     68 4C584000      push Notepad.0040584C
0040D04C     64:FF35 00000000 push dword ptr fs:[0]    //第一次硬件中斷,F9
0040D053     64:8925 00000000 mov dword ptr fs:[0],esp
0040D05A     66:9C            pushfw
0040D05C     60               pushad
0040D05D     50               push eax

直接對0012FFC0下硬件寫入斷點,F9運行。(注意硬件中斷)

在0040D04C第一次硬件中斷,F9繼續!

0040D135     A4               movs byte ptr es:[edi],byte ptr ds:[esi] //訪問異常,不管他 shift+F9繼續
0040D136     33C9             xor ecx,ecx
0040D138     83FB 00          cmp ebx,0
0040D13B   ^ 7E A4            jle short Notepad.0040D0E1

第二次硬件中斷。

004058B5       64             db 64                                 //斷在這裏
004058B6       89             db 89
004058B7       1D             db 1D
004058B8       00             db 00
004058B9       00             db 00

這裏也不是,F9繼續!

004010CC   /.  55             push ebp
004010CD   |.  8BEC           mov ebp,esp  //斷在這裏,哈哈,到了!(如果發現有花指令,用ctrl+A分析一下就能顯示出來)
004010CF   |.  83EC 44        sub esp,44
004010D2   |.  56             push esi

   快吧!還不過癮,在來一個例子。

   脫殼進階第二篇

   如果按上面的方法斷不下來,程序直接運行了!沒什麼,我們在用另一種方法!
  
   載入後停在這裏,用插件把OD隱藏!

0040DBD6 N>^\E9 25E4FFFF      jmp Note_tEl.0040C000                  //停在這裏
0040DBDB     0000             add byte ptr ds:[eax],al
0040DBDD     0038             add byte ptr ds:[eax],bh
0040DBDF     A4               movs byte ptr es:[edi],byte ptr ds:[esi]
0040DBE0     54               push esp

   F9運行,然後用SHIFT+F9跳過異常來到這裏:

0040D817   ^\73 DC            jnb short Note_tEl.0040D7F5       //到這裏
0040D819     CD20 64678F06    vxdcall 68F6764
0040D81F     0000             add byte ptr ds:[eax],al
0040D821     58               pop eax

   在這裏對0012FFC0下硬件寫入斷點!(命令行裏鍵入HW 12FFC0)SHIFT+F9跳過異常,就來到OEP的第二行處:(用CTRL+A分析一下)

004010CC   /.  55             push ebp
004010CD   |.  8BEC           mov ebp,esp                       //斷在這裏
004010CF   |.  83EC 44        sub esp,44
004010D2   |.  56             push esi
004010D3   |.  FF15 E4634000  call dword ptr ds:[4063E4]
004010D9   |.  8BF0           mov esi,eax
004010DB   |.  8A00           mov al,byte ptr ds:[eax]
004010DD   |.  3C 22          cmp al,22

   就這樣我們輕鬆搞定了兩個加密殼的找OEP問題!

5.總結

  現在我們可以輕鬆的回答一些問題了。
  
  1.ESP定律的原理是什麼?

  堆棧平衡原理。
  
  2.ESP定律的適用範圍是什麼?

  幾乎全部的壓縮殼,部分加密殼。只要是在JMP到OEP後,ESP=0012FFC4的殼,理論上我們都可以使用。但是在何時下斷點避開校驗,何時下斷OD才能斷下來,這還需要多多總結和多多積累。歡迎你將你的經驗和我們分享。

  3.是不是隻能下斷12FFA4的訪問斷點?

  當然不是,那只是ESP定律的一個體現,我們運用的是ESP定律的原理,而不應該是他的具體數值,不能說12FFA4,或者12FFC0就是ESP定律,他們只是ESP定律的一個應用罷了!

  4.對於STOLEN CODE我們怎麼辦?

  哈哈,這正是尋找STOLEN CODE最好的辦法!當我們斷下時,正好斷在了殼處理STOLEN CODE的地方,在F8一會就到OEP了!

6.後話
  
  
  以上的方法原理都是我自己總結,自己的經驗,如果有什麼不對的地方,有什麼沒解釋清楚的地方。還請海涵!但是如果覺得我很厲害,那就大可不必,因爲ESP定律也是別人教我的,不是我第一個提出來的!我只是個比你們早飛一點的菜鳥罷了^-^

  看了上面的文字希望能對你在尋找OEP的時候有幫助,但是別忘了一句話:菜鳥認爲找OEP很難,高手認爲修復纔是最難! 好了,下一篇應該寫IAT的修復原理了!讓我們共同努力吧!

  最後如果轉載註明作者並保持文章的完整, 謝謝你看完

發佈了121 篇原創文章 · 獲贊 9 · 訪問量 61萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章