pe文件導入表
1)提取導入表:在數據目錄的中,索引為1的位置;
導入表起始RVA地址:IMAGE_NT_HEADER.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
導入表大小:IMAGE_NT_HEADER.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualSize
2)導入表結構:一個導入庫對應下面的一個結構,pe文件引用了幾個導入庫文件就有幾個這樣的結構,最后以全0值結構結束。當pe在磁盤中時,結構中的兩個域OriginalFirstThunk和FirstThunk都指向IMAGE_THUNK_DATA,當pe加載准備運行時,前者仍然指向IMAGE_THUNK_DATA,后者則有裝載器修改為指向導入函數實際地址。
IMAGE_IMPORT_DESCRIPTOR struc
+00h OriginalFirstThunk: dd ;存放RVA,該RVA指向一個IMAGE_THUNK_DATA結構數組,該數組占4字節,以全0值結尾
+04h DateTimeStamp: dd
+08h ForwarderChain: dd
+0ch Name1: dd ;存放RVA,該RVA指向dll名字,該名字已0結尾
+10h FirstThunk: dd ;存放RVA,該RVA指向一個IMAGE_THUNK_DATA結構數組,該數組占4字節,以全0值結尾
IMAGE_IMPORT_DESCRIPTOR ends
IMAGE_THUNK_DATA struc
union
{
ForwarderString: dd
Function: dd
Ordinal: dd ;序號
AddressOfData: dd ;指向IMAGE_IMPORT_BY_NAME
}
IMAGE_THUNK_DATA ends
IMAGE_IMPORT_BY_NAME struc
Hint: dw ;函數序號,但有的編譯器不用此域
Name1: db ;函數名稱,以0結尾
IMAGE_IMPORT_BY_NAME ends
3)IAT導入地址表
pe裝載后,導入表的第0項的FirstThunk指向的RVA,即為導入地址表的起始位置。
另一種更便捷的導入表提取方法是:數據目錄的IMAGE_DIRECTORY_ENTRY_IAT
4)導入表圖解
pe文件加載前

