Practical Malware Analysis
Ch 10: Kernel Debugging with
WinDbg
WinDbg v. OllyDbg
• OllyDbg is the most popular user-mode
debugger for malware analysts
• WinDbg can be used in either user-mode or
kernel-mode
• This chapter explores ways to use WinDbg for
kernel debugging and rootkit analysis
Drivers and Kernel Code
Device Drivers
• Windows device drivers allow third-party
developers to run code in the Windows kernel
• Drivers are difficult to analyze
– They load into memory, stay resident, and
respond to requests from applications
• Applications don't directly access kernel
drivers
– They access device objects which send requests to
particular devices
Devices
• Devices are not physical hardware
components
• They are software representations of those
components
• Driver creates and destroys devices, which can
be accessed from user space
USB Flash Drive
• User plugs in flash drive
• Windows creates the "F: drive" device object
• Applications can now make requests to the F:
drive
– They will be sent to the driver for USB flash drives
Loading Drivers
• Drivers must be loaded into the kernel
– Just as DLLs are loaded into processes
• When a driver is first loaded, its DriverEntry
procedure is called
– Just like DLLMail for DLLs
DriverEntry
• DLLs expose functionality through the export table
• Drivers must register the address for callback
functions
– They will be called when a user-space software
component requests a service
– DriverEntry performs this registration
– Windows creates a driver object structure, passes it to
DriverEntry which fills it with callback functions
– DriverEntry then creates a device that can be accessed
from user-land
Example: Normal Read
• Normal read request
– User-mode application obtains a file handle to
device
– Calls ReadFile on that handle
– Kernel processes ReadFile request
– Invokes the driver's callback function handling I/O
Malicious Request
• Most common request from malware is
DeviceIoControl
– A generic request from a user-space module to a
device managed by a driver
– User-space program passes in an arbitrary-length
buffer of input data
– Received an arbitrary-length buffer of data as
output
Ntoskrnl.dll & Hal.dll
• Malicious drivers rarely control hardware
• They interact with Ntoskrnl.dll & Hal.dll
– Ntoskrnl.dll has code for core OS functions
– Hal.dll has code for interacting with main
hardware components
• Malware will import functions from one or
both of these files so it can manipulate the
kernel
Setting Up Kernel Debugging
VMware
• In the virtual machine, enable kernel
debugging
• Configure a virtual serial port between VM
and host
• Configure WinDbg on the host machine
Edit C:\Boot.ini
• Second boot option enables debugging
• This method won't work on Windows 7!
Add a Virtual Serial Port
Using WinDbg
Command-Line Commands
Reading from Memory
• dx addressToRead
• x can be
– da Displays as ASCII text
– du Displays as Unicode text
– dd Displays as 32-bit double words
• da 0x401020
– Shows the ASCII text starting at 0x401020
Editing Memory
• ex addressToWrite dataToWrite
• x can be
– ea Writes as ASCII text
– eu Writes as Unicode text
– ed Writes as 32-bit double words
Using Arithmetic Operators
• Usual arithmetic operators + - / *
• dwo reveals the value at a 32-bit location
pointer
• du dwo (esp+4)
– Shows the first argument for a function, as a wide
character string
Setting Breakpoints
• bp sets breakpoints
• You can specify an action to be performed
when the breakpoint is hit
• g tells it to resume running after the action
• bp GetProcAddress "da dwo(esp+8); g"
– Breaks when GetProcAddress is called, prints out
the second argument, and then continues
– The second argument is the function name
Listing Modules
• lm
– Lists all modules loaded into a process
• Including EXEs and DLLs in user space
• And the kernel drivers in kernel mode
– As close as WinDbg gets to a memory map
Microsoft Symbols
Symbols are Labels
• Including symbols lets you use
– MmCreateProcessAddressSpace
• instead of
– 0x8050f1a2
Searching for Symbols
• moduleName!symbolName
– Can be used anywhere an address is expected
• moduleName
– The EXE, DLL, or SYS filename (without extension)
• symbolName
– Name associated with the address
• ntoskrnl.exe is an exception, and is named nt
– Ex: u nt!NtCreateProcess
• Unassembles that function (disassembly)
Deferred Breakpoints
• bu newModule!exportedFunction
– Will set a breakpoint on exportedFunction as soon
as a module named newModule is loaded
• $iment
– Function that finds the entry point of a module
• bu $iment(driverName)
– Breaks on the entry point of the driver before any
of the driver's code runs
Searching with x
• You can search for functions or symbols using
wildcards
• x nt!*CreateProcess*
– Displays exported functions & internal functions
Listing Closest Symbol with ln
• Helps in figuring out where a call goes
• ln address
– First lines show two closest matches
– Last line shows exact match
Viewing Structure Information with
dt
• Microsoft symbols include type information
for many structures
– Including undocumented internal types
– They are often used by malware
• dt moduleName!symbolName
• dt moduleName!symbolName address
– Shows structure with data from address
Initialization Function
• The DriverInit function is called first when a
driver is loaded
• Malware will sometimes place its entire
malicious payload in this function
Configuring Windows Symbols
• If your debugging machine is connected to an
always-on broadband link, you can configure
WinDbg to automatically download symbols
from Microsoft as needed
• They are cached locally
• File, Symbol File Path
– SRC*c:\websymbols*http://
msdl.microsoft.com/download/
symbols
Manually Downloading Symbols
• Link Ch 10a
Kernel Debugging in Practice
Kernel Mode and User Mode
Functions
• We'll examine a program that writes to files
from kernel space
– Kernel mode programs cannot call user-mode
functions like CreateFile and WriteFile
– Must use NtCreateFile and NtWriteFile
User-Space Code
Creates a service with the CreateService function
dwServiceType is 0x01 (Kernel driver)
User-Space Code
• Not shown: edi being set to
– \\.\FileWriter\Device
User-Space Code
Kernel-Mode Code
• Set kernel-mode debugger to Verbose mode
• You'll see every kernel module that loads
• Kernel modules are not loaded or unloaded
often
– Any loads are suspicious
– Except Kmixer.sys in VMware machines
Kernel-Mode Code
• !drvobj command shows driver object
Kernel-Mode Code
• dt command shows structure
Kernel-Mode Filenames
• Tracing this function, it eventually creates this
file
– \DosDevices\C:\secretfile.txt
• This is a fully qualified object name
– Identifies the root device, usually \DosDevices
Finding Driver Objects
• Applications work with devices, not drivers
• Look at user-space application to identify the
interesting device object
• Use device object in User Mode to find driver
object in Kernel Mode
• Use !devobj to find out more about the driver
object
• Use !devhandles to find application that use the
driver
Rootkits
Rootkit Basics
• Rootkits modify the internal functionality of
the OS to conceal themselves
– Hide processes, network connections, and other
resources from running programs
– Difficult for antivirus, administrators, and security
analysts to discover their malicious activity
• Most rootkits modify the kernel
• Most popular method:
– System Service Descriptor Table (SSDT) hooking
System Service Descriptor Table
(SSDT)
• Used internally by Microsoft
– To look up function calls into the kernel
– Not normally used by third-party applications or
drivers
• Only three ways for user space to access kernel
code
– SYSCALL
– SYSENTER
– INT 0x2E
SYSENTER
• Used by modern versions of Windows
• Function code stored in EAX register
Example from ntdll.dll
• EAX set to 0x25
• Stack pointer saved in EDX
• SYSENTER is called
SSDT Table Entries
• Rootkit changes the values in the SSDT so rootkit code
is called instead of the intended function
• 0x25 would be changed to a malicious driver's
function
• Hooking NtCreateFile won't hide a file, however
Rootkit Analysis in Practice
• Simplest way to detect SSDT hooking
– Just look at the SSDT
– Look for values that are unreasonable
– In this case, ntoskrnl.exe starts at address
804d7000 and ends at 806cd580
– ntoskrnl.exe is the Kernel!
• lm m nt
– Lists modules matching "nt" (Kernel modules)
– Shows the SSDT table
SSDT Table
• Marked entry is hooked
• To identify it, examine a clean system's SSDT
Finding the Malicious Driver
• lm
– Lists open modules
– In the kernel, they are all drivers
Interrupts
• Interrupts allow hardware to trigger software
events
• Driver calls IoConnectInterrupt to
register a handler for an interrupt code
• Specifies an Interrupt Service Routine (ISR)
– Will be called when the interrupt code is generated
• Interrupt Descriptor Table (IDT)
– Stores the ISR information
– !idt command shows the IDT
Loading Drivers
• If you want to
load a driver to
test it, you can
download the
OSR Driver
Loader tool
Kernel Issues for Windows Vista,
Windows 7, and x64 Versions
• Uses BCDedit instead of boot.ini
• x64 versions starting with XP have PatchGuard
– Prevents thirdparty code from modifying the kernel
– Including kernel code itself, SSDT, IDT, etc.
– Can interfere with debugging, because debugger
patches code when inserting breakpoints
• There are 64-bit kernel debugging tools
– Link Ch 10c
Driver Signing
• Enforced in all 64-bit versions of Windows
starting with Vista
• Only digitally signed drivers will load
• Effective protection!
• Kernel malware for x64 systems is practically
nonexistent
– You can disable driver signing enforcement by
specifying nointegritychecks in BCDEdit