讀書筆記之《格蠹彙編-軟體除錯案例集錦》

whatday發表於2013-04-19

最近張銀奎大俠出新書《格蠹彙編-軟體除錯案例集錦》 迫不及待買回來看了下,確實是好書,行如流水,看如小說,怕一下看完了之想學習之餘寫下讀書筆記便於以後查詢

1.編輯部落格時,編輯的內容在瀏覽器程式裡,如果發表失敗,網頁上造成博文丟失,只要瀏覽器沒有關閉可以從瀏覽器中來找回文章。

->附加瀏覽器程式s -u 0 L800000 "當年在交大"s是搜尋 u是搜尋Unicode字串(a是ascii字串) 0是開始地址 L800000是搜素的元素個數 這裡是unicode所以元素單位是dword 搜尋的範圍就是 4*800000個byte。

->!address列出使用者態的所有區域,可以看到 State 00010000 MEM_FREE 資訊 所以可以把0改成10000 縮小點範圍。

-> du 001b5942  L1000 du檢視Unicode字串,可以看到完整文章。d是顯示記憶體。因為unicode編碼,所以這個時候把記憶體中的文章寫入檔案會造成亂碼,需要在開頭加入 ff fe。

->eb 001b5942-2 ff fe其中e是修改記憶體b是byte單位。修改後可以用

-> db 001b5942-2觀察下記憶體 然後將記憶體堆儲存到檔案,

->.writemem c:\test.txt 001b5942-2 L2000 最後找回博文。


2.當windows出問題時Bug Check會觸發藍屏崩潰,中斷到核心偵錯程式中,比如 BugCheck C000021A, {e1c52ce0, c0000034, 0, 0} 在WinDbg幫助中可以查到0xC000021A的解釋,這裡需要注意搜尋0xC000021A不是搜尋C000021A。第一個引數e1c52ce0是有關程式的資訊,比如名稱。第二個引數是錯誤碼用!error c0000034 可以檢視解釋。windows支援延時刪除,很多時候檔案已經載入,需要重新啟動來刪除檔案,比如防毒軟體刪除病毒。2個方法,第一種 登錄檔中 Key:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager   Value:PendingFileRenameOperations值下面建立一個延遲刪除列表,系統在下次啟動的時候,CSRSS.EXE程式將根據這個列表對檔案進行延遲更新或者延遲刪除操作。第二種方法 MoveFileEx 設定 MOVEFILE_DELAY_UNTIL_REBOOT 標誌。全部程式列表 !process 0 0在核心除錯才能用,核心除錯是系統為物件有很多程式,使用者態除錯是程式為物件只有一個。


3.系統啟動過程:輸入使用者名稱密碼,WinLogon將其傳遞給LSASS進行驗證,通過驗證建立訪問令牌物件

->WinLogon啟動HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon的UserInit下指定的程式,預設為C:\Windows\system32\userinit.exe, 木馬可以新增在這裡讓系統執行它。

->UserInit程式執行登入和初始化指令碼,然後啟動shell表建中定義的Shell程式,預設是Explorer.exe。出現的問題是沒有開始工作列,這是Explorer除了問題,檢查shell的值正確,檢查UserInit的值被修改,修改回來,重啟出現了工作列。


4.設定JIT(及時除錯機制) 登錄檔 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug 其中Auto為1直接執行偵錯程式 為0表示不直接偵錯程式 先彈出對話方塊,可以選擇除錯或關閉。在管理員許可權下執行WinDbg -I (大寫i)可以把WinDbg註冊為JIT偵錯程式。當廣告外掛引起Explorer程式崩潰時,會進入WinDbg,

->kn 100 k是棧回溯 n是每行前顯示棧幀的序號,100是顯示多少條。kPL也可以檢視棧資訊,P是把引數和函式原型的格式顯示出來,需要私有符號,大P是顯示在一行,小p是每個引數顯示一行,L遮蔽掉與上下文相關的原始檔資訊,以節約篇幅

->.frame /c c切換到棧幀號為c的棧幀, .frame顯示當前區域性上下文,/c顯示暫存器資訊 這裡切換到了CoGetClassObject的函式棧幀

STDAPI CoGetClassObject(
REFCLSID rclsid,                              //建立的Com物件的類識別符號(CLSID)
DWORD dwClsContext,                    //指向介面IUnknown的指標
COSERVERINFO* pServerInfo,       //執行可執行程式碼的上下文
REFIID riid,                                       //建立的Com物件的介面識別符號
LPVOID* ppvObj);                             //用來接收指向Com物件介面地址的指標變數

->kv 1 其中v是顯示前三個引數以及FPO(棧指標省略)資訊和呼叫協議,這裡的引數是不準確的,有些函式沒有這麼多引數 或 使用快速呼叫協議FASTCALL 用到暫存器傳參。對應的 kb是隻顯示前三個引數。這裡得到第一個引數01f1b434 型別是REFCLSID 這個型別沒有匯出 查詢標頭檔案看到它是IID型別 ->dt _GUID 01f1b434 dt是顯示資料型別和按照型別顯示記憶體中的資料 _GUID是結構的型別 得到COM物件的類ID({bbca9f81-8f4f-11d2-90ff-0080c83d3571}),在登錄檔 HKEY_CLASSES_ROOT\CLSID下找到這個GUID 得到模組名wc98pp.dll

->lm vm wc98pp 檢視模組的詳細資訊,其中lm是顯示一個簡單的模組列表, v是顯示詳細資訊, m是對模組名過濾, wc98pp就是模組名,使用匹配符 w*,就會列出w開頭模組的詳細資訊,!lmi也是得到模組詳細資訊,但一次只能查詢一個模組。從資訊看到 無版本 無廠家 無產品名稱 加上 Google一下,得知是廣告外掛,刪除電腦上所有的wc98pp.dll和登錄檔中相關的資訊,恢復正常。


5.win7系統不斷重啟,提示關鍵的一些系統服務被關閉,可能是SvcHost程式意外終止。SvcHost程式崩潰會產生dumpfile,重啟電腦F8,選擇修復計算機,進入win7的WinRE系統,選擇命令列,dir *.mdmp /s 找到dumpfile檔案,插入U盤複製檔案,在正常電腦分析。

