1. 程式人生 > >用記憶體斷點找OEP 問題 脫殼時提示無法讀取被除錯程序的記憶體 bad dos signature

用記憶體斷點找OEP 問題 脫殼時提示無法讀取被除錯程序的記憶體 bad dos signature

1. 本文要解決的問題是:
   1.什麼是記憶體斷點?
   2.如何在尋找OEP時使用記憶體斷點。
   3.記憶體斷點的侷限性。

2.記憶體斷點尋找OEP的原理
  i.首先,在OD中記憶體斷點,硬體斷點和普通斷點(F2下斷)是有本質區別的。硬體斷點等效與SoftICE命令bpm,他的中斷要用到DR0-DR7的除錯暫存器,也就是說OD通過這些DR0-DR7的除錯暫存器來判斷是否斷下。
    普通斷點(F2下斷)等效於bpx,他是在所執行的的程式碼的當前地址的一個位元組修改為CC(int3)。當程式執行到int3的時候就會產生一個異常,而這個異常將交給OD處理,把這個異常的regEIP-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段下記憶體訪問斷點了吧。
  而如果你還要繼續問我為什麼一定要到那個地方才可以下斷呢?我難道不可以一開始就下斷嗎?
  正入我上面所說的,如果你在前面下斷很可能殼對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次記憶體斷點去找,如果還不行就用多次記憶體斷點。總之明白了原理在多次的記憶體斷點其實都一樣。從這個過程中我們瞭解的是殼在對區段解碼的順序!

OD脫殼,找到OEP,dump記憶體時提示無法讀取被除錯程序的記憶體 顯示 bad dos signature。可能你在利用二次記憶體映像法時,下的F2斷點,應該下記憶體訪問斷點,動畫演示下載地址:

連結:http://pan.baidu.com/s/1gdXGlxT 密碼:9zjy