之前也就是把Windbg做爲一個調試所寫驅動的調試器。只進行源碼級的調試,運用的比較淺顯。函數
最近研讀張銀奎老師的《軟件調試》獲益良多,恰好與之配套的《格蠹彙編》提供了老師大量的調試經驗以及實驗環境。不拿來好好實踐一番簡直浪費。工具
0X01調試筆記之偵查廣告插件測試
俗話說:工欲善其事,必先利其器。對於調試領域來講,更是如此。咱們不但要在本身的計算機中安裝有WinDbg,還應當使用JIT調試的方法。由於對於Windows系統中的應用程序的崩潰問題,JIT調試是很是有效的辦法,並且JIT調試仍是Windows系統和WinDbg密切配合,從而實現高效調試的典範。這樣,當咱們的程序崩潰時,調試器就可以自動地執行,配合以相應的指令,就可以很快地定位程序出錯的位置,從而進行修改。編碼
本節叫偵查廣告插件,其實是用JIT肯定老發生崩潰的錯誤框是哪一個程序彈出來的。spa
第一步 在註冊表中設置JIT調試
咱們首先須要設置JIT調試。這裏須要打開註冊表,對於32位的Windows系統而言,其位置在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug:插件
這裏的Auto表示是否啓動JIT調試,若是這個值爲1,則是啓動JIT調試,若是爲0,說明不啓動。而下面的Debugger保存的是欲啓動的調試器的路徑及參數信息。線程
在執行 AcsVio.exe(人爲製造一個崩潰,彈出錯誤提示框) 以前需設置WinDbug爲默認的即時調試器,設置爲在cmd行輸入C:\WinDbg\windbg_CN.exe -I 命令調試
這是咱們執行提供的AcsVio.exe(一個崩潰的exe文件)
:code
第二步 利用JIT調試來分析軟件問題blog
能夠看到WinDbg已經自動彈出了,而且在出問題的位置斷了下來。上圖中第一個紅框說明了程序的問題:Access violation,也就是訪問違例。而第二個紅框則是給出了出問題位置的反彙編代碼。能夠看到,程序將0賦給了[ecx],這個地址讀寫發生了錯誤,就出現了訪問違例的狀況。
下面輸入指令:
0:000>.symfix c:\Symbols
這條語句用於設置符號路徑。而後輸入:
0:000>kPL
其中k表示顯示棧回溯的信息,P表示將全部參數也顯示出來,L用於隱藏原始代碼:
能夠看到問題就在main函數裏面。經過棧的回溯,咱們就可以看到系統都調用了那些函數,從而進行進一步的分析。
0X02從堆裏搶救丟失的博客
相信不少使用計算機的朋友都曾經遇到過在編輯文章時,因爲本身的不當心或者是計算機的問題,而丟失了剛剛編輯好的文檔的狀況。 雖說如今的文字編輯軟件通常也漸漸支持了自動存盤的功能,使得出現這樣的「悲劇」的概率大大下降了,可是數據丟失的狀況,偶爾仍是會發生的, 並且自動存盤的功能也會有失靈的時候。一旦出現了這種狀況,那麼這就須要咱們掌握必定的調試技術來嘗試恢復這些數據。由於通常來講,這些數據是保存在咱們的內存中的, 理論上來講,只要這塊內存區域的數據沒有被改寫,那麼咱們就有辦法找到那些丟失的數據。
咱們首先打開WinDbg
,而後選擇File菜單下的Open Crash Dump
,載入咱們此次所研究的文件ieblog.dmp。可見WinDbg已經爲咱們打開了文件,而且已經停下來了:
雖說做者是在網上寫的博客文章,可是事實上這篇文章的本體依舊是存在於本地計算機內存中的某個區域中的。因爲做者很清楚本身的博客中有哪些內容,所以咱們能夠在內存中檢索博文中相應的字符串。這裏能夠輸入以下指令:
>s –u 0 L800 「當年在交大」
上述命令的意思是,以Unicode
的形式在內存中查找「當年在交大」這幾個字,查找範圍是從0到800。
回車後發現WinDbg並無返回結果,那麼說明咱們這裏所指定的800這個範圍過小了,這裏修改一下,將上述語句中的800改爲8000000,而後再次嘗試查找:
能夠看到此次檢索出了不少個結果。之因此可以在內存中搜索到這麼多的結果,有多是做者在寫做的過程當中對文章進行了屢次保存,或者說是系統自動進行了保存,因而就在內存中留下了痕跡。那麼咱們下一步的操做就是確認到底是哪一個位置保存的是完整的博文。固然這裏咱們依舊可使用s -u
命令來查找博文中最後的幾個字符,從而定位博文的範圍。或者可使用以下命令:
>du 001b5942 L1000
上述命令的意思是從內存地址爲0x001b5942
的位置開始,以Unicode的形式顯示內存中的內容,一共顯示800個結果。WinDbg輸出以下:
很顯然已經找到了!
能夠發現,這個地址正是博文真實存放的地址。既然已經在內存中找到了這篇文章,那麼下一步就是 將其從內存中提取出來。可使用以下命令:
>.writemem e:\blog_1.txt 001b5942 L1458
這行命令的意思是,將內存起始位置爲0x001b5942
處的內容讀取出來,一共讀取1458個字符,並命名爲blog_1.txt,保存在E盤根目錄下:
而後來到E盤根目錄下,打開blog_1.txt文件:
可見雖然咱們已經把博文提取出來了,可是倒是以亂碼的形式顯示的。並且雖說是亂碼,可是能夠發現這些文字已經很接近於咱們的中文字了。其實之因此會出現這樣的結果,就是由於咱們的系統沒能有效地識別這些編碼。爲了解決這個問題,這裏能夠利用十六進制編輯工具,好比WinHex
打開blog_1.txt文件,而後在文件開頭加上Unicode
的標識符FFFE,這樣系統就可以以Unicode字符的形式進行解析了。
0X03拯救發瘋的Windows 7
在咱們的平常生活中,會接觸到各類各樣的軟件。這些軟件的編寫者在開發該軟件時,每每並不會對其作很是全面的測試,這就致使了當這款軟件被不一樣的用戶所使用時,不可避免地會出現各類各樣的問題。若是隻是功能上出現問題,那麼危害每每不大。可是若是是軟件中存在着致命的漏洞,那麼極可能就會被別有用心者所利用,從而危害到用戶的計算機系統。甚至還可能出現這樣一種狀況,有時候用戶的一些無意的輸入,而軟件中沒有相應的處理機制,因而也就致使了軟件乃至系統的崩潰。那麼這些問題,其實均可以利用調試技術進行解決。
首先打開WinDbg,而後在File菜單下選擇Open Crash Dump
,打開WERA7FB.tmp.mdmp
文件。此時WinDbg就已經幫咱們斷下來了:
在上圖的紅框中能夠發現,出現問題的位置在280號進程中的2a4號線程。所出現的問題是緩衝區的溢出。因爲緩衝區的溢出是與咱們的棧空間緊密相關的,所以咱們如今能夠看一下棧上的狀況。在WinDbg中輸入如下命令:
>kn
其中的k
用於顯示給定的線程中的棧幀的信息,而參數n
能夠顯示幀的編號。WinDbg獲得以下輸出:
能夠看到這裏出現了幾個以Wer開頭的函數,wer
的意思是Windows Error Report,說明這個進程在終止前調用了WER設施,這正是咱們可以獲得這個轉儲文件的緣由。8號棧幀中的函數是UnhandledExceptionFilter,這是位於kernel32.dll中的用於處置未處理異常的核心函數,它也是系統在終止掉一個進程前作最後處理的地方,應用程序錯誤對話框和JIT調試都是從這個函數發起的。
由張銀奎老師所編寫的《軟件調試》的第12章就深刻地討論了這個問題。而在這個函數的下方,通常就是咱們所要查找的致使異常的函數位置了。看一下9號棧幀,這個函數的名稱叫作_report_gsfailure,其所在的模塊爲umpo.dll。說到這裏我想要強調的是,咱們在之後的分析過程當中,若是說遇到了咱們並不熟悉的模塊,那麼我建議你們應當查看一下模塊的基本信息,能夠在WinDbg輸入以下指令:
>lmvm umpo
上述命令中lm
表示列出模塊的信息,v
表示將詳細信息顯示出來,最後的m
表示須要進行模塊名稱的匹配。
WinDbg的輸出以下:
可見,這裏已經列出了關於umpo這個模塊的比較詳細的信息。我之因此強調讓你們多關注一些不太常見的模塊,就是由於不少惡意模塊每每是「三無」產品,好比對於沒有版本號、沒有廠家、沒有產品名稱等,但卻存在於Windows的重要目錄,那麼這個模塊就很值得懷疑了。固然這裏的umpo模塊是沒有問題的。
那麼咱們繼續分析棧幀。簡單來講,是ump
o這個模塊中的UmpoAlpcSendPowerMessage函數出現了緩衝區溢出的狀況。當這個函數要返回的時候,編譯在函數中的溢出檢查代碼檢測出了溢出,因而調用_report_gsfailure函數來報告錯誤。這種檢測溢出的方式一般稱爲基於Cookie的溢出檢查,簡稱爲GS機制。
簡單來講,GS機制就是在可能發生溢出的函數所使用的棧幀起始處(EBP-4的位置)存放一個稱爲Cookie的整數,在函數返回時檢查這個Cookie是否無缺,若是被破壞了,就說明函數中發生了溢出。部署和檢查Cookie的代碼都是編譯器在編譯時加入到函數中的。
由於咱們已經知道函數UmpoAlpcSendPowerMessage出現了緩衝區溢出的錯誤,那麼咱們能夠具體看一下當前的Cookie以及EBP等的值都是多少。能夠在WinDbg中輸入以下命令:
>dd 009afb30-4 L4
上述命令中的dd
表示以雙字的形式顯示內存中的內容,009afb30
表示出問題函數的EBP,減去4則是Cookie值的位置,L4代表顯示4個結果。WinDbg的輸出以下:
能夠看到第一個00640064就是Cookie值,父函數的EBP也是00640064,而返回地址則是006a002e。能夠發現,這些值都不像是正規的內存地址,反而像是ASCII碼值。看來因爲出現了緩衝區溢出的問題,使得一些重要的數據都被沖掉了,變成了其它的數值。下面咱們能夠看一下出問題的函數的變量空間的狀況。那麼該如何肯定這個範圍呢?首先用兩個函數的保存有EBP的位置的地址相減,也就是0x009AFB30減去0x009AF924,得出的結果爲0x20C。可是對於_report_gsfailure這個函數而言,它的下方還包含有Cookie值以及EBP的地址,一共佔據了8個字節的空間,因此還應當用0x20C減去8,也就是0x204,就是問題函數UmpoAlpcSendPowerMessage的變量空間了。那麼下面就來看一下這個空間中發生了什麼:
>db 009afb30-204 L210
上述命令的意思是以字節的形式顯示內存地址爲0x009AFB30減去0x204位置的內容,顯示210個結果:
能夠看到這裏出現了一個超長的文件名,那麼咱們就能夠知道,這就是出現緩衝區溢出問題的源頭了。可見上圖中第一個紅框就是EBP
,而第二個紅框則是返回地址的位置。如今能夠知道,由於Umpo
模塊中的函數UmpoAlpcSendPowerMessage接收到了一個比預想長度還要長的參數,因而就發生了緩衝區的溢出狀況,從而觸發了GS機制。既然知道了緣由,那麼咱們如今只要把文件的名稱改短,問題也就可以解決了。