->Windbg開啟轉儲檔案 顯示(280.2a4): Stack buffer overflow - code c0000409 (first/second chance not available) 說明280號程式的2a4執行緒發生棧溢位,~*檢視所有執行緒,發現當前執行緒就是發生溢位的執行緒,執行kn觀察棧回溯,
發現幾個Wer開頭的函式,說明程式終止前呼叫了WER措施,從而產生了dumpfile。棧中顯示
...
08 009af5f0 74ee700a kernel32!UnhandleExceptionFilter+0x1af
09 009af942 74ed1674 umpo!__report_gsfailure+0xce
0a 009afb30 006a002e umpo!UmpoAlpcSendPowerMessage+0x88
WARNING: Frame IP not in any known module. Following frames may be wrong.
0b 009afb3c 00000000 0x6a002e
...
0b號棧沒有符號說明,可能是正確資料覆蓋,UmpoAlpcSendPowerMessage中呼叫了__report_gsfailure,此函式是在Cookies的溢位檢查(簡稱GS機制)中報告錯誤的函式,說明U函式中有CS機制,反彙編U函式可以看到
mov eax,dword ptr [XXXX!__security_cookie]
xor eax,ebp
mov dword ptr [ebp-4],eax
返回時有:
call XXXX!__security_check_cookie

->U函式的EBP是009afb30,dd 009afb30-4 l4 得到 009afb2c 00640064 00640064 006a002e 00670070 其中Cookie值為00640064,父函式的EBP為00640064,函式返回地址006a002e,這些值看起來不太像記憶體地址,像ASCII碼。反彙編U函式發現問題程式碼,變數區長度是0x204.

->db 009afb30-0x204 l210 顯示長度0x210=0x204+4(cookie)+4(父ebp)+4(返回地址) 結果中看到一個很長的檔名覆蓋了Cookie父EBP和返回地址,登錄檔搜尋此檔名,改小長度,重啟正常了。


6. 繼續上章系統電源崩潰的問題,採用核心除錯的方法。在WinRE中用bcdedit開啟核心除錯,配置參照:http://blog.csdn.net/whatday/article/details/7290147 重啟後中斷到windbg
->!process 看到 Image:svchost.exe,和上一章推斷一樣斷點異常來自承載系統服務的svchost程式,斷點指令與正在除錯的服務崩潰問題相關。
->k 棧回溯,但是沒有模組符號資訊,因為每個程式的使用者態空間不一樣,而且平凡切換,為了節約時間,偵錯程式不記錄每個使用者態空間有哪些模組,如果要觀察使用者態內容,首先要確保當前程式是要觀察的程式,程式的切換.process /i 9328a530 其中9328a530是程式EPROCESS結構地址, 另外要讓偵錯程式重新載入使用者模組資訊,.reload /user 執行一下就可以了 在執行k命令 棧回溯有資訊了。最終都是到了UnhandleExceptionFilter函式
-> uf KERNELBASE!UnhandledExceptionFilter反彙編得到如下偽碼:
if (ExInfo->ExceptionRecord.ExceptionCode == 0C0000409h && BaseIsKernelDebuggerPresent())
{
    DbgPrint("..STATUS_STACK_BUFFER_OVERRUN encountered..");
    __asm(int 3);
}
->kv 得到 002af8e4 74c97022 74c97038 ... KERNELBASE!UnhandledExceptionFilter+0x5f 第三列的74c97038就是ExInfo(反彙編可知道)
->dt _EXCEPTION_POINTERS 74c97038 -r得到ExceptionCode:On-1073740791 其中r是顯示成員中是子結構成員的資訊
->?? (unsigned int)(-1073740791) 得到 unsigned int 0xc0000409 其中??是專門用來評估C++表示式的
得到結論:函式中有專門的針對溢位異常(0xc0000409)的程式碼,這部分程式碼會判斷當前系統是否被核心除錯,如果是,執行斷點指令(int 3)觸發斷點異常(0x80000003)。再繼續執行,最終觸發WER服務.


7.再接上章電源崩潰,利用JIT進行除錯,
->拷貝WinDbg到問題電腦(複製到U盤->xcopy /s到目標電腦),注意拷貝時碟符問題(有可能C盤變D盤,D盤變E盤,我使用VM中的Win7沒有出現碟符變化)。
->設定JIT,需要注意,在WinRE中的登錄檔不是原始的win7的,需要通過"檔案->載入配置單元->選擇win7盤\windows\system32\config\SOFTWARE檔案",然後在[win7\Microsoft\Windows NT\CurrentVersion\AeDebug]下增加

"Debugger"="c:\WinDbg\WinDbg.exe -p %ld -e %ld -g -loga c:\WindDbg.log"
"Auto"="1"

-loga c:\WindDbg.log是讓WinDbg將工作情況寫入指定檔案中
->重啟計算機後,發現黑屏,遠端核心除錯跟蹤後結論如下:
1.電源服務程式啟動後,從umpo!UmpoMain處開始執行,先呼叫RegisterServiceCtrlHandleExW向服務管理器(services.exe)註冊服務控制函式。然後呼叫umpo!UmpoAlpcinit函式建立一個新的執行緒,入口為umpo!UmpoAlpcListenForPoMessages,用於監聽由全域性變數umpo!UmpoAlpcPoPort所標識的ALPC埠,接收ALPC訊息,向外提供服務.
2.UmpoMain執行緒在呼叫UmpoAlpcInit函式後,繼續呼叫UmpoGroupPolicyInit函式,此函式呼叫UmpoNotifyKernelAllPowerPolicyChanged函式通知電源策略變化,但在處理的過程中發生了棧溢位崩潰。因為註冊了JIT偵錯程式,系統啟動JIT偵錯程式附加到這個程式,電源服務程式處於掛起狀態。
3.伺服器管理程式得到電源服務啟動的訊息,程式中的scext模組(Service Control Manager Extension DLL)企圖通過ALPC訊息註冊電源事件回撥。但電源程式掛起,註冊受阻導致服務管理器的服務執行緒被阻塞。
4.LSM程式在啟動RpcSs服務時與伺服器管理器進行通訊,但是因為伺服器管理器程式的伺服器執行緒阻塞,導致這個程式遲遲不能設定WinLogon主執行緒所等待的TermSrvReadyEvent事件,於是系統啟動的關鍵路徑被阻塞,長時間黑屏。
->黑屏解決方案:把電源服務啟動型別設為"禁止",需要注意的WinDbg命令有,!object 938024f8 觀察事件物件相信資訊,

