天天看點

windbg分析堆溢出

  本文實驗的例子來自《windows進階調試》第6.2.2節,參考書中的方法進行。

1.通過windbg分析堆塊

  (1)在指令行運作程式,輸入參數(輸入超過10個字元),在出現如下提示的時候,使用windbg attach到該程序。

windbg分析堆溢出

  (2)按任意鍵繼續執行,執行完後,程式崩潰到windbg,使用kb指令檢視堆棧如下: 

windbg分析堆溢出

  (3)我們看到報的堆棧資訊是在HeapFree函數中,其實我們知道原因是wcscpy函數溢出了,但崩潰點卻不在溢出發生的地方,堆破壞的最大問題在于造成錯誤的代碼無法在發生堆破壞時被發現,我們可以通過檢視目前堆的一些情況進行分析。 

windbg分析堆溢出

  (4)檢視預設堆的詳細情況,由于資訊比較多,我僅僅把最後一部分列印出來。

windbg分析堆溢出

  (5) 我們看到最後一個堆塊是有問題的,可以看下該堆的内容,我們從004e5188位址開始列印。

windbg分析堆溢出

  (6)我們看到了一系列的0x31字元,就是我們參數輸入的“1”,我們可以用du指令再列印下: 

windbg分析堆溢出

  (7)果然是我們輸入的參數,而且參數越過了堆塊004e51a8,我們把該堆塊的頭列印出來: 

windbg分析堆溢出

  發現堆塊的頭全都被我們輸入的參數覆寫了,這就導緻了記憶體通路異常。 

2.通過windbg+普通頁堆分析

  上面的程式很簡單,很容易通過分析堆塊來找出問題,然而通過分析堆塊來查找堆溢出的問題并非總是可行的,還有一種方式可以讓我們很快找到堆溢出的原因,就是頁堆,我們可以通過Application Verifier工具開啟頁堆。

windbg分析堆溢出

  通過Add Application菜單,添加我們要分析的應用程式,然後再右邊會有Heaps的選項。 

windbg分析堆溢出

  右擊Heaps 選擇屬性,在彈出框中,把full去掉(我們先分析普通頁堆,之後再分析完全頁堆)。 

windbg分析堆溢出

   完成後我們按照原來的方式執行,程式崩潰後,列印堆棧如下。

windbg分析堆溢出

  上面給了我們堆的記憶體資訊,要轉儲頁堆資料的内容,我們需要将該位址減去32位元組然後再轉成_DPH_BLOCK_INFORMATION結構,如下: 

windbg分析堆溢出

  上述結構體最重要的一項是StackTrace,可以查找堆棧的回溯,如下: 

windbg分析堆溢出

  通過上述資訊,我們很快就能找到有問題堆的配置設定棧回溯,通過分析代碼很容易發現堆的溢出情況。 

3.通過windbg+完全頁堆分析

  普通頁堆還不是很直覺的發現堆溢出的地方,但是開啟了完全頁堆就不一樣了,完全頁堆開啟後,程式隻要發生堆溢出就立馬崩潰,這樣就很好的發現問題所在了,開啟完全頁堆:

windbg分析堆溢出

  再次運作程式,崩潰後堆棧情況: 

windbg分析堆溢出

  很快就找到問題所在了,我們可以把wcscpy拷貝的字元列印出來:

windbg分析堆溢出

  就是我們傳入的參數導緻的溢出。 

繼續閱讀