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
…