Getting IAT for all drivers from a Kernel Dump

For some obscure reasons, I needed the Import Address Table (IAT) of specific modules from a kernel dump. Actually I needed them for all modules from potentially a whole lot of dumps. Getting the IAT for one module is straightforward:

  • Get the address of a module. For example for smb.sys

    1: kd> lm msmb

    start end module name

    9c03e000 9c054000 smb

     

  • Dump the headers

    1: kd> !dh /f 9c03e000

     

    File Type: EXECUTABLE IMAGE

    FILE HEADER VALUES

    14C machine (i386)

    7 number of sections

    4A5BC903 time date stamp Mon Jul 13 16:53:39 2009

     

     

    0 [ 0] address [size] of Special Directory

    0 [ 0] address [size] of Thread Storage Directory

    0 [ 0] address [size] of Load Configuration Directory

    0 [ 0] address [size] of Bound Import Directory

    C000 [ 1F4] address [size] of Import Address Table Directory

    0 [ 0] address [size] of Delay Import Directory

    0 [ 0] address [size] of COR20 Header Directory

    0 [ 0] address [size] of Reserved Directory

 

  • Dump the IAT

    1: kd> dds 9c03e000+C000 9c03e000+C000+1F4

    9c04a000 82e06700 hal!KfAcquireSpinLock

    9c04a004 82e086ee hal!KeGetCurrentIrql

    9c04a008 82e067a0 hal!KfReleaseSpinLock

     

But that is all very manual. I would like to iterate over all modules in the dump and spit out the IAT to a text file or so. Excellent opportunity to finally learn WinDbg scripts. So here is the result:

$$ run like this: $$>a<" IAT.txt"

 

.logopen /t @"mylogfile.txt"

 

.echo =========================================

.echo Get IAT for all modules

.echo =========================================

 

$$ get offset of NT Header offset

r? $t1 = #FIELD_OFFSET(_IMAGE_DOS_HEADER , e_lfanew )

 

$$ get offset of OptionalHeader and store it

r? $t3 = #FIELD_OFFSET(_IMAGE_NT_HEADERS, OptionalHeader)

 

$$ get offset of DataDirectory and store

r? $t4 = #FIELD_OFFSET(_IMAGE_OPTIONAL_HEADER, DataDirectory)

 

$$ Iterate over each base address, get to the IAT address

!for_each_module "r $t0 = @#Base; .echo ==== @#ModuleName;

r $t2=poi(@$t0+@$t1);

r $t5=poi(@$t0+@$t2+@$t3+@$t4+0n12*0x8);

r $t6=poi(@$t0+@$t2+@$t3+@$t4+0n12*0x8+0x4);

dds @$t0 + @$t5 @$t0 + @$t5 + @$t6"

 

.logclose

 

There are probably better ways of doing this. But it gets the job done and I wrote my first script J. And the output

Opened log file 'D:\Playground7\OCA Reclassification\mylogfile_0820_2010-04-21_15-25-53-872.txt'

=========================================

Get IAT for all modules

=========================================

==== kdcom

80bc9000 82e1bfe4 hal!READ_PORT_UCHAR

80bc9004 82e1c04c hal!WRITE_PORT_UCHAR