!thread 9383a030 檢視執行緒詳細資訊,包含引數資訊的棧回溯。
->重啟後沒有WinDbg視窗,但任務管理中已有原因在於執行在會話0(Session 0)中。讓Session 0可見。1.Power服務屬性-登入-允許服務於桌面互動
2.開啟互動服務檢測(Interactive Server Dectection)服務,當Session 0有介面顯示時,此服務會建立通知程式(UI0Dectect.exe)到使用者會話(Session 1),點選對話方塊的View the Message進入Session 0
3.在Power服務啟動時就啟動偵錯程式,以免後邊被阻塞,通過配置可執行檔案的執行選項,HKLM\SOFT\WARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options下建立svshost.exe子健,建立名為Debugger的鍵值,將其設定為c:\WinDbg\WinDbg.exe
4.再啟動電源服務,UI0Detect程式出現,順利進入會話0。
-> 遙控會話0中的JIT偵錯程式,系統其它服務啟動後才觸發的JIT,網路和命令或許可用。將AeDebug下的JIT設定為

c:\WinDbg\WinDbg.exe -p %ld -e %ld -QY -c ".server tcp:port=2000" -loga c:\WinDbg.log注意關掉-g是因為溢位崩潰時。偵錯程式首先收到斷點異常,如果有-g偵錯程式會當成初始斷點,-g是忽略初始斷點,錯過了好時機,.server tcp:port=2000讓WinDbg建立除錯服務,並監聽TCP網路埠。 去掉Image File Execution Options設定,等工作管理員中出現WinDbg後, 在啟動WinDbg-File-Connect to Remote Session-輸入tcp:port=2000,server=127.0.0.1,從而連線成功


8.往PowerPoint拖放指令碼檔案時崩潰,用ADPlus拍照,產生轉儲檔案,日誌檔案,報告檔案,永久儲存現場資料。

Adplus -pn powerpnt.exe -pn wincmd32.exe -hang -o c:\test其中“-pn”開關用於指定您希望 ADPlus 分析的程式名。要指定多個程式,請使用多個“-pn process name”開關。"-hang"此開關將 ADPlus 配置為在掛起模式下執行。您必須將此開關與“-iis”、“-pn”或“-p”開關一起使用。不能將“-hang”與“-crash”開關一起使用。"-o"此開關指示 ADPlus 在哪裡放置除錯輸出檔案。如果使用長檔名,則必須用雙引號將它們括起來。此外,還可以使用 UNC 路徑 (\\server\share)。如果使用 UNC 路徑,則 ADPlus 在緊跟您指定的 UNC 路徑的下方建立一個新資料夾。根據正在執行 ADPlus 的伺服器命名該資料夾(例如,\\server\share\Web1 或 \\server\share\Web2)。如果 ADPlus 在 Web 場中的多臺計算機上(這些計算機全都將其輸出放置於同一網路共享上)執行,則此開關十分有用。
->附加程式 ~0s 切換到0號執行緒,因為幾乎所有windows GUI程式,編號為0的初始執行緒就是UI執行緒。kn 100檢視棧回溯,發現UI執行緒進入核心介面就是失去響應了,從公開API HRESULT OleCreateFromFileEx(REFCLSID rclsid, LPCOLESTR lpszFilenName,...)下手,通過棧回溯得到執行此函式對應棧幀的基地址是0013a98,du 0013a98+c (0013a98+0對應的是父EBP,0013a98+4對應返回地址,0013a98+8對應第一個引數,0013a98+c對應第二個引數)顯示lpszFilenName字串,發現是指令碼檔案全路徑,確認方向沒錯。
->開啟第二個WinDbg開始本地核心除錯 File-kernel Debug-Local,找到PowerPoint程式 !process 0 0 powerpnt.exe 列出該程式的各個執行緒結構 !process 88bfbb80 2,顯示UI執行緒的詳細資訊 !thread 891c4020,發現很多包含SendMessage的函式,傳送訊息都是 3e0 視窗指標都是 bc74ed08,現在關鍵要查出是向哪個視窗傳送訊息的,dd bc74ed08l1得到001506c4, 驗證它是不是視窗控制程式碼可以用 Spy++,也可以用Skywing編寫的sdbgext擴充套件模組中的hwnd擴充套件命令來觀察 !sdbgext.hwnd 001506c4 得到該視窗控制程式碼的程式ID 執行緒ID
->開啟第三個WinDbg,附加這個程式,~*列出所有執行緒,切換到上邊查詢的執行緒,這裡是~0s 然後kn 100發現根本沒有等待和處理視窗訊息,在服務管理中終止該服務,分離附加的PwoerPoint(Debug-Detach Debuggee 或 .detach),恢復正常。
->原因總結,先前的棧回溯中有
...
05 0013a638 775f9904 ole32!BdeBindToObject+0xde
06 0013a8c0 7757c79c ole32!CPackagerMoniker::BindToObject+0xc7
...
通過跟蹤發現是CpackagerMoniker:BindToObject發生問題,win7中沒有呼叫DdeBingToObject,在win7中跟蹤BindToObject執行過程發現呼叫了CoCreateInstance分析引數,得到要建立物件的元件ID,查登錄檔可以找到對應的元件,於是BindToObject呼叫這個元件物件,不呼叫DdeBingToObject.而XP中程式碼邏輯相似,只是沒有找到ID對應的元件,從而呼叫DdeBingToObject出現問題。


9.郵件中的PDF附件,下載直接開啟PDF閱讀器無響應。附加到閱讀器,.dump /mfh c:\dumps\pdf\acrobat.dmp 產生轉儲檔案,/m代表Mimi Dump,但檔案其實一點都不小,因為windows下使用者態轉儲檔案都是用的MiniDumpWriteDump這個API來寫的, /f 是full的意思,代表完整的使用者態轉儲,包含使用者態空間的所有記憶體資料。
->開啟轉儲檔案,File-Open Crash Dump..., 執行~* kv1 其中1代表只顯示每個執行緒的第一個棧幀。發現很多執行緒都是在執行不同形式的Wait函式。檢視引數中的Timeout都是0xFFFFFFFF,也就是INFINITE無限等待,除此之外0號執行緒沒有執行等待,~0s所切換到0號執行緒,u 反彙編程式碼,發現程式碼一直在迴圈。所有執行緒都在等待或忙碌,沒有可以響應介面的執行緒。
->等待和鎖相關,檢視處於鎖定狀態的鎖 !locks,關鍵區通過RTL_CRITICAL_SECTION結構來實現的。

