首先就是确定如何定位导入表的位置,导入表是位于数据目录项的第二项
前四个字节为相对虚拟地址(RVA),后四个字节为大小(这里做个参考,不依赖)
好了,既然是RVA,那么说的就是内存中情况,那么如何在文件中定位到导入表位置呢,这里我们则需要做的就是将RVA转换为FA,这里的话就大致来说明一下,不清楚的可以参考下其他博客
先来看一下节区的分布情况,有2个节,分别在0x1000处和0x2000处,大小都为0x1000
RVA=2020
1.查找RVA位于哪个节区内
这里很明显位于.rdata内,该段起始为0x2000
2.计算节内偏移
也就是减去该节起始地址(0x2000) = 0x20
3.加上该节的文件起始偏移
0x20 + 0x400 = 0x420
所以我们来看一下文件偏移为0x420的地方
此时我选中的部分就是导入表的位置了。下面先不着急来分析字段,我们先来探讨一下为什么需要导入表?
在我们程序运行的时候,可能需要调用一些外部接口,比如说动态库,说到动态库,很容易想到两个API
LoadLibrary //加载动态库
GetProcAddress //获取模块内函数地址
是的,我们可以使用上面两个API来获取到模块中函数地址,并调用,那么问题来了,这个地址可以写死么?
答案是不可以的,因为该程序放到其他环境中运行时,该函数地址可能是会发生变化的,所以该这么办呢?
这里的话就涉及到了编译器与操作系统之间的交互了,编译器会生成间接调用的代码(留IAT接口),操作系统在装载应用程序时会填写该值,这样子就保证了正确的函数指针了。有点抽象,下面来看一下这段汇编代码
00401000 >/$ 6A 00 push 0 ; Style = MB_OK|MB_APPL