Jirairya

PE之IAT


IAT,Import Address Table,导入地址表。IAT是一种表格,用来记录程序正在使用哪些库中的哪些函数。IAT保存的内容与Windows操作系统的核心进程、内存、DLL结构等有关。

DLL

DLL,Dynamic Link Library,动态链接库。

  • 不要把库包含到程序中,单独组成DLL文件,需要时调用即可.
  • 内存映射技术使加载后的DLL代码,资源在多个进程中实现共享.
  • 更新库时只要替换相关DLL文件即可.

加载DLL文件时有两种方式 : 一种是”显式链接”(Explicit Linking),程序使用DLL时加载,使用完毕后释放内存;另一种是”隐式链接(Implicit Linking)”,程序开始时即一同加载DLL,程序终止时再释放占用的内存.

实际操作中无法保证DLL一定会被加载到PE头指定的ImageBase处,但是EXE文件(生成的进程主体)却能准确加载到自身的ImageBase中,因为它拥有自己的虚拟空间。

IMAGE_IMPORT_DESCRIPTOR

IMAGE_IMPORT_DESCRIPTOR结构体中记录着PE文件要导入那些库文件.

  • Import : 导入,向库提供服务(函数)
  • Export : 导出,从库向其他PE文件提供服务(函数)

执行一个普通程序时往往需要导入多个库,导入多少库就存在着多少个IMAGE_IMPORT_DESCRIPTOR结构体,这些结构体形成了数组,且结构体数组最后以NULL结构体结束。

IMAGE_IMPORT_DESCRIPTOR中的重要成员:

项目 含义
OriginalFirstThunk INT的地址(RNA)
Name 库名称字符串的地址(RVA)
FirstThunk IAT的地址(RVA)
  • PE头中提到了提到的table是数组
  • INT与IAT是长整型数组(4字节),以NULL结束(未另外明确指出大小)
  • INT中各元素的值为IMAGE_IMPORT_BY_NAME结构体指针(有时IAT也拥有相同的值)
  • INT与IAT的大小应相同

** PE装载器把导入函数输入至IAT的顺序**

  1. 读取IID的NAME 成员,获取扩名称字符串
  2. 装载相应库: LoadLibrary(“kernel32.dll”)
  3. 读取OriginalFirstThunk成员,获取INT 地址
  4. 逐一读取INT 数组中的值,获取相应的 IMAGE_IMPORT_BY_NAME地址(RVA)
  5. 使用IMAGE_IMPORT_BY_NAME 的Hint 或者是Name 项,获取相应函数的起始地址。 ->GetProcAddress(“GetCurrentThreadId”)
  6. 读取IID的FistrThunk 成员,获得IAT 地址。
  7. 将上面获得的函数地址输入相应IAT 数组值。
  8. 重复4-7步骤,到INT 结束。(遇到NULL时)

上一篇 PE之EAT

下一篇 PE

Comments

Content