dt _RTL_CRITICAL_SECTION其中LockCount標識關鍵區的鎖狀態,RecursionCount記錄遞迴次數,支援同一執行緒多次進入關鍵區,OwningThread進入關鍵區的執行緒ID,LockSemaphore是這個關鍵區對應的事件物件,為空表示沒有執行緒在等待。!locks不能顯示LockSemaphore欄位,!cs -l 則可以顯示LockSemaphore欄位,再結合前邊棧回溯可以發現,執行緒2460擁有關鍵區物件事件2e0等待2dc,執行緒25f4擁有關鍵區物件事件2dc等待2e0,從而2個執行緒現死鎖。


10.意外藍屏得到dump檔案,開啟dump發現系統執行時間33s,推斷系統正在啟動中,!process 0 0只有3個程式其中有CSRSS,說明已經完成了核心初始化,執行體初始化,大部分驅動載入工作,驅動出問題藍屏有可能。!analyze -v自動分析結果,第一個引數08代表此次異常型別,雙誤異常。結果中錯誤程式碼指向push ebp,定位源程式發現是定義變數。開啟dump時windbg提示:WARNING: Process directory table base C7F45840 doesn't match CR3 00185000,Implicit process is now 85ad72c0,!process85ad72c0 0得到當前程式DirBase:C7F45840r cr3是00185000, !process 4 0發現DirBase:00185000,Image:System, 可以斷定雙誤異常,原因是當雙誤發生後,CPU啟動硬體的執行緒切換機制把CR3暫存器切換到00185000,也就是系統程式所使用的頁目錄基地址。然後在新的執行緒中開始執行處理雙誤的程式碼,讓系統崩潰和儲存轉儲資訊。因為是硬體做的切換執行緒,所以作業系統沒有來得及更新當前程式。
->執行kvn發現#0號棧幀後邊有FPO: TSS 28:0這是任務門資訊,表示前一個執行緒的TSS段選擇子是0x28,.tss 28切換到崩潰的執行緒。再次定位到push ebx發生異常,由於這條指令發生異常機率很低,所以觀察上一條指令sub esp,408h這條指令更低,所以基本確認push指令引發雙無異常。
->模擬push執行過程,1.遞減指標挪出空間,ESP=ESP-4=f655cfb8-4=f655cfb4  2.將要壓入的內容寫入到挪出的空間中,執行ed f655cfb4 f655d7dc,錯誤:Memory access error in 'ed f655cfb4 f655d7dc'。dd f655cfb4得到發現??號直到f655d000,有可能這段記憶體沒有包含在轉儲檔案中,有可能記憶體沒有分配,用!pte觀察記憶體頁情況, !pte f655cfb4 得到not valid, !pte f655d000得到pfn 100e1,結果顯然是push執行時訪問了無效記憶體。
->!thread  得到Stack Init f6560000 Current f655de8c Base f6560000 Limit f655d000,邊界是f655d000,ESP(f655cfb8)顯然已經越界。在每次頁錯誤異常時,CPU會把訪問的地址寫到CR2中,r cr2得到cr2=f655cfb4 這正是ESP-4的位置。CPU執行壓棧第一步後,第二步向f655cfb4寫資料,因為無法訪問出現異常了。CR2就是一個證明,最後定位連續的程式碼 char szXXX[MAX_PATH] 造成核心態棧的溢位,x86 CPU新核心態棧初始化大小是12KB,X64是24KB 本例棧大小為. Base f6560000-Limit f655d000 = 3000 =12KB 執行k可以看出的確是用光了發生了棧溢位。


11.linux平臺下使用者態後臺程式MyDaemon與核心態驅動程式MyDriver通過驅動程式建立的虛擬檔案/sys/mydevice/vfile來通訊,發現通訊有問題,列印通訊資訊發現多出了printf除錯資訊,虛擬檔案和除錯資訊混合為一體了,導致問題的原因是MyDaemon中關閉了3個標準流,而後當它繼續執行開啟虛擬檔案時,系統複用了空閒出來的標準檔案描述符,將他們返回給應用程式,於是虛擬檔案的描述複用了標準輸出的描述符,也就是1。寫虛擬檔案時,用1描述符把資訊寫給驅動程式,當執行printf時,任按printf的邏輯找stdout指標,得到檔案描述符也是1。結果便是printf輸出的除錯資訊意外寫到了虛擬檔案中去,不一定非利用虛擬檔案與驅動檔案通訊才有問題,只要關閉了標準流,再開啟普通檔案,都可能亂套。在windows中也可以重現,因為標準流和C函式都是按工業標準實現的。


12.windows系統補丁安裝失敗,開啟事件檢視器-windows logs-Application-根據時間查詢-檢視錯誤資訊的一條顯示了安裝錯誤的記錄,按照記錄提示啟動安裝日誌,1.單擊開始,然後單擊執行。2.在開啟框中,鍵入 gpedit.msc 以啟動“組策略編輯器”。3.依次展開計算機配置、管理模板、Windows 元件,然後單擊 Windows 安裝程式。4.雙擊日誌記錄,然後單擊啟用。5.在日誌記錄框中,指定您想記錄的選項。日誌檔案 Msi.log 出現在系統卷的 Temp 資料夾中。重新執行補丁程式,沒有發現日誌檔案,上偵錯程式。
->開啟winDbg監視檔案操作,設定條件斷點 bp KERNELBASE!CreateFileW+05 "dU /c 50 poi(@ebp+8);gc"其中+05是因為CreateFileW開始的彙編程式碼是
757400d9 8bff            mov     edi,edi
757400db 55              push    ebp
757400dc 8bec            mov     ebp,esp
757400de 83e4f8          and     esp,0FFFFFFF8h
加5正好是執行了mov     ebp,esp便於後邊的取引數,dU顯示Unicode字串,/c顯示字元的單位數量50個,poi是MASM表示式支援的特殊運算子,在MASM中 @ebp+8代表一個地址,這裡是第一個引數lpFileName,要取它的值就需要使用poi操作符,poi的含義是從指定地址取指標長度的資料,分號後邊是繼續執行的指令,gc是從一個條件斷點返回,這樣一來就可以監視函式引數了。g 執行後從結果中找到臨時目錄的html檔案開啟檢視,提示說OpenFileMapping錯誤,條件斷點觀察,

