Reputation: 3107
I'm trying to troubleshoot an old application which crashes on my notebook.
Looking at the dump file I've found that it crashes with this instruction:
0044e381 ff1538b57b00 call dword ptr [appname+0x3bb538 (007bb538)]
because of a trivial reason:
0:000> dp 0x007bb538
007bb538 00000000 00000000 00000000 00000000
If I understand correctly, it is a call to a function of a dll which somehow failed to load. If I had symbols I would probably see something like _impl_!blahblahblah
to help me guess what's that. Alas, that's not the case.
So the question is: how to determine which dll it tries to call?
Upvotes: 1
Views: 152
Reputation: 9007
disassembly with symbols
0:000> u calc!AllocNumString+20 l1
calc!AllocNumString+0x20:
00083801 ff154c120800 call dword ptr [calc!_imp__LocalAlloc (0008124c)]
lets unload the symbols
0:000> .reload /u calc
Unloaded calc
disassembly without symbols
0:000> u 83801 l1
00083801 ff154c120800 call dword ptr ds:[8124Ch]
0:000> $$ you want to know what 8124c is/maybe pointing to
and you assume it might be an import
0:000> $$ lest get the import table address and size and see if that assumption is true
dt ntdll!_IMAGE_NT_HEADERS OptionalHeader -a OptionalHeader.DataDirectory[0n12].. 80000+poi(80000+3c)
+0x018 OptionalHeader : _IMAGE_OPTIONAL_HEADER
+0x060 DataDirectory : [12]
+0x000 VirtualAddress : 0x1000
+0x004 Size : 0x630
0:000> $$ yes 8124c lies between 81000 and 81630 definately import
0:000> $$ check the IAT
0:000> dt ntdll!_IMAGE_NT_HEADERS OptionalHeader -a OptionalHeader.DataDirectory[0n1].. 80000+poi(80000+3c)
+0x018 OptionalHeader : _IMAGE_OPTIONAL_HEADER
+0x060 DataDirectory : [1]
+0x000 VirtualAddress : 0x51afc
+0x004 Size : 0x154
0:000> $$ so IMAGE_IMPORT_DESCRIPTORS ARE AS FOLLOWS
0:000> dd /c 5 d1afc l154/4 51afc+imgbase(80000)
000d1afc 00051d20 ffffffff ffffffff 00051d14 00001000
000d1b10 00051d38 ffffffff ffffffff 00051d08 00001018
000d1b24 00051d40 ffffffff ffffffff 00051cfc 00001020
000d1b38 00051da8 ffffffff ffffffff 00051cec 00001088
000d1b4c 00051df0 ffffffff ffffffff 00051cdc 000010d0
000d1b60 00051e0c ffffffff ffffffff 00051cd0 000010ec
000d1b74 00051e14 ffffffff ffffffff 00051cc4 000010f4
000d1b88 00051e24 ffffffff ffffffff 00051cb4 00001104
000d1b9c 00051e4c ffffffff ffffffff 00051ca8 0000112c
000d1bb0 **00051e64** ffffffff ffffffff 00051c98 00001144
000d1bc4 00051fc8 ffffffff ffffffff 00051c8c 000012a8
000d1bd8 00052150 ffffffff ffffffff 00051c80 00001430
000d1bec 00052160 ffffffff ffffffff 00051c74 00001440
000d1c00 00052168 ffffffff ffffffff 00051c68 00001448
000d1c14 00052178 ffffffff ffffffff 00051c5c 00001458
000d1c28 000521e8 ffffffff ffffffff 00051c50 000014c8
000d1c3c 00000000 00000000 00000000 00000000 00000000
0:000> $$ you can find the respective dlls on each of the 4th dword in IID (it is rva add imagebase to it)
0:000> .foreach /pS 4 /ps 5 (place { dd /c 5 d1afc l154/4 }) { .printf "%x\t%ma\n" , place , 80000+ place }
51d14 SHELL32.dll
51d08 SHLWAPI.dll
51cfc gdiplus.dll
51cec ADVAPI32.dll
51cdc OLEAUT32.dll
51cd0 UxTheme.dll
51cc4 ole32.dll
51cb4 COMCTL32.dll
51ca8 ntdll.dll
51c98 KERNEL32.dll **51e64 : d1e64 with imgbase**
51c8c USER32.dll
51c80 RPCRT4.dll
51c74 WINMM.dll
51c68 VERSION.dll
51c5c GDI32.dll
51c50 msvcrt.dll
0 MZ
0:000> $$ the fifth dword (first thunk) will hold the start of imports for each dll
0:000> $$ so 124c lies between 1144 and 12a8 Ie in kernel32.dll
0:000> .foreach /ps1 /pS1 (place { dpa d1e64 l?((12a8-1144)/4) } ) {da place + 80000 }
000d27ea "I.lstrlenA"
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
000d2cde "D.LocalAlloc"
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
00080000 "MZ."
124c is the 43rd import
0:000> ? ((124c-1144) /4 ) + 1
Evaluate expression: 67 = 00000043
and it matches the symbol
0:000> r $t0=0; .foreach /ps1 /pS1 (place { dpa d1e64 l?((12a8-1144)/4) } ) { r $t0 = @$t0+1; .if(@$t0==43){ da place + 80000 } }
000d2cde "D.LocalAlloc"
-------------------------------------------------
UPDATE
-------------------------------------------------
the inbuilt !imports <module> command doesn't work without symbols
so i have been using some scripts similar to what was posted above
since this question came up i tried to remove hard coded hacks from the
script added some hacks for import by ordinal and post here may be it is useful
Script as Follows
$$ input to the script ; r $t0=${$arg1}; .printf /D "<b>Input\t%x\n</b>",@$t0
$$ mask for ibase ; r $t1=@$t0&0xffff0000;.printf /D "<b>IBase\t%x\n</b>",@$t1
$$ check dos_signature ; .printf /D "<b>IsDos\t%ma\n</b>",@$t1
$$ get image_nt_headers to a pseudo register ;
r? $t2 = (ntdll!_IMAGE_NT_HEADERS *) (@$t1 + (*(unsigned long *)( @$t1 + 0x3c)))
.printf /D "<b>\nImport Table DataDirectory[0n12] \n\n</b>"
?? @$t2->OptionalHeader.DataDirectory[0xc]
.printf /D "<b>\nIAT DataDirectory[0n01] \n\n</b>"
?? @$t2->OptionalHeader.DataDirectory[0x1]
.printf /D "<b>\nDump IMAGE_IMPORT_DESCRIPTOR without 5 NULL DWORDS \n\n</b>"
r? $t3 = @@c++( @$t2->OptionalHeader.DataDirectory[0x1].VirtualAddress + @$t1 )
r? $t4 = @@c++( @$t2->OptionalHeader.DataDirectory[0x1].Size / 4) - 5
dd /c 5 @$t3 l?@$t4
.printf /D "<b>\nRespective dlls from 4th DWORD of IID\n\n</b>"
.foreach /pS 4 /ps 5 (place {dd /c 5 @$t3 l?@$t4 }) {
.printf "%x + ibase \t %ma\n" , place , ( place + @$t1 )
}
.printf /D "<b>\nFirst import from respective dlls 1st DWORD From IID \n\n</b>"
.foreach /pS 1 /ps 5 (place {dd /c 5 @$t3 l?@$t4 }) {
r $t5 = poi( place + @$t1 );
.if( @$t5 & 0x80000000 ) {
.printf /D "<b>Import By Ordinal 0n%d\n</b>" , (@$t5 & 0fffffff)
} .else {
.printf "poi(%x+ ib)+ib+2) %x\t%ma\n", place ,(@$t5+@$t1+2),(@$t5+@$t1+2)
}
}
.printf /D "<b>\nDumping All Imports From All dlls \n\n</b>"
.for (r $t6 = 0 ; @$t6 < @$t4*4 ; r $t6 = @$t6+14) {
r $t7=poi(@$t3+@$t6) ; r $t8 = @$t7+@$t1 ;
.printf /D "<b>\n%ma\n\n</b>" , (poi(@$t3+@$t6+0xc)+@$t1)
.while( poi(@$t8)!=0 ) {
r $t9 = (poi(@$t8)+@$t1);
.if( @$t9 & 0x80000000 ) {
.printf /D "<b>Import By Ordinal 0n%d\n</b>" , (@$t9 & 0000ffff)
}.else {
.printf "%ma\n", (poi(@$t8)+@$t1)+2
}
r $t8 = @$t8+4;
}
}
usage 0:000> $$>a< x:\getimp.txt f1124c
should result in
0:000> $$>a< e:\windbgscripts\getimp.txt f1124c
Input f1124c
IBase f10000
IsDos MZ
Import Table DataDirectory[0n12]
struct _IMAGE_DATA_DIRECTORY
+0x000 VirtualAddress : 0x1000
+0x004 Size : 0x630
IAT DataDirectory[0n01]
struct _IMAGE_DATA_DIRECTORY
+0x000 VirtualAddress : 0x51afc
+0x004 Size : 0x154
Dump IMAGE_IMPORT_DESCRIPTOR without 5 NULL DWORDS
00f61afc 00051d20 ffffffff ffffffff 00051d14 00001000
00f61b10 00051d38 ffffffff ffffffff 00051d08 00001018
00f61b24 00051d40 ffffffff ffffffff 00051cfc 00001020
00f61b38 00051da8 ffffffff ffffffff 00051cec 00001088
00f61b4c 00051df0 ffffffff ffffffff 00051cdc 000010d0
00f61b60 00051e0c ffffffff ffffffff 00051cd0 000010ec
00f61b74 00051e14 ffffffff ffffffff 00051cc4 000010f4
00f61b88 00051e24 ffffffff ffffffff 00051cb4 00001104
00f61b9c 00051e4c ffffffff ffffffff 00051ca8 0000112c
00f61bb0 00051e64 ffffffff ffffffff 00051c98 00001144
00f61bc4 00051fc8 ffffffff ffffffff 00051c8c 000012a8
00f61bd8 00052150 ffffffff ffffffff 00051c80 00001430
00f61bec 00052160 ffffffff ffffffff 00051c74 00001440
00f61c00 00052168 ffffffff ffffffff 00051c68 00001448
00f61c14 00052178 ffffffff ffffffff 00051c5c 00001458
00f61c28 000521e8 ffffffff ffffffff 00051c50 000014c8
Respective dlls from 4th DWORD of IID
51d14 + ibase SHELL32.dll
51d08 + ibase SHLWAPI.dll
51cfc + ibase gdiplus.dll
51cec + ibase ADVAPI32.dll
51cdc + ibase OLEAUT32.dll
51cd0 + ibase UxTheme.dll
51cc4 + ibase ole32.dll
51cb4 + ibase COMCTL32.dll
51ca8 + ibase ntdll.dll
51c98 + ibase KERNEL32.dll
51c8c + ibase USER32.dll
51c80 + ibase RPCRT4.dll
51c74 + ibase WINMM.dll
51c68 + ibase VERSION.dll
51c5c + ibase GDI32.dll
51c50 + ibase msvcrt.dll
First import from respective dlls 1st DWORD From IID
poi(51d20+ ib)+ib+2) f62352 SHGetSpecialFolderPathW
Import By Ordinal 0n225
poi(51d40+ ib)+ib+2) f623a0 GdipDrawLineI
poi(51da8+ ib)+ib+2) f625a8 RegEnumKeyExW
Import By Ordinal 0n2
poi(51e0c+ ib)+ib+2) f626d0 IsThemeActive
poi(51e14+ ib)+ib+2) f626e0 CoInitialize
poi(51e24+ ib)+ib+2) f62716 ImageList_Destroy
poi(51e4c+ ib)+ib+2) f6277c WinSqmAddToStreamEx
poi(51e64+ ib)+ib+2) f627ec lstrlenA
poi(51fc8+ ib)+ib+2) f62ea0 GetSysColor
poi(52150+ ib)+ib+2) f6351a UuidCreate
poi(52160+ ib)+ib+2) f6354a timeGetTime
poi(52168+ ib)+ib+2) f63558 GetFileVersionInfoExW
poi(52178+ ib)+ib+2) f6359e EqualRgn
poi(521e8+ ib)+ib+2) f6376a wcsncmp
Dumping All Imports From All dlls
SHELL32.dll
SHGetSpecialFolderPathW
SHGetFolderPathW
ShellAboutW
Import By Ordinal 0n165
ShellExecuteExW
SHLWAPI.dll
Import By Ordinal 0n225
gdiplus.dll
GdipDrawLineI
xxxxxxxxxxxx
OLEAUT32.dll
Import By Ordinal 0n2
Import By Ordinal 0n7
Import By Ordinal 0n8
Import By Ordinal 0n150
Import By Ordinal 0n6
Import By Ordinal 0n9
UxTheme.dll
IsThemeActive
xxxxxxxxxxxxxxx
msvcrt.dll
wcsncmp
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
_wcsrev
------------------------------------------------------------------------------------------------------
UPDATE NUMBER TWO
------------------------------------------------------------------------------------------------------
A new script that uses c++ expressions and array subscripts to parse import address table manually
with array subscripts we can access each of the five dwords in each IMAGE_IMPORT_DESCRIPTOR
so this script can also print the actual address with symbols from te 5th dword
and as such we can also see what the actual imports are for the ordinals
Script as follows
r $t0 = ( ${$arg1} & 0xffff0000 )
.if(@$t0 != 0) {
.if( (poi(@$t0) & 0x0000ffff) == 5A4D ) {
r $t1 = @$t0 + poi(@$t0+0x3c)
.if( (poi(@$t1) & 0x0000ffff) == 4550 ) {
r? $t2=@@c++((((ntdll!_IMAGE_NT_HEADERS *)@@masm(@$t1)))->OptionalHeader.DataDirectory)
r? $t3=@@c++(((unsigned long *)( @$t2[1].VirtualAddress + @@masm(@$t0))))
.for(r $t19 = 0; @$t19 < ((@@c++(@$t2[1].Size) /4 )-5) ; r $t19 = @$t19+0n5 ) {
.printf /D "<b>\n Imports From %ma\n</b>",@@c++(@$t3[3 + @$t19 ] + @$t0)
.printf /D "<b>Address\tNameFromIAT Symbol Resolved</b>\n\n"
r? $t4 = ((unsigned long *) (@@c++(@$t3[0 + @$t19 ] + @@masm( @$t0 ))))
r $t5 = 0
r $t9 = 0
.while ( @@c++(@$t4[@$t5]) != 0) {
r $t6 = @@c++(@$t4[@$t5])
.if(@$t6 & 0x80000000) {
.printf /D "<b>0n%08d\tImport By Ordinal</b>" , @$t6 & 0x0000ffff
.printf " "
.printf "%y\n" , poi(@@c++(@$t3[4 + @$t19 ] + @@masm( @$t0 )) + @$t9)
r $t9 = @$t9+4
} .else {
.printf "%08x\t" ,poi(@@c++(@$t3[4 + @$t19 ] + @@masm( @$t0 )) + @$t9)
.printf "%-40ma" , ( @$t6 + @$t0 +2)
.printf "%y\n" ,poi(@@c++(@$t3[4 + @$t19 ] + @@masm( @$t0 )) + @$t9)
r $t9 = @$t9+4
}
r $t5 = @$t5+1
}
}
} .else {
.printf "IMAGE_NT_SIGNATURE PE NOT FOUND\n"
}
} .else {
.printf "IMAGE_DOS_SIGNATURE MZ NOT FOUND\n"
}
}.else {
.printf "provide an argument usage $$>a< <path to script file> <Address>\n"
}
usage and result as follows
0:000> $$>a< e:\windbgscripts\gimp.txt calc+124c
Imports From SHELL32.dll
Address NameFromIAT Symbol Resolved
76060468 SHGetSpecialFolderPathW SHELL32!SHGetSpecialFolderPathW (76060468)
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
0n00000165 Import By Ordinal SHELL32!SHCreateDirectory (7614dd83)
76061e46 ShellExecuteExW SHELL32!ShellExecuteExW (76061e46)
Imports From SHLWAPI.dll
Address NameFromIAT Symbol Resolved
0n00000225 Import By Ordinal SHLWAPI!SHStripMneumonicW (75ac417a)
Imports From ADVAPI32.dll
Address NameFromIAT Symbol Resolved
76de46c8 RegEnumKeyExW ADVAPI32!RegEnumKeyExWStub (76de46c8)
76de468d RegOpenKeyExW ADVAPI32!RegOpenKeyExWStub (76de468d)
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
7707d9dd EventUnregister ntdll!EtwEventUnregister (7707d9dd)
77085b0c EventRegister ntdll!EtwEventRegister (77085b0c)
Imports From OLEAUT32.dll
Address NameFromIAT Symbol Resolved
0n00000002 Import By Ordinal OLEAUT32!SysAllocString (76c94642)
0n00000007 Import By Ordinal OLEAUT32!SysStringLen (76c94680)
0n00000008 Import By Ordinal OLEAUT32!VariantInit (76c93ed5)
0n00000150 Import By Ordinal OLEAUT32!SysAllocStringByteLen (76c94731)
0n00000006 Import By Ordinal OLEAUT32!SysFreeString (76c93e59)
0n00000009 Import By Ordinal OLEAUT32!VariantClear (76c93eae)
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Imports From msvcrt.dll
Address NameFromIAT Symbol Resolved
76f7b05e wcsncmp msvcrt!wcsncmp (76f7b05e)
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
76fa048d _wcsrev msvcrt!_wcsrev (76fa048d)
Upvotes: 4