Scanning for Drivers

Drivers extend the functionality of the kernel, e.g. by implementing a network communication protocol or an interface to a new piece of hardware. They are loadable kernel-mode modules, what allows them to modify any system behavior. Several rootkits are implemented by drivers. In this post I present a plugin for the Volatility memory analysis framework, that scans for driver objects.

A driver object is represented by a, you guessed it, _DRIVER_OBJECT structure. This structure tells about the address of the driver's code in memory and provides pointers to a variety of request handling functions.

kd> dt _DRIVER_OBJECT
ntdll!_DRIVER_OBJECT
struct _DRIVER_OBJECT, 15 elements, 0xa8 bytes
   +0x000 Type             : Int2B
   +0x002 Size             : Int2B
   +0x004 DeviceObject     : Ptr32 _DEVICE_OBJECT
   +0x008 Flags            : Uint4B
   +0x00c DriverStart      : Ptr32 Void
   +0x010 DriverSize       : Uint4B
   +0x014 DriverSection    : Ptr32 Void
   +0x018 DriverExtension  : Ptr32 _DRIVER_EXTENSION
   +0x01c DriverName       : _UNICODE_STRING
   +0x024 HardwareDatabase : Ptr32 _UNICODE_STRING
   +0x028 FastIoDispatch   : Ptr32 _FAST_IO_DISPATCH
   +0x02c DriverInit       : Ptr32     long 
   +0x030 DriverStartIo    : Ptr32     void 
   +0x034 DriverUnload     : Ptr32     void 
   +0x038 MajorFunction    : [28] Ptr32     long 

The object also links to an extension. It tells us about the "ServiceKeyName". That's the registry key below HKLM\SYSTEM\controlset\Services, where the driver stores its configuration data.

kd> dt _DRIVER_EXTENSION
ntdll!_DRIVER_EXTENSION
struct _DRIVER_EXTENSION, 6 elements, 0x1c bytes
   +0x000 DriverObject     : Ptr32 _DRIVER_OBJECT
   +0x004 AddDevice        : Ptr32     long 
   +0x008 Count            : Uint4B
   +0x00c ServiceKeyName   : _UNICODE_STRING
   +0x014 ClientDriverExtension : Ptr32 _IO_CLIENT_EXTENSION
   +0x018 FsFilterCallbacks : Ptr32 _FS_FILTER_CALLBACKS

Both structures point to the other. So, one might assume, they are stored in different locations of the memory. But interestingly nt!IoCreateDriver allocates a single block of memory that is large enough to hold both of them. The allocation is made from the nonpaged pool and tagged with "Driv".

The final in-memory structure, as assembled by IoCreateDriver, looks as follows:

  1. _POOL_HEADER
  2. extra object name information
  3. _OBJECT_HEADER
  4. _DRIVER_OBJECT
  5. _DRIVER_EXTENSION

Here's a little plugin for the Volatility memory analysis framework to search for and parse these structures. Please create a backup copy of your Volatility installation first. Then unzip the archive in your Volatility base directory. If you use the current version from the Volatility SVN repository, then please install only the plugin file.

Below are the results on an infection with Unreal.A. Even though the rootkit tried to hide its name, the plugin found it in object meta-data. The zeroed object type pointer should raise some suspicion, too.

Obj Type   #Ptr #Hnd Start        Size Service key  Name
0x00000000    0    0 0xfca49000   5888              unreal
0x812b5ad0    3    0 0xfc62b000  57600 usbhub       usbhub    \Driver\usbhub
0x812b5ad0    4    0 0xfa8ef000  76256 hgfs         hgfs      \FileSystem\hgfs

Archives

Imprint

This blog is a project of:
Andreas Schuster
Im Äuelchen 45
D-53177 Bonn
impressum@forensikblog.de

Copyright © 2005-2012 by
Andreas Schuster
All rights reserved.
Powered by Movable Type 5.12