bp KERNELBASE!OpenFileMappingW+5 "kv 10;dU /c 30 poi(@ebp+10)"
跟蹤無果,再看html檔案中有“Applicability for Installing: evaluating each item...(適用性:評估每一項) 應用的專案數為0”,說明補丁程式沒有修補物件。
->補丁程式判斷適用性是依據釋放出的ParameterInfo.xml,其中資訊有補丁的名稱,大小,GUID,修補物件的GUID,及其版本。
通過修補物件GUID再登錄檔中找到了對應的軟體產品是.NET Framework 4 Extended,版本好也匹配,說明是適應的,所以除錯Setup.EXE檔案,看看執行過程中出現了什麼問題。
->開啟補丁程式Setup.exe設定條件斷點 bp KERNELBASE!CreateFileW+05 "dU /c 50 poi(@ebp+8);gu;r eax;gc" 增加了gu;r eax兩條命令是為了執行完CreateFileW函式後顯示出函式返回值,從而知道成功還是失敗。記錄中發現開啟186ceccc.msi檔案失敗,.restart /f 讓目標復位,修改斷點讓其失敗就停止,

bp KERNELBASE!CreateFileW+05 "dU /c 50 poi(@ebp+8);gu;r eax;.if(@eax<0){.echo hit}.else{gc}"其中.echo hit是顯示hit字串,算是一個斷下來的提示。執行g命令,中斷後執行k 100從棧回溯中發現公開函式MsiOpenDatabase,函式的第一個引數是檔名,它的棧幀基地址是0423ed44,dU /c 50 poi(0423ed44+8)得到"C:\Windows\Installer\186ceccc.msi"正是開啟失敗的檔案,再看下MsiDeterminePatchSequence函式,它是專門用來評估補丁的應用順心的,第一個引數是目標產品的程式碼dU /c 50 poi(0423f324+8)得到的GUID正是前邊修補物件的GUID,綜上所述可以得到,補丁程式是MsiDeterminePatchSequence函式失敗,因為沒有開啟186ceccc.msi檔案.

->C:\Windows\Installer下有很多MSI檔案,是用來解除安裝和修復已安裝軟體的,在C:\Windows\Microsoft.NET\Framework64\v4.0.30319\SetupCache\Extended\中找到複本,執行後發現C:\Windows\Installer增加了MSI,再次執行補丁安裝程式正常安裝了。


13.執行Setup.exe安裝windows7 SDK過程中卡殼,WinDbg附加SDKSetup程式,因為Setup是預備程式,只是為了以管理員身份啟動SDKSetup,安裝的SDK是64位版本所以SDKSetup也是64位,WinDbg也要用64位的。檢視每個執行緒的Last Error,

~*e ? @$tid;!gle 其中~*是對每個執行緒,e是執行一系列命令,如果沒有e就只能執行最後一個命令,合起來就是針對每條執行緒顯示執行緒ID和Last Error值(相當於呼叫GetLastError() API)。結果中發現0執行緒的LastErrorValue(DosC錯誤碼)為0表示沒有錯誤,且它的LastStatusValue(NT作業系統的狀態碼)為0xc0000034表示有錯誤,這2個值都是儲存線上程TEB中的,dt _TEB -y Last 可以看到這兩個欄位,其中-y是附加搜尋選項,Last開頭的欄位。造成一對一錯的原因在於:某些API只修改了LastErrorValue不修改LastStatusValue,windows API一般是將呼叫系統服務失敗返回的NT狀態碼傳給RtlNtStatusToDosError函式,這個函式內部會將狀態碼更新到TEB的LastStatusValue欄位,然後呼叫錯誤碼轉換函式得到對應的DOS錯誤碼並返回。總的來說它最近一次呼叫API是成功的,暫時pass它尋找2個都錯誤的執行緒。發現9號執行緒都錯,切換到它~9s檢視棧回溯k 100,發現多個棧幀無法解析到任何地址結合棧中多次出現mscorwks模組,推測是及時編譯(JIT)出的託管程式碼,說明使用了.NET開發。
->多個棧幀中的函式只有二進位制地址,沒有函式名不易理解,載入用於解析託管語義的SOS擴充套件命令模組。執行

.loadby sos mscorwks,然後執行!clrstack觀察託管方法呼叫經過,通過觀察完美的回溯發現get_Length方法遇到了意外呼叫,WinIoError函式內部丟擲了異常,使用SOS的!threads命令觀察執行緒資訊,發現9號執行緒發生了System.IO.FileNotFoundException異常。檢視異常物件詳情,!do 0000000002901750 再檢視詳情中message欄位的值

