WinDbg/Examples
You are here: | Examples
|
Description
In this example, we will analyze Lab10-01 from Practical Malware Analysis.
First step: analyze code in IDA Pro
Before we analyze the code in WinDbg, let's analyze it in IDA-Pro. We start with Lab10-01.exe. The malware first calls OpenSCManager to get a handle to the Windows service manager:
.text:00401000 sub esp, 1Ch
.text:00401003 push edi
.text:00401004 push 0F003Fh ; dwDesiredAccess
.text:00401009 push 0 ; lpDatabaseName
.text:0040100B push 0 ; lpMachineName
.text:0040100D call ds:OpenSCManagerA
.text:00401013 mov edi, eax
.text:00401015 test edi, edi
.text:00401017 jnz short loc_401020
.text:00401019 pop edi
.text:0040101A add esp, 1Ch
.text:0040101D retn 10h
Then CreateService is called with dwServiceType set to 0x1, which corresponds to a kernel driver service (SERVICE_KERNEL_DRIVER). The code for the service is stored in the C:\Windows\System32\Lab10-01.sys file.
.text:00401020 push esi
.text:00401021 push 0 ; lpPassword
.text:00401023 push 0 ; lpServiceStartName
.text:00401025 push 0 ; lpDependencies
.text:00401027 push 0 ; lpdwTagId
.text:00401029 push 0 ; lpLoadOrderGroup
.text:0040102B push offset BinaryPathName ; "C:\\Windows\\System32\\Lab10-01.sys"
.text:00401030 push 1 ; dwErrorControl
.text:00401032 push 3 ; dwStartType
.text:00401034 push 1 ; dwServiceType
.text:00401036 push 0F01FFh ; dwDesiredAccess
.text:0040103B push offset ServiceName ; "Lab10-01"
.text:00401040 push offset ServiceName ; "Lab10-01"
.text:00401045 push edi ; hSCManager
.text:00401046 call ds:CreateServiceA
.text:0040104C mov esi, eax
.text:0040104E test esi, esi
.text:00401050 jnz short loc_401069
If the function isn't successful (service may already exist), OpenService is called to open the existing service named "Lab10-01":
.text:0040104E test esi, esi
.text:00401050 jnz short loc_401069
.text:00401052 push 0F01FFh ; dwDesiredAccess
.text:00401057 push offset ServiceName ; "Lab10-01"
.text:0040105C push edi ; hSCManager
.text:0040105D call ds:OpenServiceA
.text:00401063 mov esi, eax
.text:00401065 test esi, esi
.text:00401067 jz short loc_401086
The service is then started:
.text:00401069 push 0 ; lpServiceArgVectors
.text:0040106B push 0 ; dwNumServiceArgs
.text:0040106D push esi ; hService
.text:0040106E call ds:StartServiceA
.text:00401074 test esi, esi
.text:00401076 jz short loc_401086
And the service is then immediately stopped (ControlService called with dwControl set to SERVICE_CONTROL_STOP):
.text:00401078 lea eax, [esp+24h+ServiceStatus]
.text:0040107C push eax ; lpServiceStatus
.text:0040107D push 1 ; dwControl
.text:0040107F push esi ; hService 0x1 = SERVICE_CONTROL_STOP
.text:00401080 call ds:ControlService
This latest instruction will unload the driver and call the driver's unload function.
WinDbg on the debuggee's side
Now we can open our debuggee's virtual machine and load Lab10-01.exe in WinDbg (Ctrl+E). Prior to opening WinDbg, move the Lab10-01.sys file to C:\Windows\System32
We set a breakpoint to 0x401080, just before the driver is unloaded, and reach the breakpoint:
0:000> bp 0x401080 *** WARNING: Unable to verify checksum for image00400000 *** ERROR: Module load completed but symbols could not be loaded for image00400000 0:000> g Breakpoint 0 hit eax=0012ff1c ebx=7ffd6000 ecx=77dbfb6d edx=00000000 esi=00143fe8 edi=00144ef8 eip=00401080 esp=0012ff08 ebp=0012ffc0 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206 image00400000+0x1080: 00401080 ff1510404000 call dword ptr [image00400000+0x4010 (00404010)] ds:0023:00404010={ADVAPI32!ControlService (77dc49dd)}
WinDbg on the debugger's side
Find driver's address
Now, start WinDbg on the debugger's side, invoke kernel debugging (Ctrl+K) to connect to the debuggee's machine (refer to for more information). and select Debug > Break. You should get something similar to this:
In the command prompt, enter the following command to search for the driver:
kd> !drvobj Lab10-01 Driver object (861acb90) is for: \Driver\Lab10-01 Driver Extension List: (id , addr) Device Object list:
Find driver function's address
Now that we know the driver is at offset 0x861acb90, we can display its structure:
kd> dt nt!_DRIVER_OBJECT 0x861acb90 +0x000 Type : 0n4 +0x002 Size : 0n168 +0x004 DeviceObject : (null) +0x008 Flags : 0x12 +0x00c DriverStart : 0xf7c80000 Void +0x010 DriverSize : 0xe80 +0x014 DriverSection : 0x85f8df00 Void +0x018 DriverExtension : 0x861acc38 _DRIVER_EXTENSION +0x01c DriverName : _UNICODE_STRING "\Driver\Lab10-01" +0x024 HardwareDatabase : 0x80670ae0 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM" +0x028 FastIoDispatch : (null) +0x02c DriverInit : 0xf7c80959 long +fffffffff7c80959 +0x030 DriverStartIo : (null) +0x034 DriverUnload : 0xf7c80486 void +fffffffff7c80486 +0x038 MajorFunction : [28] 0x804f354a long nt!IopInvalidDeviceRequest+0
The driver's unload function is called DriverUnload and is at offset 0x34 to the beginning of the driver's start address. We can now set a breakpoint at 0x95191486 where the function is called:
kd> bp 0xf7c80486 kd> g
Don't forget to also resume (kd> g) WinDbg on the debuggee's side. Back to the debugger's side, here's what we should see:
Breakpoint 0 hit f7c80486 8bff mov edi,edi
Analyze driver's function in WinDbg
Press Alt+7 or go to View > Disassembly to display the assembly code. Press F10 (step over) to see the different functions that are called.
[SNIP] f7c804a0 ffd6 call esi {nt!RtlCreateRegistryKey (805ddafe)} [SNIP] f7c804a8 ffd6 call esi {nt!RtlCreateRegistryKey (805ddafe)} [SNIP] f7c804b0 ffd6 call esi {nt!RtlCreateRegistryKey (805ddafe)} [SNIP] f7c804b9 ffd6 call esi {nt!RtlCreateRegistryKey (805ddafe)} [SNIP] f7c804d6 ffd6 call esi {nt!RtlWriteRegistryValue (805dda74)} [SNIP] f7c804e4 ffd6 call esi {nt!RtlWriteRegistryValue (805dda74)} [SNIP]
The program is calling RtlCreateRegistryKey several times to create registry keys and RtlWriteRegistryValue to set EnableFirewall value to 0.
Analysis of the function in IDA Pro
Now, we can analyze the function in IDA-Pro. Let's open the Lab01-01.sys file and rebase it (because the ImageBase is set to 0x00010000 by default).
The lm instruction can provide us with the driver start adddress:
kd> lm start end module name 804d7000 806cfe00 nt (pdb symbols) c:\websymbols\ntkrnlpa.pdb\30B5FB31AE7E4ACAABA750AA241FF3311\ntkrnlpa.pdb Unloaded modules: f7c80000 f7c81000 Lab10-01.sys ee683000 ee6ae000 kmixer.sys f7bcc000 f7bcd000 drmkaud.sys ee74e000 ee771000 aec.sys eebfe000 eec0b000 DMusic.sys f76cd000 f76db000 swmidi.sys f7bab000 f7bad000 splitter.sys f794d000 f7952000 Cdaudio.SYS f72ca000 f72cd000 Sfloppy.SYS
Now we want to rebase our driver in IDA-Pro. To do that, go to Edit > Segments > Rebase program... and enter "0xf7c80000". Now, we can easily find (at offset 0xf7c80486) the driver's function (DriverUnload) that has been called:
Comments
Keywords: windbg kernel debugging