windowsclient崩潰分析和除錯

2021-09-07 11:40:05 字數 3784 閱讀 5335

本文介紹windows上崩潰分析的一些手段,順便提多程序除錯、死鎖等。

1.崩潰分析過程

1.1 確認錯誤碼

不管是用windbg還是用vs。首先應該注意的是錯誤碼,而90%以上的崩潰都是非法訪問。

在非法訪問時。能夠看一下訪問的目標位址。

位址是0,或者離0非常近(0x00000008或0xfffffffc)。

一般和空指標相關。假設是乙個貌似正常的位址,通常是物件已析構後訪問其資料,或者堆破壞。

1.2確認崩潰相應的c++操作

什麼是確認崩潰相應的c++操作:

比方非法訪問,通常得有個mov指令才會觸發記憶體訪問,然後導致崩潰。而mov指標相應於c++的哪一步呢?

比方a->b->c->foo();

在看到源**時,會定位於這一行,可是,並不清楚是哪一步訪問失敗。

所以這個時候要檢視相應彙編**。

大概會有好幾個mov,簡單的分析就知道是哪一步時訪問失敗。

對編碼的影響:

這就要求,不要在單個語句中寫太複雜的東西比方

x ? b[i] : y > 0 ? c->member[8] : *ptr;

這種**崩潰。要還原到錯誤的地方非常難。

虛函式呼叫:

通常mov edx, dword ptr [ecx]

mov edx, dword ptr [edx+0x??

]call edx

意味著虛函式呼叫。每一行都可能是崩潰位置(在call內崩潰時,vs會標註出下一條語句的位置)。

在第一行崩潰意味著拿到乙個非法指標,可能是空,也能夠指向非法位址。

在第二行崩潰意味著物件已經析構,ecx指向能夠訪問,可是值不正確。所以拿到的虛函式表不正確。

在最後一行崩潰一般另乙個崩潰棧,可是看不到棧幀,在vs中相應的棧楨顯示乙個位址。沒其他內容。

也一般意味著物件析構。

物件及析構函式:

析構函式是常常發生崩潰的地方,假設沒實使用者提供的析構函式,會定位到幾行彙編。所以沒事,就寫個

析構函式吧,至少能定位到是析構函式。

在析構函式外部還會有一大堆彙編**,裡面是物件成員析構的**。崩潰在裡面的時候,難以確認

是哪個物件析構。

假設用指標,在析構函式中主動呼叫release或delete,這樣能夠顯示呼叫,不用去猜是誰在析構,當然

用指標或值物件。在邏輯上各有其優點。在此不表。

假設崩潰位置是call或jmp到某個a::~a()的位置。能夠推測到析構的物件的型別是a。

物件析構順序是從後往前,從子類到基類,依據這點,結合崩潰位置。能夠推測誰析構。

利用物件布局,比方成員在物件中的偏移,可能有得於推測誰析構出問題。

能夠人為地在物件布局中引入一些填充的位元組,使得能看到this物件(線上崩潰沒有堆上的資料,由於

擷取fulldump並上報有操作上的難度。所以this指向堆上時可能看不到,而在棧上則有可能),有利於分析。

還原上下文:

線上拿到的dump的資訊少,不能除錯。所以能夠依據崩潰所在模組。崩潰在模組中的偏移量,在本地

除錯相應的bin,找到相應的模組。偏移量。打上斷點,能夠在本地還原出崩潰時的執行環境。

當然,在本地執行到相應位置時不一定崩潰,可是,有了很多其它上下文資訊。能夠比較easy確定相應的c++操作。

使用ida:

能夠使用ida讓彙編**更好看,較easy分析流程。

有時可能會

還原出幾個資訊:a::foo() + 0x?

?, b::foo1() + 0x??。這就須要自己依據上下文推斷了。

**優化:

**優化使得分析更難,能夠嘗試改變一些編譯選項,減少優化級別,保留棧楨,關閉應用程式全域性優化,

使得在release下的分析easy些。

所見並不是真實:

windbg和vs看到的棧幀可能是假的:可能在中間某一些可能已經亂了,可能棧楨省略使得vs分析的結果不正確。

(通常是vs分析得不正確。另外也有windbg杯具的時候)

對於在中間已經亂掉的棧。能夠依據返回位址。棧引數,棧楨省略資料等,又一次還原出棧。只是在90%的情況

下,即使還原出來,也不知道下一步怎麼辦。

物件還原:

線上崩潰沒有堆,能夠將感興趣的物件拷貝複製到棧上(自己得控制深拷貝)。然後崩潰上報中就能夠看到

物件的狀態了。

(注意**優化可能使得拷貝無效)

1.3c++上的邏輯