!do 0000000002901570看到了這個異常的文字描述,其中的檔案路徑錯誤,以上步驟也可以直接用SOS的!printexception命令列印出當前執行緒的異常資訊。
->反彙編SDKSetup,.NET的反彙編使用ILDASM(在SDK目錄中一般為:C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin),開啟檔案,便顯示出了SDKSetup的中間程式碼,通過前邊的回溯可以判斷髮生問題的函式Dispose,其中使用到!ip2md 0x7ff`001c0dbd 讓SOS查詢這個地址對應的託管方法。通過分析得出問題是因為對異常情況的估計不足,處理錯誤邏輯不充分,造成程式流程跑飛,進入死迴圈從而卡殼。


14. 無效控制程式碼的追蹤。WinDbg載入dump檔案,k命令棧回溯發現NtGetContextThread,其它比較亂沒有函式名,當前在寫轉儲檔案的執行緒,.ecxr讀取異常資料流, 回到了異常現場,定位到RtlRaiseStatus函式,u命令反彙編該函式,發現先呼叫了RtlCaptureContext在呼叫了ZwRaiseException,說明該函式是丟擲異常錯誤狀態的函式,尋找是誰呼叫了它。
->kn 觀察棧回溯
***Stack trace for last set context - .thread/.cxr resets it
00 0`5df7f530 0`773c78e9 ntdll!RtlRaiseStatus+0x18
01 0`5df7fad0 1`40007d7a ntdll!??::FNODOBFM::'string'
02 0`5df7fb00 1`4000c09e XXModule+0x7d7a
此環境是64位的 ***行表明現在的觀察點不是最新的時間點,因為前邊執行了.ecxr而時光倒流到以前的時間點上了。因為RtlRaiseStatus不是公開函式,使用者程式碼不能太直接呼叫它,所以應該是1號呼叫的,還原1號的名稱。
->反向反彙編1號棧幀呼叫返回點 ub 00000001'40007d7a得到此地址前八條彙編指令。最近的一個條是call qword ptr [XXModule + 0x520b8(00000001'400520b8)],但是沒有函式名,ln命令通過地址(函式指標)得到最近的符號(函式名稱),ln poi(00000001'400520b8)得到函式名稱為RtlLeaveCriticalsection,可見XXModule中呼叫了該函式造成了異常。棧幀1號顯示比較混亂是因為二進位制優化造成的,優化工具將高執行概率的程式碼挪動到一起,使它們相鄰,執行時這些程式碼有更高的概率被prefetch技術預先讀入記憶體,或是因為其中的模組程式碼被執行,讓其它程式碼借光調入記憶體,執行概率低的程式碼比如用作錯誤處理的程式碼就會被流放到比邊遠地方去,優化工具只是調整程式碼不會調整符號,偵錯程式就近尋找參照物,所以棧幀1號顯示比較混亂。所有環境都還原以後,下一步就是找發生問題的原因了。
->ub 773c78e9 反向反彙編RtlRaiseStatus返回點,跟蹤發現是ZwSetEvent執行失敗造成的,它的第一個引數是控制程式碼,推測應該是該控制程式碼無效造成的,找出這個控制程式碼值,這裡是通過RCX傳值的,但呼叫動作已經過去很久,暫存器已改變,追蹤方法是:追蹤感興趣的暫存器值是否來自記憶體或向記憶體中寫過。
->RtlLeaveCriticalsection的第一個引數是_RTL_CRITICAL_SECTION結構其中成員LockSemaphore是存放關鍵區事件控制程式碼的,ub 40007d7a發現
lea rcx,[rdi+18h]推測rdi是結構體,追蹤發現rdi來之rcx其中有mov qword ptr [rsp+38h],rcx 追蹤rsp+38h 通過前邊棧回溯知道rsp為5df7fb00, dq 5df7fb00+38 l1檢視記憶體值 得到00000001`4006fbb0 觀察物件偏移18的關鍵區結構dt _RTL_CRITICAL_SECTION 000000014006fbb0+18得到LockSemaphore為460,找到控制程式碼。另一種尋找關鍵區的方法是 !cs命令列出程式中所有關鍵區,1'4006fbc8在其中,然後觀察程式裡的其它執行緒,有一個執行緒正在等待進入關鍵區,觀察它的暫存器上下文,rbx=000000014006fbc8,正是同一個關鍵區.找到無效控制程式碼,通過分析源程式及其日誌修改解決問題。


15. 系統掛死,強制系統崩潰,熱鍵觸發崩潰右Ctrl+Scroll Lock 2次,開啟熱鍵觸發崩潰 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters\ 鍵值名:CrashOnCtrlScroll 型別:REG_DWORD 值:1啟動 2禁用。強制藍屏崩潰後,產生轉儲檔案需要一會時間,當進度到100%完成就可以重啟電腦了,這時就會有dump檔案了一般路徑為:c:\Windows\Minidump,開啟轉儲檔案,!anayze -v自動分析顯示結果是固定的,因為是手工觸發的所以停止碼是固定的,kn看到PS/2鍵盤驅動觸發藍屏的過程。
->!pcr命令觀察處理器控制區,其中顯示CurrentThread: 80551d20 NextThread: 89b512e8 IdleThread: 80551d20 DpcQueue有很多工。PCR是管理CPU狀態的一段記憶體區,格式為KPCR結構,兩個記憶體頁大小8KB,X86架構上,NT會使用FS指向這個段,dg @fs顯示該段詳情,dg是顯示段的選擇子,看到基地址是ffdff000 邊界是1fff 大小正好是8KB 這種正好和!pcr看到的是一樣。!pcr的資訊顯示 CPU執行的是Idle執行緒,表示比較空閒,處於空閒迴圈中。
->切換到Idle執行緒,.thread 80551d20 執行kn通過棧回溯發現usbehci!EHCI_RH_PortResetComplete的問題,uf usbehci!EHCI_RH_PortResetComplete反彙編該函式,觀察邏輯發現CPU反覆讀寫一個硬體暫存器造成死迴圈,函式第一個引數對應了此硬體暫存器,該函式的棧幀地址是805490c4,得到硬體暫存器的線性地址dd 805490c4+8 l1得到bafde064,得到對應實體地址!vtop 0 bafde064得到實體地址b0000064,核實下是否正確!arbiter 2可以列出系統中實體地址分配情況,發現b0000064正好屬於usbehci驗證正確,至於反覆讀寫沒成功的原因在於電腦太老了,硬體有點問題了。


16. 筆記本合上休眠後喚醒失敗。熱鍵強制系統藍屏產生轉儲檔案,WinDbg開啟轉儲檔案.分析方法有兩個,方法1!pcr 0!pcr 1觀察雙核CPU控制區瞭解CPU狀態,其中一個處於IdleThread空閒中,另一個在scan32.exe中,系統掛死一般在核心態,所以方法1pass。方法2 !locks尋找核心物件死鎖,顯示3個物件,且持有者都是87474da8執行緒,!thread 87474da8觀察可疑執行緒發現屬於WinLogon程式,處於等待狀態,切換到該執行緒.thread /p 87474da8 執行kvn 100 觀察棧回溯,發現了導演睡眠過程的NtSetSystemPowerState函式,通知裝置驅動的PopSetDevicesSystemState,PopWakeDeviceList,PopNotifyDevice函式,通過這些知道這個執行緒是系統中執行睡眠任務的關鍵執行緒。將執行緒置入等待狀態的ser2pl驅動程式,得到驅動資訊!drvobj ser2pl,得到驅動物件地址86851358,裝置物件地址85163500,檢視詳情dt _DEVICE_OBJECT 85163500,觀察裝置棧!devstack 85163500,顯示所有裝置的裝置樹!devnode 0 1以上資訊可以得ser2pl是USB轉串列埠裝置的驅動程式。隨後通過!irp來觀察各個裝置驅動間的資訊傳遞,比如!irp 8761f600.最終問題在於USB轉序列口的轉接頭,處理電源事件存在問題。


