PE文件格式詳解(六)
0x00 前言
前面兩篇講到了輸出表的內容以及涉及如何在hexWorkShop中找到輸出表及輸入DLL,感覺有幾個地方還是沒有理解好,比如由數據目錄表DataDirectory[16]找到輸出表表後以為找到輸入DLL就完了,其實這一流程的最終功能是通過輸入DLL找到輸入DLL調用的函數,這一步驟是通過輸出表結構中的OriginalFristThunk或者OriginalFristThunk所指向的INT或者IAT結構來找到的。這裏要說明的是,雖然一般情況通過OriginalFristThunk也行,但是有些情況下它的值被設置為0了,這樣就無法利用了,最委托的的方式是通過FristThunk所指向的
0x01 找尋輸入DLL以及輸入DLL調用的函數
材料及工具:名為PE.exe的可執行文件,工具hexWrokshop,LordPE
思路:找到PE文件頭——》找到數據目錄表第二項——》通過地址轉換找到輸出表數組——》逐個讀出輸出表數組的OriginalFristThunk,FristThunk值——》通過INT或者IAT逐個讀出被調用函數的名字地址——》通過名字地址找到函數名。
1)將目標文件拖入hexWrokShop,快捷鍵ctrl+g跳往載入地址的3ch處,這裏即PE文件頭地址,如下圖:
2)跳往40h處,該處即為文件頭,如下圖:
3)跳往PE文件頭+80h處,該處存儲了輸入數據表的地址如下圖:
4)將RVA=2040h轉化位FileOffset地址,這裏我們利用lordpe協助轉化,轉化後值為440h。
5)跳轉至440h處,該處即為輸出表IID數組的數據所在,每項為五對雙字組成,結尾以五對雙字0。我這個實例一共兩組,如下圖:
將以上根據字段數據統計如下表(PS:由於hex中是由低位到高位的故統計時應該註意高低位的換位):
OriginalFristThunk |
TimeStamp |
ForwardChain |
Name |
FristThunk |
0000208C |
00000000 |
00000000 |
00002174 |
00002010 |
0000207C |
00000000 |
00000000 |
000021B4 |
00002000 |
利用表中的Name字段我們可以直接推出輸入DLL的名字,第一項Name的RVA為2174h,轉化為FileOffset值為:574h,跳往574h,我們可以看到第一個DLL為USER32.DLL,如下圖:
第二項的Name值為RVA值為21B4h,轉化位FileOffset值為5B4h,跳往574h,我們知道第二項DLL為KERNEL32.DLL,如下圖:
6)知道了輸入DLL不是我們目的終點,我們還要知道DLL所調用的所有函數名字地址,這裏有兩個字段可用,第一個是OriginalFristThunk,它所指向的是一個名為輸入名稱表(INT)的結構,這個結構是由多個IMAGE_THUNK_DATA結構所組成的數組。第二個是FristThunk,它所指向的是一個名稱為輸入地址表的(IAT)的結構,這個結構也是有多個IMAGE_THUNK_DATA結構所組成的數組。IMAGE_THUNK_DATA雙字數組的每項指向另一個結構——IMAGE_IMPORT_BY_NAME。最終通過IMAGE_IMPORT_BY_NAME找到被DLL調用的函數。一般而言,這兩個被指向的數組值是相等的。我們接下來分別用兩個字段來查找。我們先用第一項的OriginalFristThunk來試試,將208C轉化為FileOffset得48ch。掉跳往48ch,的如下圖結果,共十一項,以雙字0結尾。
我們用FristThunk來試試,將2010h轉化為FileOffset得410h,跳往410h,可得下圖:
它們的值都為:
102100001C210000F4200000E0200000502100006421000002210000CE200000BC2000002E21000042210000,將數據按八個字節拆分與翻轉的下表:
第一項指向的IAMGE_THUNK_DATA數組
00002110 |
0000211C |
000020F4 |
000020E0 |
00002150 |
00002164 |
00002102 |
000020CE |
000020BC |
0000212E |
00002142 |
|
|
|
|
|
接下來進行地址轉換,的下表:
510 |
51c |
4f4 |
4e0 |
550 |
564 |
502 |
4ce |
4bc |
52e |
542 |
|
7)由上表逐個查詢出被調用函數名,如下圖:
重復以上操作的下表:
RVA |
FileOffset |
Hint |
函數名 |
00002110 |
510 |
019B |
LoadIconA |
0000211C |
51c |
01DD |
PostQuitMessage |
000020F4 |
4f4 |
0128 |
GetMessageA |
000020E0 |
4e0 |
0094 |
DispatchMessageA |
00002150 |
550 |
027D |
TranslateMessage |
00002164 |
564 |
028B |
UpdateWindow |
00002102 |
502 |
0197 |
LoadCursorA |
000020CE |
4ce |
0083 |
DefWindowProcA |
000020BC |
4bc |
0058 |
CreateWindowExA |
0000212E |
52e |
01EF |
RegisterClassExA |
00002142 |
542 |
0265 |
ShowWindow |
|
|
|
|
8)當然你可能會覺得這樣找輸入表實在太麻煩了,確實是,但是只有經過這樣找你才能弄明白輸出表到底是如何存放的轉換的,從而對PE文件格式有更為透徹理解。接下來我們通過強大的lordPE來輕松查找到輸入表和輸入函數。如下圖:
0x02 總結
這兩天看加密與解密收獲很大,對於對逆向破解的朋友我強烈建議讀一讀此書,有相同興趣的朋友歡迎評論留言交流。
PE文件格式詳解(六)