PE格式汇总(一)
在PE文件头的可选映像头(IMAGE_OPTIONAL_HEADER)中,数据目录表的第二个成员(Import table)指向输入表。输入表以一个IMAGE_IMPORT_DESCRIPTOR(IID)数组开始。每一个PE文件隐式连接的DLL都有一个IID。IID数组以最后一个全是0的IID结构作为结束。
奇奇怪怪的两张图
图1
图2
这里的两张图都是展示IID的指向方式的,上面的那张图是静态文件下的PE,是由两个并行的指针指向导入函数(IMAGE_IMPORT_BY_NAME)。下面那张是执行状态下被重写后的指向方式,FirstThunk指向函数地址,通过排序和函数对应。
在16进制编辑器内查看
OriginalFirstThunk->INT (当双字的高位为0时,表示以字符串类型的函数名方式输入)
Name:
FirstThunk:
OFT -> OriginalFirstThunk
上述都是在静态模式(PE文件未被加载)的情况下分析的,满足图1情况。
dump 加载后的PE文件
工具:PETools
查看Import Table
16进制编辑器打开PE文件
注:因为这里PE文件已经是完成映射后的,所以不再需要对RVA进行转换FileOffset的操作
同样,还是以第一个为例子
F4 25 00 00 ——>OriginalFirstThunk
00 00 00 00 ——>TimeDateStamp
00 00 00 00 ——>ForwarderChain
8A 26 00 00 ——>Name
34 20 00 00 ——>FirstThunk
这里前面的3个和之前的一样,直接看FirstThunk
未完待续....
struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics;
DWORD OriginalFirstThunk;
};
DWORD TimeDateStamp;
DWORD ForwarderChain;
DWORD Name;
DWORD FirstThunk;
} IMAGE_IMPORT_DESCRIPTOR;
struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics;
DWORD OriginalFirstThunk;
};
DWORD TimeDateStamp;
DWORD ForwarderChain;
DWORD Name;
DWORD FirstThunk;
} IMAGE_IMPORT_DESCRIPTOR;
struct _IMAGE_THUNK_DATA32{
union {
DWORD ForwarderString;
DWORD Function;
/
/
被输入的函数的内存地址
DWORD Ordinal;
/
/
高位为
1
则被输入的API的序数值
DWORD AddressOfData;
/
/
高位为
0
则指向IMAGE_IMPORT_BY_NAME 结构体二
}u1;
}IMAGE_THUNK_DATA32;
/
/
IMAGE_THUNK_DATA64与IMAGE_THUNK_DATA32的区别,仅仅是把DWORD换成了
64
位整数。
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
struct _IMAGE_IMPORT_BY_NAME {
WORD Hint;
/
/
指出函数在所在的dll的输出表中的序号
BYTE Name[
1
];
/
/
指出要输入的函数的函数名
} IMAGE_IMPORT_BY_NAME,
*
PIMAGE_IMPORT_BY_NAME;
struct _IMAGE_THUNK_DATA32{
union {
DWORD ForwarderString;
DWORD Function;
/
/
被输入的函数的内存地址
DWORD Ordinal;
/
/
高位为
1
则被输入的API的序数值
DWORD AddressOfData;
/
/
高位为
0
则指向IMAGE_IMPORT_BY_NAME 结构体二
}u1;
}IMAGE_THUNK_DATA32;
/
/
IMAGE_THUNK_DATA64与IMAGE_THUNK_DATA32的区别,仅仅是把DWORD换成了
64
位整数。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2020-9-22 09:14
被tutuj编辑
,原因: 写错