0

I'm trying to debug Windows XP's kernel with KD but every time I start the debugger,it seem to crash.

Setup

Windows 10 (host machine,running kd)

Windows XP x86 SP3 VM (being debugged)

  • I configured a serial port with the following parameters:
    • Edited boot.ini on the target OS
    • (on VMware) Use named pipe \\.\pipe\com_1
    • This end is the server
    • The other end is an application

When I try to connect to my VM I use:
kd -y srv*c:\symbols*https://msdl.microsoft.com/download/symbols -k com:port=\\.\pipe\com_1,pipe

After which I get this output:

Copyright (c) Microsoft Corporation. All rights reserved.

Opened \\.\pipe\com_1
Kernel Debug Target Status: [no_debuggee]; Retries: [0] times in last [7] seconds.
Waiting to reconnect...
Unable to read head of debugger data list, Win32 error 0n56
Connected to Windows XP 2600 x86 compatible target at (Mon Oct 24 20:21:44.286 2016 (UTC + 2:00)), ptr64 FALSE
Kernel Debugger connection established.

************* Symbol Path validation summary **************
Response                         Time (ms)     Location
Deferred                                       srv*c:\symbols*https://msdl.microsoft.com/download/symbols
Deferred                                       srv*c:symbols*http://msdl.microsoft.com/download/symbols
Symbol search path is: srv*c:\symbols*https://msdl.microsoft.com/download/symbols;srv*c:symbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
Windows XP Kernel Version 2600 UP Free x86 compatible
Built by: 2600.xpsp_sp3_qfe.130704-0421
Machine Name:
Kernel base = 0x804d7000 PsLoadedModuleList = 0x805541c0
System Uptime: not available
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   52: ERROR: UMRxReadDWORDFromTheRegistry/ZwQueryValueKey: NtStatus = c0000034
ERROR: DavReadRegistryValues/RegQueryValueExW(4). WStatus = 127
ERROR: DavReadRegistryValues/RegQueryValueExW(5). WStatus = 127
ERROR: DavReadRegistryValues/RegQueryValueExW(6). WStatus = 127
watchdog!WdUpdateRecoveryState: Recovery enabled.
Break instruction exception - code 80000003 (first chance)
*******************************************************************************
*                                                                             *
*   You are seeing this message because you pressed either                    *
*       CTRL+C (if you run console kernel debugger) or,                       *
*       CTRL+BREAK (if you run GUI kernel debugger),                          *
*   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+0x50d2c:
80527d2c cc              int     3
kd>

Problems

  • According to what I found searching around it is correct that the OS freezes as it is in debug mode. Can I actually run and stop it's execution later with breakpoints and such (I know breakpoints can be placed,but I don't know how to execute kernel code)?
  • Also, I'm trying to decompile some routines, and I would like to know if there is any command that allows me to know whether arguments are required by the function.
  • Trying to use the following variable types in KD doesn't work (I guess they're not symbols). What can I do if I want to see the fields in these structures ?

    NTKERNELAPI VOID KeInitializeApc (
    
    IN PRKAPC Apc,
    
    IN PKTHREAD Thread,
    
    IN KAPC_ENVIRONMENT Environment,
    
    IN PKKERNEL_ROUTINE KernelRoutine,
    
    IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL,
    
    IN PKNORMAL_ROUTINE NormalRoutine OPTIONAL,
    
    IN KPROCESSOR_MODE ApcMode,
    
    IN PVOID NormalContext
    
    );
    

EDIT 1: whatever I had with 'g' is gone,and I can run the XP VM.

2
  • Trying to use the following variable types in KD doesn't work - how are you using it? What are you trying to do? Apart from that - have you considered using other debuggers, such as WinDbg? It has a GUI and is much more friendly to beginners.
    – Martin
    Oct 24, 2016 at 21:33
  • I.E: kd > dt PKKERNEL_ROUTINE
    – shxdow
    Oct 25, 2016 at 5:01

1 Answer 1

1

but every time I start the debugger,it seem to crash.

and

According to what I found searching around it is correct that the OS freezes as it is in debug mode.

Exactly. It's not crashing, it's only putting a breakpoint at system level:

*******************************************************************************
*                                                                             *
*   You are seeing this message because you pressed either                    *
*       CTRL+C (if you run console kernel debugger) or,                       *
*       CTRL+BREAK (if you run GUI kernel debugger),                          *
*   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.                                          *
*                                                                             *
*******************************************************************************

Simply press g then Enter. Do it again if it doesn't work, and it should run properly. Press Ctrl+C (for kd) or Ctrl+Break (for windbg) to break (i.e. "pause" the system) again.


Also, I'm trying to decompile some routines, and I would like to know if there is any command that allows me to know whether arguments are required by the function.

You need to load the symbols for the module you're going to debug. To do so, you have a few handy commands:

  • .symfix - Fix symbol path

    • This command sets the symbol path to point to the Microsoft symbol store, i.e. makes your debugger download necessary symbols when needed.
  • .reload - the Reload Module

    • This is the command you will use to load symbols for the module you're interested in. If you were interested in e.g. sysaudio.sys, you'd run the command .reload /f sysaudio.sys - where the /f flag makes the command immediately load the symbols. For your example, KeInitializeApc, you'd need to reload nt. I explain how I found it below.
  • lm - List Loaded Modules

    • This will show the currently loaded modules. Useful for finding the base address of the module you're interested in (for example, sysaudio.sys)

To find KeInitializeApc, you would need to use the x command, like this:

0: kd> x *!KeInitializeAPC
82aebdf3          nt!KeInitializeApc (<no parameter info>)

