Ci eravamo lasciati in questa situazione: Windbg avviato as admin, la VM configurata per il kernel debugging su seriale, ma spenta.
Se non lo siamo, chiudiamo tutto ed eseguiamo questi passi nell’ordine esatto.
Avviamo Windbg “As Administrator”. Verifichiamo che Symbol Path contenga il percorso corretto al nostro symbol store e il riferimento al server pubblico Microsoft, e andiamo a selezionare Kernel Debugger. Controlliamo che il tab COM sia configurato per collegarsi alla pipe creata, che "Reconnect” sia spuntato e premiamo “OK”.
Apparirà questo messaggio all’interno della finestra Command del debugger:
Microsoft (R) Windows Debugger Version 6.11.0002.408 X86Copyright (c) Microsoft Corporation. All rights reserved. Opened \\.\pipe\VistaDebugWaiting to reconnect...
Il debugger è pronto in attesa che sulla pipe arrivino le informazioni dalla macchina target.
Avviamo ora la VM.
Dopo qualche istante, il sistema inizierà a mandare delle informazioni in output:
Connected to Windows Server 2008/Windows Vista 6002 x86 compatible target at (Wed Dec 16 14:23:06.947 2009 (UTC + 1:00)), ptr64 FALSEKernel Debugger connection established.Symbol search path is: D:\Symbols;srv*D:\Symbols*\\symbols\symbolsExecutable search path is: Windows Server 2008/Windows Vista Kernel Version 6002 MP (1 procs) Free x86 compatibleBuilt by: 6002.18082.x86fre.vistasp2_gdr.090803-2339Machine Name:Kernel base = 0x81a49000 PsLoadedModuleList = 0x81b60c70System Uptime: not available
XP si metteva subito in BreakPoint, ho notato che Vista non lo fa. Almeno, nel mio caso, ha raggiunto la schermata iniziale e ho dovuto premere io il pulsante “Break” sulla toolbar per poter vedere questo mesaggio:
Break instruction exception - code 80000003 (first chance)******************************************************************************** ** You are seeing this message because you pressed either ** CTRL+C (if you run kd.exe) or, ** CTRL+BREAK (if you run WinDBG), ** on your debugger machine's keyboard. ** ** THIS IS NOT A BUG OR A SYSTEM CRASH ** ** If you did not intend to break into the debugger, press the "g" key, then ** press the "Enter" key now. This message might immediately reappear. If it ** does, press "g" and "Enter" again. ** ********************************************************************************nt!RtlpBreakWithStatusInstruction:81af4a98 cc int 3
Questo messaggio è la conferma che il sistema è sotto Kernel Debugger.
Giusto per sicurezza, verifichiamo che il debugger risponda ai comandi, usando il comando “vertarget”:
kd> vertargetWindows Server 2008/Windows Vista Kernel Version 6002 (Service Pack 2) MP (1 procs) Free x86 compatibleBuilt by: 6002.18082.x86fre.vistasp2_gdr.090803-2339Machine Name: "MRRVISTALAB"Kernel base = 0x81a49000 PsLoadedModuleList = 0x81b60c70Debug session time: Wed Dec 16 14:24:28.961 2009 (UTC + 1:00)System Uptime: 0 days 0:01:06.051
E’ tutto a posto. la macchina virtuale è sotto Kernel Debugger e il debugger riesce ad esaminare il target. Abbiamo accesso completo al kernel del sistema operativo.
A questo punto, la macchina virtuale è bloccata dal debugger. Dobbiamo farla ripartire e collegarci alla stessa premendo CTRL+ALT+CANC ed eseguire il logon.
Per farla ripartire, si preme il pulsanto “GO” sulla toolbar o F5 o si digita “g” sul prompt dei comandi in windbg.
A questo punto siamo pronti per avviare l’applicazione che vogliamo debuggare, o per riprodurre il problema che stiamo cercando di risolvere, come era nel mio caso.
Avviamo l’applicazione che vogliamo debuggare, ad esempio Notepad, e poi interrompiamo la macchina virtuale, premendo il pulsante Break
Dobbiamo eseguire una serie di comandi che ci permetteranno di entrare nel contesto del processo che vogliamo debuggare, perchè ricordiamoci che in Kernel, la memoria è condivisa, e tutti i thread di tutti i processi in esecuzione sono a disposizione, ma noi abbiamo bisogno solo dei thread relativi alla nostra applicazione.
1) troviamo il processo che ci interessa. Eseguiamo il comando
!process 0 0
ed esaminiamo l’output, finchè troviamo il nostro processo (di solito è l’ultimo).
kd> !process 0 0**** NT ACTIVE PROCESS DUMP ****PROCESS 87e90a70 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000 DirBase: 00122000 ObjectTable: 8b400058 HandleCount: 601. Image: SystemPROCESS 89c5a2d0 SessionId: none Cid: 01c0 Peb: 7ffdc000 ParentCid: 0004 DirBase: 3de18020 ObjectTable: 8b463a28 HandleCount: 28. Image: smss.exe...PROCESS 8855fb78 SessionId: 1 Cid: 03dc Peb: 7ffdf000 ParentCid: 0420 DirBase: 3de181a0 ObjectTable: a030c6f0 HandleCount: 48. Image: notepad.exe
2) ci mettiamo nel contesto del processo con questo comando
.process /i <process>
dove <process> nel nostro caso vale 8855fb78, quindi il comando reale sarà:
kd> .process /i 8855fb78You need to continue execution (press 'g' <enter>) for the contextto be switched. When the debugger breaks in again, you will be inthe new process context.
3) come dice il messaggio ritornato dal comando, dovete premere “g”, “Go” per poter effettivamente switchare nel contesto del processo:
kd> gBreak instruction exception - code 80000003 (first chance)nt!RtlpBreakWithStatusInstruction:81af4a98 cc int 3
Adesso siamo effettivamente nel processo che ci interessa.
4) un ulteriore variante del comando .process ci assicurerà di essere nel posto giusto, e caricherà i simboli del processo user mode.
.process /p /r <process>
kd> .process /p /r 8855fb78Implicit process is now 8855fb78.cache forcedecodeuser doneLoading User Symbols....................
5) i simboli di debug, come non smetterò mai di ripetere, sono fondamentali. E’ sempre buona norma essere certi che i simboli siano disponibili e caricati. Per cui, anche se non è strettamente necessario, visto che il comando precedente li ha caricati, è buona norma forzare il reload degli stessi.
.reload /user
kd> .reload /userLoading User Symbols....................
Nel caso siate collegati ad internet, a questo punto potrebbe impiegare qualche minuto a scaricare i simboli dal server pubblico Microsoft. Attendete pazientemente.. un caffè può aiutare in questi casi
6) impostate i breakpoint che dovete impostare nella vostra applicazione e che volete seguire poi in kernel mode. Giusto per test, la CreateFile è una di quelle funzioni base, che viene chiamata spesso e volentieri anche solo per verificare la security applicata ad un file o se il file esiste prima di crearlo, e sicuramente switcha in Kernel mode, dove le sue controparti potranno a questo punto essere esaminate. Attenzione che siccome questa funzione viene richiamata spessimssimo potrebbe accadere che vi troviate fuori dal vostro processo, e a quel punto dovrete ripartire da capo risincronizzandovi col processo che volete debuggare. Windows è multitasking, quindi purtroppo questa cosa non si può evitare..
BP è il comando per impostare un BreakPoint. Quindi ad esempio:
bp Kernel32!CreateFileW
kd> bp kernel32!createfilew
Oppure, si può impostare un breakpoint globale, su una funzione che verrà chiamata da qualunque processo:
Ad esempio, se imposto un BreakPoint su NtCreateUserProcess, e poi da Start, Run, scrivo Notepad, per avviare una istanza di Notepad, e premo OK, prima o poi arriverò alla NtCreateUserProcess
Se controlliamo lo stack a questo punto possiamo vedere come siamo arrivati qui:
kd> kL200ChildEBP RetAddr 05a3d680 774d5c20 ntdll!NtCreateUserProcess05a3dc94 774b1c1f kernel32!CreateProcessInternalW+0xf8505a3dccc 763becc6 kernel32!CreateProcessW+0x2c05a3ddc4 763bdd50 SHELL32!_SHCreateProcess+0x25405a3de18 763beaa3 SHELL32!CExecuteApplication::_CreateProcess+0xfe05a3de28 763bea5a SHELL32!CExecuteApplication::_TryCreateProcess+0x2e05a3de38 763bddd8 SHELL32!CExecuteApplication::_DoApplication+0x4805a3de48 763be0ab SHELL32!CExecuteApplication::Execute+0x3305a3de68 763bd981 SHELL32!CExecuteAssociation::_DoCommand+0x7005a3de88 763bdb0b SHELL32!CExecuteAssociation::_TryApplication+0x3e05a3dea0 76372fbd SHELL32!CExecuteAssociation::Execute+0x3005a3dec0 76372f34 SHELL32!CAssocMenu::_Execute+0x4c05a3e130 76372e0e SHELL32!CAssocMenu::InvokeCommand+0x9d05a3e1a0 76372d45 SHELL32!HDXA_LetHandlerProcessCommandEx+0xbf05a3e43c 76451e3d SHELL32!CDefFolderMenu::InvokeCommand+0x1e305a3e4a8 76451d71 SHELL32!CShellExecute::_InvokeInProcExec+0xb905a3e4c4 76451d1c SHELL32!CShellExecute::_InvokeCtxMenu+0x3905a3e4dc 763c1ac6 SHELL32!CShellExecute::_DoExecute+0x5a05a3e4f0 763bc1ea SHELL32!CShellExecute::ExecuteNormal+0x8705a3e504 763bc177 SHELL32!ShellExecuteNormal+0x3305a3e51c 7640db74 SHELL32!ShellExecuteExW+0x6205a3e790 7640d9a9 SHELL32!ShellExecCmdLine+0x1aa05a3ec58 7640dcd4 SHELL32!CRunDlg::OKPushed+0x16905a3ecb0 77a2fd72 SHELL32!RunDlgProc+0x16205a3ecdc 77a249a9 USER32!InternalCallWinProc+0x2305a3ed58 77a2481f USER32!UserCallDlgProcCheckWow+0x13205a3eda0 77a24a33 USER32!DefDlgProcWorker+0xa805a3edbc 77a2fd72 USER32!DefDlgProcW+0x2205a3ede8 77a2fe4a USER32!InternalCallWinProc+0x2305a3ee60 77a30943 USER32!UserCallWinProcCheckWow+0x14b05a3eea0 77a30b36 USER32!SendMessageWorker+0x4b705a3eec0 74c4b4b2 USER32!SendMessageW+0x7c05a3eee0 74c4b514 COMCTL32!Button_NotifyParent+0x3d05a3eefc 74c4b61f COMCTL32!Button_ReleaseCapture+0x11205a3ef5c 77a2fd72 COMCTL32!Button_WndProc+0xa9805a3ef88 77a2fe4a USER32!InternalCallWinProc+0x2305a3f000 77a3018d USER32!UserCallWinProcCheckWow+0x14b05a3f064 77a3022b USER32!DispatchMessageWorker+0x32205a3f074 77a251f5 USER32!DispatchMessageW+0xf05a3f098 77a43bc5 USER32!IsDialogMessageW+0x58605a3f0d4 77a42dc0 USER32!DialogBox2+0x14305a3f0fc 77a42eec USER32!InternalDialogBox+0xd005a3f11c 77a410ef USER32!DialogBoxIndirectParamAorW+0x3705a3f140 7640d747 USER32!DialogBoxParamW+0x3f05a3f164 7640d680 SHELL32!SHFusionDialogBoxParam+0x3205a3f1a0 00c44602 SHELL32!RunFileDlg+0xe8WARNING: Frame IP not in any known module. Following frames may be wrong.05a3f7e0 00c4442f 0xc4460205a3fc84 7726c2c9 0xc4442f05a3fd08 774fd0e9 SHLWAPI!WrapperThreadProc+0x11c05a3fd14 778919bb kernel32!BaseThreadInitThunk+0xe05a3fd54 7789198e ntdll!__RtlUserThreadStart+0x2305a3fd6c 00000000 ntdll!_RtlUserThreadStart+0x1b
Senza simboli privati o se non state creando un device driver, è difficile che il Kernel Debugging vi possa interessare, ma potrebbe capitare che vi venga qualche curiosità da soddisfare, e seguendo i passi che vi ho mostrato riuscirete a iniziare un Kerne Debugging con successo.
Vi lascio con un link molto utile: 148660 How to Verify Windows Debug Symbols http://support.microsoft.com/default.aspx?scid=kb;EN-US;148660
Alla prossima!
Mario Raccagni Senior Support Engineer Platform Development Support Team