I have started the Windows kernel hacking section with a simple explaination of the setup and a quick analysis of the crackme, that we analysed here, using the kd.exe kernel debugger.
I chose to do this instead of any actual Windows kernel stuff because its a steep learning experience learning how to use KD so its probably best to look at something you have already seen.
Setting Up The Environment
For this post I will be using a total of 4 machines, 3 virtual machines using VMware Player (you probably could use Virtualbox for this also though) hosted on a reasonably powerful machine and a laptop.
You can however do all of this with just 1 physical machine, hosting 1 virtual machine and I will explain the differences in the setup afterwards but I'll first explain the setup I am using.
Here is a visual representation of the network:
So I have 3 virtual machines on my machine running VMware Player:
1 Kali Linux, 1 Windows XP Professional and 1 Windows 7 Home Edition. All 3 of these are 32bit, although it doesn't matter but to follow along you would probably want the debuggee (the Windows 7 machine in my setup) to be 32bit. In my 2 machine setup described below the host (and debugger) is a Windows 7 64bit machine.
The Kali machine has 2 network interfaces, 1 setup in Bridged mode (so that I can SSH directly to it):
And the other setup in Host-only mode (So that it has access to the other 2 machines):
The Windows XP machine has 1 network interface setup in Host-only mode:
And the same for the Windows 7 machine:
The Windows XP and Windows 7 machines are also connected via a virtual serial cable, this is for the debugger connection.
The Windows XP machine will be the client (or the debugger):
And the Windows 7 machine will be the server (or the debuggee):
The Windows 7 machine needs both Visual Studio Express 2013 for Windows Desktop and the Windows Driver Kit (WDK) installed on it. You can get them both here.
The Windows XP machine needs Microsoft Windows SDK for Windows 7 installed, which you can get here. To install this you need to install the full version of Microsoft .NET Framework 4, which you can get here (Bare in mind that you might need an internet connection while you install these so just change the network adaptor configuration to NAT and then once it is installed change it back to Host-only again).
If the debugger is a Windows 7 machine then you will need to install the same software as on the debuggee.
Once these are installed, its best to add the path to the kd.exe application to the PATH variable.
You do this by going in to the properties of My Computer and, on Windows 7 going to Advanced system settings->Environment Variables... or on Windows XP going to Advanced->Environment Variables... and scroll down the Path and click Edit.
The path on Windows 7 should be something like C:\Program Files\Windows Kits\8.1\Debuggers\x86 and on Windows XP C:\Program Files\Debugging Tools for Windows (x86).
For remote administration I've installed TightVNC on both of the Windows machines.
I set it up with access through a Kali machine so that I can setup SSH tunnels and get VNC access to the Windows machines without giving them access to the outside network.
After TightVNC is up and running on your Windows machines, you can setup the SSH tunnels like this (For this explaination we'll imagine that the Windows XP machine is on the VMware virutal network with an IP of 172.16.188.130, the Windows 7 machine is on 172.16.188.131 and that our Kali machine is also on this network):
[email protected]:~# ssh -f [email protected] -L 5900:172.16.188.130:5900 -N [email protected]:~# ssh -f [email protected] -L 5901:172.16.188.131:5900 -N
Now if you VNC to 127.0.0.1 you will have access to the Windows XP machine and to 127.0.0.1:1 you will have access to the Windows 7 machine.
1 VM Setup
You can also setup this up with 2 machines, the VMware host (running Windows, which will be the debugger) and the VMware guest (also running Windows, which will be the debuggee).
The serial port configuration for the debuggee in VMware in this setup should look like this:
Notice the different file path and name for Windows, the other end should be set to The other end is an application and Yeild CPU on poll should be checked.
The only other thing that is different is the command you will use to launch KD on the debugger (we haven't got to that but it is shown below for my 4 machine setup), you should instead use
kd -k com:port=\\.\pipe\com_1,pipe.
On Windows 7 (the debuggee) you will need to tell it to lanuch the debugger on boot, for this you need to run an Administrator command prompt and:
C:\Windows\system32>bcdedit /dbgsettings SERIAL DEBUGPORT:2 BAUDRATE:115200 The operation completed successfully. C:\Windows\system32>bcdedit /debug on The operation completed successfully.
The DEBUGPORT:2 option here is the port number of the COM port that you are going to use, for me it was COM2 hence the number 2.
Now we launch the kernel debugger on the Windows XP machine (this is the command that is different on the 2 machine setup):
C:\Documents and Settings\User>kd -k com:port=1,baud=115200 Microsoft (R) Windows Debugger Version 6.12.0002.633 X86 Copyright (c) Microsoft Corporation. All rights reserved. Opened \\.\com1 Waiting to reconnect...
Again the port=1 option here is the COM port that you are going to be using, I will be using COM1 on this machine hence the 1.
Then reboot the Windows 7 machine and watch the KD terminal on the Windows XP machine:
Connected to Windows 7 7601 x86 compatible target at (Fri Sep 26 14:43:59.625 20 14 (UTC + 1:00)), ptr64 FALSE Kernel Debugger connection established. Symbol search path is: SRV*C:\websymbols*http://msdl.microsoft.com/download/symb ols Executable search path is: Windows 7 Kernel Version 7601 (Service Pack 1) MP (1 procs) Free x86 compatible Product: WinNt, suite: TerminalServer SingleUserTS Personal Built by: 7601.18409.x86fre.win7sp1_gdr.140303-2144 Machine Name: Kernel base = 0x82814000 PsLoadedModuleList = 0x8295d5b0 Debug session time: Sun Dec 29 22:42:59.976 1985 (UTC + 1:00) System Uptime: 0 days 0:02:14.490
Now run the crackme application on the debuggee (Windows 7):
Go back to the Windows XP machine and in the debugger terminal window press Control + C:
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: 8288e7b8 cc int 3 kd>
Now we have broken into the kernel, this means that anything we do will be in the context of the kernel, we can see this in the debugger:
kd> .process Implicit process is now 844bdae8 kd> !process 0 0 **** NT ACTIVE PROCESS DUMP **** PROCESS 844bdae8 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000 DirBase: 00185000 ObjectTable: 88401c78 HandleCount: 463. Image: System PROCESS 85027020 SessionId: none Cid: 00ec Peb: 7ffd4000 ParentCid: 0004 DirBase: 5f228020 ObjectTable: 89496538 HandleCount: 29. Image: smss.exe PROCESS 85702030 SessionId: 0 Cid: 0140 Peb: 7ffd6000 ParentCid: 0134 DirBase: 5f228060 ObjectTable: 91695508 HandleCount: 389. Image: csrss.exe PROCESS 84520378 SessionId: 0 Cid: 0170 Peb: 7ffdf000 ParentCid: 0134 DirBase: 5f2280a0 ObjectTable: 93023448 HandleCount: 87. Image: wininit.exe PROCESS 850e7030 SessionId: 1 Cid: 0178 Peb: 7ffda000 ParentCid: 0168 DirBase: 5f228040 ObjectTable: 885f5520 HandleCount: 176. Image: csrss.exe PROCESS 8572f530 SessionId: 1 Cid: 0194 Peb: 7ffdb000 ParentCid: 0168 DirBase: 5f2280c0 ObjectTable: 93020e70 HandleCount: 117. Image: winlogon.exe PROCESS 857e2c48 SessionId: 0 Cid: 01dc Peb: 7ffd6000 ParentCid: 0170 DirBase: 5f228080 ObjectTable: 98040678 HandleCount: 245. Image: services.exe PROCESS 857fb980 SessionId: 0 Cid: 01e4 Peb: 7ffdf000 ParentCid: 0170 DirBase: 5f2280e0 ObjectTable: 9805ba38 HandleCount: 504. Image: lsass.exe PROCESS 857fc678 SessionId: 0 Cid: 01ec Peb: 7ffdf000 ParentCid: 0170 DirBase: 5f228100 ObjectTable: 9805dcf0 HandleCount: 144. Image: lsm.exe PROCESS 8582c858 SessionId: 0 Cid: 0258 Peb: 7ffd6000 ParentCid: 01dc DirBase: 5f228120 ObjectTable: 98168ef8 HandleCount: 352. Image: svchost.exe PROCESS 85845848 SessionId: 0 Cid: 02a4 Peb: 7ffd3000 ParentCid: 01dc DirBase: 5f228140 ObjectTable: 93182530 HandleCount: 241. Image: svchost.exe PROCESS 8585b568 SessionId: 0 Cid: 02e0 Peb: 7ffd7000 ParentCid: 01dc DirBase: 5f228160 ObjectTable: 980d5468 HandleCount: 383. Image: svchost.exe PROCESS 85897628 SessionId: 0 Cid: 0350 Peb: 7ffdf000 ParentCid: 01dc DirBase: 5f2281a0 ObjectTable: 8ca18bc0 HandleCount: 268. Image: svchost.exe PROCESS 858a7410 SessionId: 0 Cid: 037c Peb: 7ffda000 ParentCid: 01dc DirBase: 5f2281c0 ObjectTable: 8ca8e818 HandleCount: 251. Image: svchost.exe PROCESS 858bf818 SessionId: 0 Cid: 03b4 Peb: 7ffdf000 ParentCid: 01dc DirBase: 5f2281e0 ObjectTable: 8ca00b30 HandleCount: 806. Image: svchost.exe PROCESS 858ce658 SessionId: 0 Cid: 03ec Peb: 7ffd8000 ParentCid: 02e0 DirBase: 5f228200 ObjectTable: 8cb845d0 HandleCount: 121. Image: audiodg.exe PROCESS 858d37c0 SessionId: 0 Cid: 0400 Peb: 7ffde000 ParentCid: 01dc DirBase: 5f228220 ObjectTable: 8cb97f58 HandleCount: 104. Image: svchost.exe PROCESS 858e8238 SessionId: 0 Cid: 0460 Peb: 7ffd6000 ParentCid: 01dc DirBase: 5f228240 ObjectTable: 8cbc3380 HandleCount: 351. Image: svchost.exe PROCESS 85707d40 SessionId: 1 Cid: 050c Peb: 7ffd9000 ParentCid: 0194 DirBase: 5f228280 ObjectTable: 92cff7b0 HandleCount: 46. Image: userinit.exe PROCESS 8593dd40 SessionId: 1 Cid: 051c Peb: 7ffda000 ParentCid: 0350 DirBase: 5f2282a0 ObjectTable: 92d040e0 HandleCount: 71. Image: dwm.exe PROCESS 8594b738 SessionId: 1 Cid: 0538 Peb: 7ffde000 ParentCid: 050c DirBase: 5f2282c0 ObjectTable: 92d16c08 HandleCount: 684. Image: explorer.exe PROCESS 8595d990 SessionId: 0 Cid: 055c Peb: 7ffd8000 ParentCid: 01dc DirBase: 5f2282e0 ObjectTable: 980413e8 HandleCount: 75. Image: spoolsv.exe PROCESS 85975d40 SessionId: 1 Cid: 0574 Peb: 7ffdb000 ParentCid: 01dc DirBase: 5f228300 ObjectTable: 98087388 HandleCount: 180. Image: taskhost.exe PROCESS 8597c480 SessionId: 0 Cid: 059c Peb: 7ffd8000 ParentCid: 01dc DirBase: 5f228320 ObjectTable: 981644c0 HandleCount: 321. Image: svchost.exe PROCESS 857b1030 SessionId: 0 Cid: 061c Peb: 7ffdf000 ParentCid: 01dc DirBase: 5f228340 ObjectTable: 9361d7c0 HandleCount: 62. Image: armsvc.exe PROCESS 8576a030 SessionId: 0 Cid: 066c Peb: 7ffd8000 ParentCid: 01dc DirBase: 5f228360 ObjectTable: 98192530 HandleCount: 84. Image: sqlwriter.exe PROCESS 857b99c0 SessionId: 0 Cid: 0694 Peb: 7ffd8000 ParentCid: 01dc DirBase: 5f228380 ObjectTable: 9765fa30 HandleCount: 92. Image: tlntsvr.exe PROCESS 85996d40 SessionId: 1 Cid: 06bc Peb: 7ffdf000 ParentCid: 0538 DirBase: 5f2283a0 ObjectTable: 976b6a40 HandleCount: 64. Image: tvnserver.exe PROCESS 859d92f0 SessionId: 0 Cid: 0708 Peb: 7ffdc000 ParentCid: 01dc DirBase: 5f2283e0 ObjectTable: 8d600730 HandleCount: 184. Image: tvnserver.exe PROCESS 859ec4f0 SessionId: 1 Cid: 075c Peb: 7ffd3000 ParentCid: 06cc DirBase: 5f228400 ObjectTable: 9812e900 HandleCount: 48. Image: reader_sl.exe PROCESS 859f7d40 SessionId: 0 Cid: 0220 Peb: 7ffdd000 ParentCid: 01dc DirBase: 5f2283c0 ObjectTable: 977880a0 HandleCount: 102. Image: svchost.exe PROCESS 85a68d40 SessionId: 0 Cid: 03c4 Peb: 7ffd9000 ParentCid: 01dc DirBase: 5f228260 ObjectTable: 980eb688 HandleCount: 590. Image: SearchIndexer.exe PROCESS 85a4cd40 SessionId: 0 Cid: 04dc Peb: 7ffd5000 ParentCid: 03c4 DirBase: 5f228420 ObjectTable: 94285460 HandleCount: 233. Image: SearchProtocolHost.exe PROCESS 85a95d40 SessionId: 0 Cid: 0378 Peb: 7ffd5000 ParentCid: 03c4 DirBase: 5f228440 ObjectTable: 931b48e8 HandleCount: 79. Image: SearchFilterHost.exe PROCESS 85abfd40 SessionId: 1 Cid: 08e4 Peb: 7ffdf000 ParentCid: 0538 DirBase: 5f228460 ObjectTable: 92c6b320 HandleCount: 35. Image: SomeCrypto~01.exe kd>
On line 1 I run the .process command without any parameters and it tells us the process we are currently in (844bdae8 is the EPROCESS number).
On line 3 I run the !process extension with 0 0 as its arguments, this lists all of the running processes and some details about them, as you can see from lines 5-7, EPROCESS 844bdae8 is the System process, or the kernel.
What we want to do is change the context to our crackme application, which you can see from lines 141-143 has the EPROCESS of 85abfd40:
kd> .process /i /r /p 85abfd40 You need to continue execution (press 'g' <enter>) for the context to be switched. When the debugger breaks in again, you will be in the new process context. kd> g Break instruction exception - code 80000003 (first chance) nt!RtlpBreakWithStatusInstruction: 828c97b8 cc int 3 kd> .process Implicit process is now 85abfd40 kd>
On line 1 I use the .process command to change the context to our crackme application but before the context can be changed execution needs to be resumed (which is done on line 5).
Now we can set a breakpoint anywhere in the crackme's virtual memory address space, we want to break with them calls to GetDlgItemTextA that were responsible for getting the text in the textboxes of the application (If you are unsure about what I am talking about, please go back and review the previous post):
kd> bp USER32!GetDlgItemTextA kd> bl 0 e 76213d14 0001 (0001) user32!GetDlgItemTextA kd>
Now that the breakpoint is set we can resume execution, wait for it to be hit and inspect the memory.
Remember that the prototype for GetDlgItemText is:
UINT WINAPI GetDlgItemText( _In_ HWND hDlg, _In_ int nIDDlgItem, _Out_ LPTSTR lpString, _In_ int nMaxCount );
kd> g Breakpoint 0 hit user32!GetDlgItemTextA: 001b:76213d14 8bff mov edi,edi kd> dd esp L4 0012fb6c 0040127f 0002014e 000003e9 0012fc40 kd> da 12fc40 0012fc40 "Enter your name..." kd>
On line 5 I use the dd command to display 4 double words on the top of the stack. The first dword will be the return address (as you will see in a minute), then we have the first 3 arguments.
The 3rd argument is the address where the buffer for the string is, on line 7 I use the da command to display the ascii value at that address.
Keep in mind that this is the start of the function so the value hasn't been fetched yet, we can see the returned value by tracing through until we are in the calling function using the ug command and checking again:
kd> gu 001b:0040127f 6a40 push 40h kd> u 001b:0040127f 6a40 push 40h 001b:00401281 8d942484000000 lea edx,[esp+84h] 001b:00401288 52 push edx 001b:00401289 68ea030000 push 3EAh 001b:0040128e 56 push esi 001b:0040128f ffd7 call edi 001b:00401291 8d44240c lea eax,[esp+0Ch] 001b:00401295 50 push eax kd> da 12fc40 0012fc40 "Enter your name..." kd>
As you can see the value is the same (because we haven't changed the text in the textbox), you can also see the address which it returned back to after executing GetDlgItemTextA was 0040127f, which was the top value on the stack.
Lastly let's resume and make sure it does the same with the other textbox:
kd> g Breakpoint 0 hit user32!GetDlgItemTextA: 001b:76213d14 8bff mov edi,edi kd> dd esp L4 0012fb6c 00401291 0002014e 000003ea 0012fc00 kd> da 12fc00 0012fc00 "Enter your serial..." kd> gu 001b:00401291 8d44240c lea eax,[esp+0Ch] kd> da 12fc00 0012fc00 "Enter your serial..."
This was only a simple tutorial to get the environment set up and get a basic grasp of kd.exe and some of its commands.
This was by no means an exhaustive list of commands and extensions, the debugger comes with many and has very good documentation.
Hopefully you now have a better understanding of how to debug using kd.exe and you now have the environment to do it in.
The Debugging and Automation chapter in Practical Reverse Engineering by Bruce Dang, Alexandre Gazet and Elias Bachaalany.
Also the kd.exe documentation that ships with the WDK or SDK.