RvaToOffset.asm
;======================
;將RVA轉化為pe文件偏移
;by 紫陌
;======================
_RvaToOffset proc _lpImageBase, _lpRva
local @offsetFile
pushad
xor eax, eax
mov @offsetFile, eax
;*******************
;判斷是否為pe文件
;*******************
mov edi, _lpImageBase
assume edi:ptr IMAGE_DOS_HEADER
.if [edi].e_magic != IMAGE_DOS_SIGNATURE
xor eax, eax
jmp _overpos
.endif
add edi, [edi].e_lfanew
assume edi:ptr IMAGE_NT_HEADERS
.if [edi].Signature != IMAGE_NT_SIGNATURE
xor eax, eax
jmp _overpos
.endif
;*********************
;edi指向節表
;*********************
movzx ecx, [edi].FileHeader.NumberOfSections
movzx ebx, [edi].FileHeader.SizeOfOptionalHeader
add edi, 4
add edi, sizeof IMAGE_FILE_HEADER
add edi, ebx
assume edi:ptr IMAGE_SECTION_HEADER
mov ebx, _lpRva
.while ecx
mov edx, [edi].VirtualAddress
add edx, [edi].Misc.VirtualSize
.if ebx >= [edi].VirtualAddress && ebx <= edx
sub ebx, [edi].VirtualAddress
mov eax, [edi].PointerToRawData
add eax, ebx
mov @offsetFile, eax
jmp _overpos
.endif
add edi, sizeof IMAGE_SECTION_HEADER
dec ecx
.endw
_overpos:
assume edi:nothing
popad
mov eax, @offsetFile
ret
_RvaToOffset endp
processpefile_import.asm
;=====================
;處理pe文件導入表
;by 紫陌
;=====================
;=====================
;數據段
;=====================
.const
szTitleImportTable db 'Import Descriptor (%08X)', 0dh, 0ah, 0
szImportDescriptor db 0dh, 0ah, '*****************ImportDescriptor************************', 0dh ,0ah
db 'OriginalFirstThunk (%08X):%08X', 0dh, 0ah
db 'TimeDateStamp (%08X):%08X', 0dh, 0ah
db 'ForwarderChain (%08X):%08X', 0dh, 0ah
db 'Name1 (%08X):%08X->%s', 0dh, 0ah
db 'FirstThunk (%08X):%08X', 0dh, 0ah, 0
szTitleOrignialFirstThunk db '-----------------OriginalFirstThunk-------------------------', 0dh ,0ah, 0
szThunkData db 'Addresss or Order (%08X):%08X', 0dh, 0ah, 0
szImportByName db ' -->ImportByName (%08X):%04X %s', 0dh ,0ah, 0
szTitleFirstThunk db '-------------------FirstThunk-------------------------', 0dh ,0ah, 0
;=====================
;代碼段
;=====================
.code
_ProcessPeFile_Import proc _lpImageBase
local @szBuf[512]:BYTE
local @szDllName:DWORD
local @ThunkFlag:BYTE
pushad
;**********************
;edi指向導入表
;**********************
mov edi, _lpImageBase
assume edi:ptr IMAGE_DOS_HEADER
add edi, [edi].e_lfanew
assume edi:ptr IMAGE_NT_HEADERS
mov eax, [edi].OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT * sizeof IMAGE_DATA_DIRECTORY].VirtualAddress
invoke _RvaToOffset, _lpImageBase, eax
mov edi, eax
add edi, _lpImageBase
assume edi:ptr IMAGE_IMPORT_DESCRIPTOR
invoke RtlZeroMemory, addr szShowMsg, sizeof szShowMsg
;***********************
;輸出導入表首地址
;***********************
invoke wsprintf, addr @szBuf, addr szTitleImportTable, edi
invoke lstrcpy, addr szShowMsg, addr @szBuf
;***********************
;循環輸出IMAGE_IMPORT_DESCRIPTOR
;***********************
.while !(([edi].OriginalFirstThunk == 0) && ([edi].TimeDateStamp == 0) && ([edi].ForwarderChain == 0) && ([edi].Name1 == 0) && ([edi].FirstThunk == 0))
invoke _RvaToOffset, _lpImageBase, [edi].Name1
add eax, _lpImageBase
mov @szDllName, eax
invoke wsprintf, addr @szBuf, addr szImportDescriptor, \
addr [edi].OriginalFirstThunk, [edi].OriginalFirstThunk, \
addr [edi].TimeDateStamp, [edi].TimeDateStamp, \
addr [edi].ForwarderChain, [edi].ForwarderChain, \
addr [edi].Name1, [edi].Name1, @szDllName, \
addr [edi].FirstThunk, [edi].FirstThunk
invoke lstrcat, addr szShowMsg, addr @szBuf
invoke SetWindowText, hRichEdit, addr szShowMsg
;***************************
;根據OriginalFirstThunk循環輸出IMAGE_THUNK_DATA和IMAGE_IMPORT_BY_NAME
;***************************
invoke lstrcat, addr szShowMsg, addr szTitleOrignialFirstThunk
mov @ThunkFlag, 0
invoke _RvaToOffset, _lpImageBase, [edi].OriginalFirstThunk
add eax, _lpImageBase
mov esi, eax
_OriginalFirstThunk:
.while (DWORD ptr [esi]) != 0
invoke wsprintf, addr @szBuf, addr szThunkData, \
esi, \
DWORD ptr [esi]
invoke lstrcat, addr szShowMsg, addr @szBuf
mov eax, [esi]
test eax, 80000000h
jnz @F
invoke _RvaToOffset, _lpImageBase, eax
add eax, _lpImageBase
mov ebx, eax
add ebx, 2
movzx ecx, WORD ptr [eax]
invoke wsprintf, addr @szBuf, addr szImportByName, \
eax, \
ecx, \
ebx
invoke lstrcat, addr szShowMsg, addr @szBuf
@@:
add esi, 4
invoke SetWindowText, hRichEdit, addr szShowMsg
.endw
.if @ThunkFlag == 1
jmp _continuewhile
.endif
;***************************
;根據FirstThunk循環輸出IMAGE_THUNK_DATA和IMAGE_IMPORT_BY_NAME
;***************************
invoke lstrcat, addr szShowMsg, addr szTitleFirstThunk
mov @ThunkFlag, 1
invoke _RvaToOffset, _lpImageBase, [edi].FirstThunk
add eax, _lpImageBase
mov esi, eax
jmp _OriginalFirstThunk
_continuewhile:
add edi, sizeof IMAGE_IMPORT_DESCRIPTOR
.endw
assume edi:nothing
popad
ret
_ProcessPeFile_Import endp
_ProcessPeFile_IAT proc _lpImageBase
local @szBuf[512]:BYTE
local @NumOfIAT
pushad
;********************
;edi指向IAT表
;********************
mov edi, _lpImageBase
assume edi:ptr IMAGE_DOS_HEADER
add edi, [edi].e_lfanew
assume edi:ptr IMAGE_NT_HEADERS
mov eax, [edi].OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT * sizeof IMAGE_DATA_DIRECTORY].VirtualAddress
invoke _RvaToOffset, _lpImageBase, eax
add eax, _lpImageBase
mov ecx, [edi].OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT * sizeof IMAGE_DATA_DIRECTORY].isize
shr ecx, 2
mov @NumOfIAT, ecx
mov edi, eax
assume edi:ptr IMAGE_THUNK_DATA
invoke lstrcat, addr szShowMsg, addr szTitleIAT
mov ecx, @NumOfIAT
.while ecx
mov @NumOfIAT, ecx
invoke wsprintf, addr @szBuf, addr szIAT, \
edi, \
[edi].u1.AddressOfData
invoke lstrcat, addr szShowMsg, addr @szBuf
mov ecx, @NumOfIAT
add edi, 4
dec ecx
.endw
invoke SetWindowText, hRichEdit, addr szShowMsg
assume edi:nothing
popad
ret
_ProcessPeFile_IAT endp