本帖最后由 appsion 于 2020-11-2 11:03 编辑
PE 文件解析4-数据目录[导入表]
新手学习PE文件解析记录, 持续更新. 部分参考来源于网络, 无法逐一标注, 如果侵权,请及时联系. 如有错误请指正,误喷.
上文链接: https://www.52pojie.cn/thread-1294832-1-1.html
IAT
Import Address Table, 导入地址表
INT
Import Name Table, 导入名称表
结构体: IMAGE_IMPORT_DESCRIPTOR
说明: 导入表信息
头文件: winnt.h
帮助文档: 仅存在于头文件, 没有帮助文档
参考链接: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
[Asm] 纯文本查看 复制代码
typedef struct _IMAGE_IMPORT_DESCRIPTOR
{
union {
DWORD Characteristics; // 0 for terminating null import descriptor
DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
} DUMMYUNIONNAME;
DWORD TimeDateStamp; // 0 if not bound,
// -1 if bound, and real date\time stamp
// in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
// O.W. date/time stamp of DLL bound to (Old BIND)
DWORD ForwarderChain; // -1 if no forwarders
DWORD Name;
DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses)
} IMAGE_IMPORT_DESCRIPTOR;
typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;
参数说明: 仅供参考, 详细说明请参考原文.
DUMMYUNIONNAME.Characteristics
导入表描述
DUMMYUNIONNAME.OriginalFirstThunk
INT的RVA
TimeDateStamp
时间日期戳.
ForwarderChain
被转向API的索引.
Name
导入DLL库文件名的RVA
FirstThunk
IAT的RVA, IMAGE_THUNK_DATA 结构.
结构体: IMAGE_THUNK_DATA
说明: 导入外部库文件的函数表信息
头文件: winnt.h
帮助文档: 仅存在于头文件, 没有帮助文档
参考链接: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
[Asm] 纯文本查看 复制代码
typedef struct _IMAGE_THUNK_DATA32 {
union {
DWORD ForwarderString; // PBYTE
DWORD Function; // PDWORD
DWORD Ordinal;
DWORD AddressOfData; // PIMAGE_IMPORT_BY_NAME
} u1;
} IMAGE_THUNK_DATA32;
typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;
参数说明: 仅供参考, 详细说明请参考原文.
u1.ForwarderString
转发字符串
u1.Function
导入函数的地址的RVA
u1.Ordinal
导入函数的序号
u1.AddressOfData
导入函数名称的RVA, IMAGE_IMPORT_BY_NAME 结构.
结构体: IMAGE_IMPORT_BY_NAME
说明: 导入外部库文件的函数序号和名称
头文件: winnt.h
帮助文档: 仅存在于头文件, 没有帮助文档
参考链接: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
[Asm] 纯文本查看 复制代码
typedef struct _IMAGE_IMPORT_BY_NAME
{
WORD Hint;
CHAR Name[1];
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
参数说明: 仅供参考, 详细说明请参考原文.
Hint
函数的序号
Name
导入函数名
4.1 获取导入表信息
[Asm] 纯文本查看 复制代码
// 参数说明
// DataBuff: 文件指针
// ImportRVA: 导入表的RVA
IMAGE_IMPORT_DESCRIPTOR *Import = GetImport(DataBuff, ImportRVA);
while (true)
{
if (Import->OriginalFirstThunk == 0 && Import->FirstThunk == 0)
{
break;
}
// 导入表名称
DWORD DllName_RVA = Import->Name;
DWORD DllName_FOA = RVAToRaw(SectionHead, SectionCount, DllName_RVA);
char * DllName = DataBuff + DllName_FOA;
// INT的RVA
DWORD INT_RVA = Import->OriginalFirstThunk;
// IAT的RVA
DWORD IAT_RVA = Import->FirstThunk;
Import++;
}
4.2 获取函数信息
[Asm] 纯文本查看 复制代码
// 注:
// 1. 判断导入方式
// 序号方式导入, IMAGE_THUNK_DATA 值的最高位为1, 低31位值为函数序号.
// 字符串方式导入, IMAGE_THUNK_DATA 的值.
void ImportFunctionInfo(char *DataBuff, DWORD INT_Thunk_RVA, DWORD IAT_Thunk_RVA)
{
while (true)
{
DWORD INT_Thunk_FOA = RVAToRaw(SectionHead, SectionCount, INT_Thunk_RVA);
IMAGE_THUNK_DATA *THUNK = (IMAGE_THUNK_DATA *)(DataBuff + INT_Thunk_FOA);
if (THUNK->u1.Ordinal == 0)
{
break;
}
// 判断导入方式
if (THUNK->u1.Ordinal & IMAGE_ORDINAL_FLAG)
{
// 导入序号
// THUNK->u1.Ordinal - IMAGE_ORDINAL_FLAG;
// INT的RVA
// INT_Thunk_RVA
// IAT的RVA
// IAT_Thunk_RVA
}
else
{
// 获取函数名
DWORD ByName_RVA = THUNK->u1.AddressOfData;
DWORD ByName_FOA = RVAToRaw(SectionHead, SectionCount, ByName_RVA);
IMAGE_IMPORT_BY_NAME *ByName = (IMAGE_IMPORT_BY_NAME*)(DataBuff + ByName_FOA);
// 导入序号
// ByName->Hint
// INT的RVA
// INT_Thunk_RVA
// IAT的RVA
// IAT_Thunk_RVA
}
INT_Thunk_RVA += sizeof(DWORD);
IAT_Thunk_RVA += sizeof(DWORD);
}
}
|