CreateServiceA
call failed because the service already existed.ControlService
at ❷. The second parameter to ControlService
is what type of control message is being sent. In this case, the value is 0x01
at ❸, which we look up in the documentation and find that it means SERVICE_CONTROL_STOP
. This will unload the driver and call the driver’s unload function.DriverEntry
function appears to move an offset value into a memory location, but otherwise it doesn’t make any function calls or interact with the system.Example C-28. Viewing the driver object for Lab10-01.sys in WinDbg
kd> dt _DRIVER_OBJECT 8263b418 nt!_DRIVER_OBJECT +0x000 Type : 4 +0x002 Size : 168 +0x004 DeviceObject : (null) +0x008 Flags : 0x12 +0x00c DriverStart : 0xf7c47000 +0x010 DriverSize : 0xe80 +0x014 DriverSection : 0x826b2c88 +0x018 DriverExtension : 0x8263b4c0 _DRIVER_EXTENSION +0x01c DriverName : _UNICODE_STRING "\Driver\Lab10-01" +0x024 HardwareDatabase : 0x80670ae0 _UNICODE_STRING "\REGISTRY\MACHINE\ HARDWARE\DESCRIPTION\SYSTEM" +0x028 FastIoDispatch : (null) +0x02c DriverInit : 0xf7c47959 long +0 +0x030 DriverStartIo : (null) +0x034 DriverUnload : ❶0xf7c47486 void +0 +0x038 MajorFunction : [28] 0x804f354a long nt!IopInvalidDeviceRequest+0
We’re trying to identify the function called when the driver is unloaded—information at offset 0x034, DriverUnload
, as shown at ❶. Then we set a breakpoint using the following command:
kd> bp 0xf7c47486
Having set the breakpoint, we resume running our kernel. Then we return to the version of WinDbg running on the executable on our virtual machine and resume it as well. Immediately, the entire guest OS freezes because the kernel debugger has hit our kernel breakpoint. At this point, we can go to the kernel debugger to step through the code. We see that the program calls the RtlCreateRegistryKey
function three times to create several registry keys, and then calls the RtlWriteRegistryValue
twice to set the EnableFirewall
value to 0 in two places. This disables the Windows XP firewall from the kernel in a way that is difficult for security programs to detect.
If the unload function at 0xf7c47486 were long or complex, it would have been difficult to analyze in WinDbg. In many cases, it’s easier to analyze a function in IDA Pro once you have identified where the function is located, because IDA Pro does a better job of analyzing the functions. However, the function location in WinDbg is different than the function location in IDA Pro, so we must perform some manual calculations in order to view the function in IDA Pro. We must calculate the offset of the function from the beginning of the file as it is loaded in WinDbg using the lm
command, as follows:
kd> lm start end module name ... f7c47000❶ f7c47e80 Lab10_01 (no symbols) ...
As you can see, the file is loaded at 0xf7c47000 at ❶, and from earlier, we know the unload function is located at 0xf7c47486. We subtract 0xf7c47000 from 0xf7c47486 to get the offset (0x486), which we then use to navigate to the unload function in IDA Pro. For example, if the base load address in IDA Pro is 0x00100000, then we navigate to address 0x00100486 to find the unload function in IDA Pro. We can then use static analysis and IDA Pro to confirm what we discovered in WinDbg.
Alternatively, we can change the base address in IDA Pro by selecting Edit ▸ Segments ▸ Rebase Program and changing the base address value from 0x00100000 to 0xf7c47000.
If you tried to use a deferred breakpoint using the bu $iment(Lab10-01)
, you may have run into trouble because WinDbg changes hyphens to underscores when it encounters them in filenames. The correct command to break on the entry point of the driver in this lab would be bu $iment(Lab10_01)
. This behavior is not documented anywhere and may be inconsistent across versions of WinDbg.