第四章 导入表
导入表是PE数据组织中的一个很重要的组成部分,它是为实现代码重用而设置的。通过分析导入表数据,可以获得诸如OE文件的指令中调用了多少外来函数,以及这些外来函数都存在于哪些动态链接库里等信息。Windows加载器在运行PE时会将导入表中声明的动态链接库一并加载到进程的地址空间,并修正指令代码中调用的函数地址。在数据目录中一共有四种类型的数据与导入表数据有关: 导入表、导入函数地址表、绑定导入表、延迟加载导入表。
4.1何为导入表
当程序调用了动态链接库的相关函数,在进行编译和链接的时候,编译程序和链接程序就会将调用的相关信息写入最终生成的PE文件中,以告诉操作系统这些函数的执行指令字节码从哪里能够获取。这些信息就是导入表所要描述的内容。
4.2导入函数
程序开发者在基于汇编语言的源程序中,通过invoke指令调用用户自定义的函数,或者从其他动态链接库中导入的函数。
4.2.1 invoke指令分解
在汇编语言中,程序一旦被编译,编译器会对invoke指令进行适当分解。分解后的指令中将会包含指向导入函数的地址的操作数。当PE文件被装载到内存中时,该操作数就会变成导入函数所在虚拟地址真实的VA。
使用OD打开HelloWorld.exe程序,查看汇编后的字节码以及相关调用如下:
书上的OD结果:
自己本地C++写的一个的OD结果:
VS2012 反汇编结果:
以书上的为解释例子:
将原代码中两个导入函数MessageBoxA和ExitProcess的调用语句解释成字节码分别为:
从指令的反汇编代码中可以看出,以第一个调用为例,对invoke指令的分解操作包含以下三步:
1.压栈。即先将要调用的所有参数push到栈中。(反向顺序压栈)。
2.段内调用。即通过指令call调用一个段内地址,既call 00401018。
3.无条件转移。call指令操作数0x00401018处的值是:FF25 28204000,该字节码反汇编,得到一个无条件跳转指令,跳转到了位置0x00402008处。
(从位置00402008处获取的值是导入函数MessageBoxA在内存中的VA。)
4.2.2 导入函数地址
导入函数是从动态链接库引入的函数,所以,导入函数地址位于被加载的进程地址空间的相应的动态链接库模块内。系统在执行用