PE文件中的输入表

Posted revercc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PE文件中的输入表相关的知识,希望对你有一定的参考价值。

前言

PE文件中的输入表含有三个重要结构IID,IDT,IAT。PE文件为需要加载的DLL文件创建一个IID结构,一个DLL与一个IID对应。IDT是输入名称表,IAT输入地址表,在没有绑定输入的情况下磁盘中的文件IDT与IAT相同。

函数隐式链接

我们一般在调用函数的时候都是直接用函数的名称,例如Message()这种其在底层汇编指令上并不是直接调用Message()函数的地址而是调用IAT中对应函数的地址(也就是函数的地址实际存放在IAT中)。一般在PE文件加载进入内存时,windows加载器会根据IDT(如果IDT为空就根据IAT)的函数信息在对应的DLL中查询实际函数的地址,然后重写到IAT中。也就是在加载到内存前IAT与IDT存储的都是输入函数的信息,并不包含函数的实际地址。只有当windows加载器将PE文件加载到内存后IAT中才会存放函数的实际地址,而我们实际调用函数的指令会指向这对应的IAT中函数的位置,完成函数的调用。这种方式称为函数隐式链接(是由windows加载器完成的)。

函数显式链接

如果我们调用函数的时候不直接使用函数名称,而是使用LoadLibrary()和GetProcAddress()函数在运行时动态获取函数的地址,这种函数调用根本不依赖于IAT,称为显示链接。
注意当我们自己的代码直接使用LoadLibrary()和GetProcAddress()函数时其汇编代码就是调用对应的函数地址。

函数绑定输入

对于函数隐式链接而言,因为需要在PE文件加载到内存时通过INT中的函数信息从DLL中获取函数的地址然后写到IAT中,这效率很低。如果我们能让PE文件在没加载到内存时就确定对应IAT中函数的地址的话就可以大大提高效率,这种就称为绑定输入函数。为了防止绑定输入的函数对应的dll发生改变造成函数调用出错,PE文件有对应的绑定输入表可以通过数据目录表访问,在PE文件加载到内存时windows加载器会依据绑定输入表中的信息与加载的dll的信息进行对比,如果发现不一致则会重新改写IAT。

延迟加载

延迟加载包括延迟加载函数(就是函数的显示链接),还有就是延迟加载DLL。延迟加载dll需要在链接器进行设置,这样会在数据目录表中的延迟加载表中形成对应的数据结构包含对应的IAT和IDT,此IAT和IDT与正常的IAT和IDT一样只不过此IAT不是windows加载器写入的。这样在第一次调用延迟加载的其中一个函数时运行库就会调用LoadLibrary()和GetProcAddress()写入此IAT,然后以后调用此函数都会来到此IAT处。注意区分延迟加载函数和延迟加载dll。

隐式,显式,绑定输入和延迟加载在HOOK中的使用

因为显式链接不依赖与IAT所以IAT_HOOK对其进行无效,而对于延迟加载的dll需要在其对应的延迟加载dll的IAT处HOOK。对于EAT_HOOK来说对四种种形式都有效。

区分动态/静态编译 与 显式/隐式链接

注意动态编译是指将对应Dll中的信息保存到PE文件的IID中,然后调用的函数信息存在IAT和IDT中。当PE文件加载到内存中时将IID对应的DLL加入到内存中进一步完成函数的调用。而静态编译是将函数对应的dll中的代码全部整合到PE文件中,这样函数的调用就不依赖于DLL也不会形成对应的IID。(不要将动态/静态编译 与 显示/隐式链接搞混)


以上是关于PE文件中的输入表的主要内容,如果未能解决你的问题,请参考以下文章

PE文件格式详解

PE文件格式详解

[DLL注入的方法]进程创建期修改PE输入表法

《VC驿站《PE文件格式解析》》

《初识PE》导出表

PE知识复习之PE的导出表