PE文件格式--------------导入表和IAT
2012-04-28 10:33
597 查看
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文件加载前
pe文件加载后
4)主要代码:
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
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文件加载前
pe文件加载后
4)主要代码:
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
相关文章推荐
- PE文件格式:导入表&IAT——手工重组
- 流水账笔记:PE文件格式(导入表注入---手动)
- PE文件格式:如何恢复导入表
- PE文件格式分析系列(文章1)----一个PE文件导入表数据的分析(MFC工程调试版)
- PE文件学习笔记(五):导入表、IAT、绑定导入表解析
- PE文件学习笔记(五):导入表、IAT、绑定导入表解析
- PE文件格式详解(下)
- 认识PE文件格式-区块表
- 如何将VMWare Workstation 虚拟机文件导入到ESX Server——VMX 转成 OVF 格式
- PE文件格式学习笔记(一) 转自http://blog.csdn.net/hbyufan/
- PE文件格式
- 将.xls文件导入SQL SERVER 2005时报错:外部表不是预期的格式,解决方法
- 深入探究 Win32 PE 文件格式
- Dll注入:修改PE文件 IAT注入
- MySQL如何导入csv格式数据文件解决方案
- PE文件格式,qduwg翻译
- PE文件格式详解(1)
- PE文件格式详解(2)
- 探密PE文件格式(Portable Executable File Format)(上)
- sql中导入*.csv格式文件