2016-09-19 55 views
1

我試圖解決在我的筆記本上崩潰的舊應用程序。如何解決在無符號轉儲中的dll函數的零指針

望着轉儲文件,我發現它與該指令崩潰: 0044e381 ff1538b57b00 call dword ptr [appname+0x3bb538 (007bb538)]

因瑣事原因: 0:000> dp 0x007bb538 007bb538 00000000 00000000 00000000 00000000

如果我理解正確的,它是一個函數的調用的某個DLL不知何故加載。如果我有符號,我可能會看到像_impl_!blahblahblah這樣的東西來幫助我猜這是什麼。唉,事實並非如此。

所以問題是:如何確定它試圖調用哪個dll?

+0

你可以嘗試'lm'並看看在卸載DLL的。運氣好的話,地址只能在一個卸載的dll的地址空間中匹配。 –

+0

@LievenKeersmaekers:我在彙編語言方面不是太深,但編譯器能否將調用解析爲一個FF15 CALLN指令的DLL?這需要知道DLL在地址空間中的加載位置。我無法在對LoadLibrary()或LoadLibraryEx()的調用中指定地址。 –

+0

如果問題是可重現的,則可以使用Process Monitor和[ProcMon Log Analyzer](http://debugging.wellisolutions.de/procmonanalyzer/) –

回答

4

拆卸與符號

0:000> u calc!AllocNumString+20 l1 
calc!AllocNumString+0x20: 
00083801 ff154c120800 call dword ptr [calc!_imp__LocalAlloc (0008124c)] 

讓卸載符號

0:000> .reload /u calc 
Unloaded calc 

拆卸不帶符號

0:000> u 83801 l1 
00083801 ff154c120800 call dword ptr ds:[8124Ch] 

0:000> $$你想知道什麼8124c是/可能指向
,你認爲它可能是一個進口
0:000> $$免得獲取導入表的地址和大小,看看這個假設是真的

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> $$檢查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> $$所以IMAGE_IMPORT_DESCRIPTORS如下

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> $$你可以找到每個IID第四DWORD各自的動態鏈接庫(它RVA添加基址的話)

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> $$的第五個dword(第一個thunk)將保存每個dll的進口開始

0:000> $$因此124c位於kernel32中的1144和12a8之間。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是第43屆進口

0:000> ? ((124c-1144) /4) + 1 
Evaluate expression: 67 = 00000043 

而且

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
---------------------------------------------- ---

內置的!進口<模塊>命令不能沒有,所以我必須使用類似於被張貼以上
一些腳本自從這個問題上來,我試圖刪除符號
工作來自
腳本的硬編碼黑客添加了一些黑客進口順序和後在這裏可能是有用的

腳本如下

$$ input to the script ; r $t0=${$arg1}; .printf /D "<b>Input\t%x\n</b>",@$t0 
$$ mask for ibase ; r [email protected]$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 [email protected]$t4 

.printf /D "<b>\nRespective dlls from 4th DWORD of IID\n\n</b>" 
.foreach /pS 4 /ps 5 (place {dd /c 5 @$t3 [email protected]$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 [email protected]$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 ,(@[email protected]$t1+2),(@[email protected]$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(@[email protected]$t6) ; r $t8 = @[email protected]$t1 ; 
    .printf /D "<b>\n%ma\n\n</b>" , (poi(@[email protected]$t6+0xc)[email protected]$t1) 
    .while(poi(@$t8)!=0) { 
     r $t9 = (poi(@$t8)[email protected]$t1); 
     .if(@$t9 & 0x80000000) { 
      .printf /D "<b>Import By Ordinal 0n%d\n</b>" , (@$t9 & 0000ffff) 
     }.else { 
      .printf "%ma\n", (poi(@$t8)[email protected]$t1)+2 
     } 
     r $t8 = @$t8+4; 
    } 
} 

使用0:000> $$>一個< X:\ getimp。TXT f1124c

應導致

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二號
- -------------------------------------------------- --------------------------------------------------

使用C++表達式和數組下標來解析導入地址表的新腳本手動
與我們可以訪問每五個雙字的每個IMAGE_IMPORT_DESCRIPTOR數組下標
因此該腳本還可以打印帶有符號的實際地址從TE 5 DWORD
,因此我們也可以看到實際進口爲序

腳本如下

r $t0 = (${$arg1} & 0xffff0000) 
.if(@$t0 != 0) { 
    .if((poi(@$t0) & 0x0000ffff) == 5A4D) { 
    r $t1 = @$t0 + poi(@$t0+0x3c) 
    .if((poi(@$t1) & 0x0000ffff) == 4550) { 
     r? [email protected]@c++((((ntdll!_IMAGE_NT_HEADERS *)@@masm(@$t1)))->OptionalHeader.DataDirectory) 
     r? [email protected]@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" 
} 

的使用和產生如下

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) 
+0

謝謝!很徹底。我能夠使用!dh來到IAT,但缺乏知識(和時間到谷歌)不允許我檢查它是否是導入。原來,這是一個opengl黑魔法。在工作轉儲中,它指向英特爾視頻驅動程序。並再次查看該地址,它位於'.data' ... – Dmitry

+0

通常導入確實坐在.data節中,除非這些節被合併到一個合併到鏈接器swutch中,這將是calc.exe中的情況上面的示例 – blabb

+0

在我的轉儲中,它位於.rdata節。在任何情況下,都沒有提及它在應用程序中調用的模塊。看一下工作環境的轉儲,它會調用'ig4dev32.dll'(或其他ig4 * 32.dll,現在不能檢查),我猜是通過opengl運行時加載的......然後,運行時將初始化位於.data中的函數指針,並將其初始化爲零。 (我再次猜測:-(我試圖用'ba'來看看在工作環境中會發生什麼,但它是一個DRM遊戲,它不能容忍調試......) – Dmitry