17. MSN的死迴圈。CPU佔用100%有2種情況,第一種:病毒掃描程式或索引服務需要處理大量事務,第二種:程式BUG內部死迴圈。MSN屬於第二種,WinDbg附加程式。尋找死迴圈執行緒。方法有4種,方法1:如果是GUI程式,介面失去響應,一般是UI執行緒問題,通常0號執行緒就是UI執行緒。方法2:使用~*e.ttime 列出每個執行緒執行時間,根據執行時間來尋找可疑執行緒。方法3:如果執行緒不多可以用~*kv列出每個執行緒棧回溯,根據函式資訊判斷可疑執行緒。方法4:使用Process Explorer觀察工具,檢視程式各個執行緒CPU佔用率,優先檢查佔用率高的執行緒。這裡由於MSN介面失去響應所以使用方法1 ~0s
->熟悉現場的資訊,kn 100檢視棧回溯,缺少除錯符號顯示不全,只有00 0006fb045 5fc021e3 msvcr80!_vsnwprintf_s+0x19顯示正確,bp msvcr80!_vsnwprintf_s+0x19,g該恢復執行發現不斷中斷到此函式,說明此函式處於迴圈內部。顯示棧幀基地址附近資料dd 0006fb045,得到第一個引數地址01939ff5(EBP+8),dU 01939ff5出現除錯資訊,觀察更多資訊bp msvcr80!_vsnwprintf_s+0x19 "dU poi(@ebp+8);kv 3;gc"命令表示條件中斷到偵錯程式後執行列印引數1,顯示3個棧幀的棧回溯,然後恢復執行。執行後出現大量資訊,ctrl+break中斷到偵錯程式。
->定位死迴圈的函式,方法有2種,方法1:對棧回溯中每個棧幀返回點由上到下依次設定斷點,如果反覆命中說明此函式可以返回上一級,不是問題所在解除此斷點,對下一個棧幀返回地址設定斷點,如此重複直到設定斷點恢復執行後程式出現死迴圈,說明死迴圈放生在當前函式中。方法2:選取2次棧回溯,從下至上比較最後一列,最後一個相同的地址代表可能是死迴圈所在函式,對其設斷用方法1判斷,如果不是再次取樣比較。選用方法2,發現最後一個相同點是CreateObjectStoreService+0x14969
,設定斷點對其返回再設一個斷點,bp LiveTransport!CreateObjectStoreService+0x14969,bp LiveTransport!CreateObjectStoreService+0x14c24
發現始終命中0x14969返回點0x14c24不命中,說明死迴圈發生在0x14969所在的函式中,反向反彙編0x14c24, ub LiveTransport!CreateObjectStoreService+0x14c24得到 call LiveTransport!CreateObjectStoreService+0x145ad(5f342ff1),由於缺少除錯符號顯示的符號資訊是就近的,是不準確的,所以死迴圈函式是5f342ff1,不知道名稱。接下來就是分析程式碼。
->入口指令sub esp,2Ch推斷區域性變數區長度0x2c即44位元組,根據"EBP-n"索引區域性變數原則,發現指令中有ebp-4,ebp-14,ebp-2c共3種寫法,推斷第一變數長度是4位元組可能是整數或指標,後兩個分別是16位元組,24位元組可能是結構體。根據"EBP+n"索引引數的規律,找到ebp+8所以此函式只有一個引數,觀察ECX的使用,推測是C++類的方法,ECX中傳遞this指標。手動跟蹤可以發現死迴圈點
5f3430b5 call LiveTransport!CreateObjectStoreService+0x32e11(5f361555)
5f3430ba cmp  dword ptr [ebp-4],0
5f3430be jne  LiveTransport!CreateObjectStoreService+0x148e0(5f343024)
5f3430c4 push 0Ah
呼叫函式,比較區域性變數,條件跳轉,並沒有用到函式的返回結果,懷疑是否應該把返回值賦值給區域性變數再比較呢?漏洩了程式碼?追蹤區域性變數。
->從棧回溯中得到這個棧幀基地址是0006fc78 所以ebp-4是0006fc74,ba w4 0006fc74其中ba是記憶體斷點,當對0006fc74到(0006fc74+4)地址寫操作時斷下,bd禁止其它斷點然後恢復MSN執行,斷下後分析函式發現,死迴圈沒對EBP-4區域性變數賦值,它的子函式賦值的,解除了先前的疑問。模擬執行觀察下情況,執行recx=poi(ecx);r ecx;z(ecx!=0)迴圈命令,其含義是把ecx所在地址的值賦給ecx,顯示ecx,反覆操作直到ecx為0。執行後發現不停迴圈,ctrl+break停止。修復死迴圈,方法有2種,方法1:修正資料,讓迴圈自然結束,方法2:修改EIP跳出迴圈,這裡使用方法2,be命令恢復前面的斷點,恢復執行,斷下後單步來到jne修改EIP,R eip=5f3430c4到下一條指令跳出迴圈執行g,MSN繼續執行正常了。


18.OneNote程式滿負荷佔用一個CPU,推斷死迴圈。附加程式,定位死迴圈執行緒,執行~*e ? @$tid;.ttime顯示每個執行緒的ID和執行時間,觀察可知執行緒0X18e4就是可疑執行緒,切換到這個執行緒,~~[18e4]s, 其中~~[n]s是切換到執行緒ID為n的執行緒,k觀察棧回溯,發現這個執行緒主要執行在msxml3這個模組中,檢視詳情lm vm msxml3,然後深入程式碼邏輯,一般先確定迴圈範圍,可以用上章的棧回溯比較法(對於函式呼叫層次很多的情況),也可以用簡單的單步跟蹤法(對於函式呼叫層次比較少的),此例用單步跟蹤,經過跟蹤發現是RemonveAdd方法的問題,此函式原理是:多工下載一個任務失敗將從頭移到尾,嘗試其它任務下載,其它結束再嘗試下載它,是一個很好的設計,但如果只有一個任務且下載失敗就會造成死迴圈了。


19.windows核心除錯連線方式,最早是串列埠,XP增加了1394,VISTA增加了USB2.0,前邊三種多少有各自難處,win8增加了網路除錯和USB3.0。
win8網路除錯KDNET的配置步驟:
第一步,將目標機和主機都連線到同一個乙太網路,為了讓目標機端能連線到主機端(可以用ping測試),然後記錄下主機端IP地址。
第二步,在目標機端以管理員身份啟動一個控制檯視窗,執行如下命令:
    bcdedit /dbgsettings net hostip:192.168.1.100 port:50000 key:a.b.c.d
    bcdedit -debug on

    hostip對應的是主機IP,port是埠,key是密碼.
    有多個網路卡的情況下,需要指定網路卡:
    bcdedit /set {dbgsettings} busparams 11.0.0
    其中 11.0.0分別是匯流排號,裝置號,功能號,在裝置管理器的網路卡裝置屬性裡可以查到。如果是VM虛擬機器不需要指定此項.
    設定完以後可以用 bcdedit /enum {dbgsettings}來檢視設定是否正確
    如果要刪除busparams的設定可以執行 bcdedit /deletevalue {dbgsetttings} busparams