As you can see, the command shows us the offset of the function (you'll use it later with u), its module (nt), and its full, correct name (nt!KeInitializeApc).

The x command looks like:

x module!symbol

You can use wildcards like in my example above, specify options, etc. More info about the command in MSDN.

TL;DR

To find KeInitializeApc, you'd do:

kd> .symfix # make the debugger download symbols it needs
kd> .reload # reload symbols NOW
kd> x *!KeInitializeAPC # find desired function
82aebdf3          nt!KeInitializeApc (<no parameter info>)
kd> u 82aebdf3 # unassemble (disassemble)
nt!KeInitializeApc:
82aebdf3 8bff            mov     edi,edi
82aebdf5 55              push    ebp
82aebdf6 8bec            mov     ebp,esp
82aebdf8 8b4508          mov     eax,dword ptr [ebp+8]
82aebdfb 8b5510          mov     edx,dword ptr [ebp+10h]
82aebdfe 8b4d0c          mov     ecx,dword ptr [ebp+0Ch]
82aebe01 c60012          mov     byte ptr [eax],12h
82aebe04 c6400230        mov     byte ptr [eax+2],30h

From there, the decompilation is up to you. You now have the disassembly. I used the u command, which means unassemble. You can also use uf (unassemble function) to get a more function-friendly output, like this:

kd> uf 82aebdf3 # unassemble function
nt!KeInitializeApc:
82aebdf3 8bff            mov     edi,edi
82aebdf5 55              push    ebp
82aebdf6 8bec            mov     ebp,esp
82aebdf8 8b4508          mov     eax,dword ptr [ebp+8]
82aebdfb 8b5510          mov     edx,dword ptr [ebp+10h]
82aebdfe 8b4d0c          mov     ecx,dword ptr [ebp+0Ch]
82aebe01 c60012          mov     byte ptr [eax],12h
82aebe04 c6400230        mov     byte ptr [eax+2],30h
82aebe08 83fa02          cmp     edx,2
82aebe0b 7506            jne     nt!KeInitializeApc+0x20 (82aebe13)  Branch

nt!KeInitializeApc+0x1a:
82aebe0d 8a9134010000    mov     dl,byte ptr [ecx+134h]

nt!KeInitializeApc+0x20:
82aebe13 894808          mov     dword ptr [eax+8],ecx
...

Edit

The part regarding parameters is exactly what I'm looking for

I dumped the PDBs and found no parameter info, so I'd guess that Microsoft simply didn't release it.

Here's what I did:

  1. Find the file where KeInitializeApc is:

    kd> x *!KeInitializeApc
    82abbdf3          nt!KeInitializeApc (<no parameter info>)
    kd> !address 82abbdf3
    ...
    ...
    Module name:            ntoskrnl.exe
    Module path:            [\SystemRoot\system32\ntkrnlpa.exe]
    
  2. Download the symbols for ntoskrnl:

    cmd> symchk /v C:\windows\system32\ntoskrnl.exe
    ...
    ...
    PdbFilename         C:\Windows\SYMBOLS\ntkrnlmp.pdb\9E22A5947A15489895CE716436B45BE02\ntkrnlmp.pdb
    ...
    

(you can find symchk.exe in the same folder as windbg.exe)

  1. Use Microsoft's cvdump tool to dump the PDB into a text file:

    cmd> cvdump C:\Windows\SYMBOLS\ntkrnlmp.pdb\9E22A5947A15489895CE716436B45BE02\ntkrnlmp.pdb > out
    
  2. Open the file and search for KeInitializeAPC. One hit:

    S_PUB32: [0001:00071654], Flags: 00000002, KeInitializeApc
    
  3. Search for KeInitializeApc again (no results), or its ID (I guess?), [0001:00071654] -> 71654. One result:

      *** SECTION CONTRIBUTIONS
    
      Imod  Address        Size      Characteristics
      01B9  0001:00071654  00000098  60303020
    
  4. Dump PDB types with cvdump -t

  5. No type info available for 01B9

Additionally, I downloaded checked symbols (they supposedly have more information in them) and repeated the process for those, but couldn't find anything either.


And after pressing "g" nothing happens,for a while, to the point that I decide to break again. Is it supposed to take long ?

When you press g, you're basically telling the debugger to run the OS. Whenever it is running, the debugger can't do anything but wait until it breaks. Since the OS is running normally, it will not stop until you manually break. Therefore, you have to break before inputting any command.


kd > dt PKKERNEL_ROUTINE

Apparently, there aren't any Ke* symbols:

kd> dt nt*!Ke*                             # nothing here
kd> dt nt!LIST_ENTRY*                     # Symbols are working properly,
          ntkrpamp!LIST_ENTRY64           # because this works
          ntkrpamp!LIST_ENTRY32
kd> dt nt!LIST_ENTRY64                    # dt works properly. Therefore,
   +0x000 Flink            : Uint8B       # Ke* doesn't have any symbols
   +0x008 Blink            : Uint8B

You'll have to reverse the code yourself and name the params, or find them somewhere in the internet, because apparently they aren't in the PDBs.

3
  • 82aebdf3 nt!KeInitializeApc (<no parameter info>). The part regarding parameters is exactly what I'm looking for. And after pressing "g" nothing happens,for a while, to the point that I decide to break again. Is it supposed to take long ?
    – shxdow
    Oct 25, 2016 at 5:06
  • UPDATE: what ever I had with 'g' is now gone,and I can successfully run the debugged OS.
    – shxdow
    Oct 25, 2016 at 19:04
  • @shxdow I made an edit, please see if that answers your question.
    – Martin
    Oct 25, 2016 at 20:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.