在確定崩潰和c++操作的關係後,就是自己邏輯上的問題了,基本上能遇到的問題都是物件生命週期管理

不當,進而造成非法訪問。

指標的判空能規避一處的非法訪問,可是能夠把錯誤進一步擴散。指標判空。且用且珍惜。

在設計或編碼時,應當考慮**的可除錯性。比方chromium中的執行緒池中,加入任務時,會生成當前呼叫

資訊。和task繫結,以使於定位錯誤。

1.4堆破壞

基本無解,崩潰現場和引入錯誤的點相差太遠。

僅僅能盡人事,聽天命了。

比方,開一下頁堆。存在一定概率使得崩潰出現,看人品。

比方。換乙個crt堆。或者自己寫個,增強錯誤檢測。

比方。crt本身。尤其是除錯的堆,堆上有些填充資訊。使得在看到的時候或多或少嘆口氣:大概認識這些

填充資訊,想要很多其它的資訊,難啊。。

比方。能夠自己寫個偵錯程式,自己插入頁堆,或者使用系統的頁堆。使得檢測自己主動化,然後通過大規模資料

使之重現。

2.其他

多程序除錯:

能夠通過在

hkey_local_machine\software\microsoft\windows nt\currentversion\image file execution options

建立關心的程序名的項。填上debugger鍵值,值為偵錯程式路徑,使得程序建立時就attach。(gflags也是

改這裡)。

可是問題是,有的模組是按需載入的,在這個時候還不能在相應模組中下斷點。

另外能夠自己在關心的位置加上messagebox或atlassert之類的**,等彈出對話方塊時再attach到相應程序。

activex:

attach方法同理。

可是,ie的多程序模型會使得attach不方便。

在ie9及以上,其程序模型是乙個主程序,控制多個tab程序,按一定規則建立tab程序,將任務分派到

tab上。同乙個網頁開啟兩次,可能分配到不同的程序上,也可能是同樣的程序。在同乙個程序中,同一

個activex可能有多個例項,並且每乙個例項相應的主線程還不一定是同乙個執行緒。

通常會控制僅僅開乙個tab,使得除錯更加easy。另外能夠開多tab。然後關閉,然後再開,來測試同乙個程序

有多外activex例項的情況。更進一步,能夠自己呼叫iwebbrowser2,來模擬很多其它的情況。

np外掛程式:

chrome中這個簡單些。乙個外掛程式乙個程序,多個例項。共享主線程。

還有些開源工具將activex適配為np外掛程式,使得能夠在chrome中呼叫ax。除錯。

多機除錯:

前面說過,windbg,vs都支援。

一般使用windbg來看,用~*kb或者

這系列的命令看看執行緒都在幹什麼。而重點關注的則是waitforsingleobjectex之類的呼叫。

通過分析呼叫

相應的引數。進一步能還原出,拿到 分發器 物件後不歸還的執行緒是誰。

或者也能夠!runaway找到占用cpu

高的執行緒,然後看看該執行緒在幹什麼。執行緒迴圈等待,則死鎖了。執行緒一直在那裡跑,可能是死迴圈了。

線下的死鎖檢測,一般能夠向主線程發乙個訊息來實現。

warning:有可能某個執行緒拿到分發器物件,可是該執行緒已經掛掉了。

利用「崩潰軌跡」分析崩潰

原文出自 聽雲技術部落格 崩潰,嚴重傷害使用者的情感,嚴重損害使用者體驗,罪惡行徑簡直令人髮指,特請xx獅 xx猿火速緝拿案犯歸案,刻不容緩,欽此。上圖所示,已經定位到某原始檔的某行,再加上崩潰message,崩潰的原因就顯而易見了。但有些崩潰的原因就不是那麼顯而易見了,往往需要尋找更多蛛絲馬跡來定...

利用「崩潰軌跡」分析崩潰

更多技術乾貨請戳 聽雲部落格 崩潰,嚴重傷害使用者的情感,嚴重損害使用者體驗,罪惡行徑簡直令人髮指,特請xx獅 xx猿火速緝拿案犯歸案,刻不容緩,欽此。上圖所示,已經定位到某原始檔的某行,再加上崩潰message,崩潰的原因就顯而易見了。但有些崩潰的原因就不是那麼顯而易見了,往往需要尋找更多蛛絲馬跡...

iOS應用崩潰(三) 崩潰日誌

當我們在模擬器上除錯時,可能經常遇到下面的記憶體訪問錯誤 該錯誤是對乙個已經釋放的物件進行操作,定位如下 2 終端輸入 info malloc history 命令,即可得到堆疊資訊,從而分析具體問題所在 gdb info malloc history 0x12e4b0 3 也可輸入如下資訊 gdb...