第三步,主機端使用新版WinDbg->Kernel Debug->NET填入資訊確定後進入等待狀態。
主機端就緒後,重啟目標機的win8,片刻之後就連線成功。測試得到如果VM虛擬機器是win8 64位時不能連線成功,32位連線正常。
win8 USB3除錯KDUSB3的配置方法:
bcdedit /dbgsettings usb targetname:<目標名稱>
bcdedit /set dbgtransport kdusb3.dll
kbcedit /debug on

如果要刪除dbgtransport設定,可以執行bcdedit /deletevalue dbgtransport
其中目標名稱對應的Windbg中Kernel Debug->USB的targetname
除了手工配置也可以通過VS來自動配置,開啟VS2012->Drivers->Test->Configure Computers來執行配置嚮導。


22.除錯.net託管程式可以使用WinDbg的SOS擴充套件模組,.net版本與SOS模組是對應的必須相匹配。方法1例如 .Net Framework 4.0程式 執行.load C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll 進行載入,相應的不同版本路徑也不一樣。方法2,.loadby sos mscorwks意思是載入與mscorwks模組相同位置的sos擴充套件模組,其中 mscorwks是不一定的,可以通過lmv來確定具體就是發現模組路徑是.NET路徑就可以,比如mscoreei也可以。載入後可以用.chain來觀察已經載入的擴充套件模組,可以用!help顯示SOS的幫助資訊,在後邊加命令得到此命令詳細解釋。當被除錯程式載入了CLR執行時後,SOS才能工作和有意義,所以制定WinDbg模組載入事件,sxe ld mscorwks.dll含義是讓WinDbg收到被除錯程式載入mscorwks.dll模組事件時中斷下來,然後就可以執行.loadby sos mscorwks了,可以把2個命令合起來執行,sxc -c ".loadby sos mscorwks;g" ld mscorwks.dll含義是收到載入mscorwks.dll事件後執行-c後邊的命令。
->SOS中的BPMD命令可以針對託管程式碼設定斷點有2種格式,方法1 !bpmd <module name> <method name>例如!bpmd CliHello CliHello.CliHello.Main 這是對ClieHello模組中的CliHello名稱空間的CliHello類的Main方法設定斷點,模組名不分大小寫,名稱空間類名方法名嚴格區分大小寫。方法2!bpmd -md <MethodDesc> 這種形式需要知道MethodDesc結構地址,這個地址可以通過!name2ee命令來得到。!name2ee clihello CliHello.CliHello.Main 得到MethodDesc:00a73020 再執行!bpmd -md 00a73020。另外還可以使用名為SOSEX的擴充套件模組來設定斷點如 !mbp Program.cs 11,這個模組可以從網上下載,複製到winext目錄後用.load載入。


25.CSRSS程式的雙機使用者態除錯(NTSD+WinDbg).
->1.修改windows的全域性標誌啟用對CSRSS的除錯,使用WinDbg目錄下的Gflags工具,勾選“Enable debugging of Win32 subsystem”,重啟系統生效。
->2.建立雙機使用者態除錯,原理是目標機NTSD主機端WinDbg通訊,類似於雙機核心除錯模型。首先建立雙機核心除錯。
->3.附加到CSRSS,目標機啟動管理員許可權的控制檯視窗執行ntsd -d -g -G -o -pd -p <CSRSS 程式ID> 其中-d表示將輸入輸出(通過DbgPrint)定向到核心除錯會話,-g表示忽略被除錯程式的初始化斷點,如果不加此開關,NTSD附加到CSRSS程式後,遠端中斷執行緒觸發的斷點異常會立刻讓CSRSS中斷下來,-G表示忽略程式終止時的最後一個斷點,-o表示除錯被除錯程式啟動的子程式,=pd表示除錯會話結束時自動與CSRSS分離,不然的話CSRSS會終止,系統會崩潰,-p用來指定CSRSS的程式ID。上面命令過於繁瑣,NTSD專門為除錯CSRSS提供了簡化命令NTSD --效果和上一樣。執行成功目標機沒有任何提示,工作管理員中可以看到ntsd.exe程式,主端機中有載入CSRSS的提示。工作管理員中CSRSS的程式有2個任意選擇一個,測試上2個命令都會在30秒後自動斷到主機端的WinDbg,且顯示(first chance)。測試-g選項沒什麼用,無論新增與否都會在30秒後自動中斷,測試環境是win8+VM win7估計是windows升級更方便除錯了。
->4.中斷到NTSD,有兩種情況,第一種由於設定了-g選項忽略初始化斷點,附加成功後,CSRSS不會中斷到偵錯程式,可以使用WinDbg工具包中的breakin小工具,用法是breakin <CSRSS 程式ID>第二種在執行了第三步以後主端機會顯示“Break-in sent, waiting 30 seconds...”
意思是30秒以後自動中斷,這樣就方便的中斷到了NTSD。中斷後在主機端資訊會出現“(1ac.1e0): Wake debugger - code 80000007 (first chance)” 其中1ac就是目標機的CSRSS程式ID的十六進位制,這個可以通過目標機任務管理檢視確定。此時主機端命令提示符號是"Input>"這表示為第三方接收輸入,這也說明了此時輸入的命令都是轉到NTSD中執行了。
->5.設定符號檔案,NTSD要求符號檔案放在目標機本地,如果目標機沒有符號檔案,可以從主端機拷貝WINSRV CSRSS CSRSRV到目標機(比如c:\symbols路徑),設定符號路徑.sympath c:\symbols,反覆測試發現如果不設定有效的符號檔案路徑執行k或者~*就會出現卡死情況,設定正確後就沒有這個問題了。
->6.最後是關閉除錯,NTSD是不帶GUI介面的,WinDbg是帶介面的,離開命令都是q,執行後友好顯示"q quit:" 這時目標機恢復執行了,再看看工作管理員ntsd.exe程式沒有了整個過程結束。


更新中。。。

相關文章