PE文件加载过程揭秘(2)

2011年10月09日 星期日 16:23

转载自 cvvd
最终编辑 cvvd


图1

PE加载器在完成文件实体数据到内存虚拟数据的映射之后,便开始从位于IMAGE_OPTION_HEADER末端的IMAGE_DATA_DIRECTORY数组的第2项(如图2),取出输入表的RVA和大小,准备开始输入函数的初始化。输入表的RVA实际上是指向一个以IMAGE_IMPORT_DESCRIPTOR为元素的数组,该数组以一个全零的结构作为结尾。


2


图3

 

从该结构(如图3)的Name字段,可以推测每一个该结构都只能描述一个动态库,事实上也是如此。

其中OriginalFirstThunkFristThunk都是IMAGE_THUNK_DATA32RVA,它们如此相像不是巧合,因为在本质上它们所描述的信息是一致的。如图4我们可以清楚的看出OriginalFristThunkFristThunk是不同的值。

4

但实际上它们如描述的RVA却是相同的如图5OriginalFirstThunk)和6FirstThunk)。

 


5

 


6

PE加载器一般会从OriginalFirstThunk读取输入函数的信息(如果OriginalFirstThunk0则从FirstThunk处读取),并将它(输入函数)的地址填入FristThunk所描述的RVA处,你一定想问一个动态库的输入函数不一定只有一个,那其他的函数应该怎么办?其实答案很简单,OriginalFirstThunkFristThunk所存储的RVA都是一个数组的起始位置,PE加载器只需要每处理一对输入信息就将指针下移4个字节即可,谈到输入表,你一定会想到IATImport address table),其实你只要足够细心就会发现第一个输入表描述符中的FristThunkIAT的表头是同一个RVA,这足以证明PE加载器实际上是在完成IAT表的填写工作。那么原来存储在IAT所描述的RVA处的数据又是什么呢?在本测试程序上IAT的地址是2000H也就是文件偏移E00H。即PE文件的映射基址+2000H开始的数据也就是图6上的数据将被系统填充为输入函数的地址,该过程也就是传说中的填写IAT

我们再来看看图56中描述的数据是什么,EA210000FC21000也就内存RVA000021EA000021FC,我们将第一个000021EA转换中文件偏移,也就是21EA-2000+E00=FEAh

可以看到此处的数据都是一个IMPORT_BY_NAME结构。如图78
7

 

8

这样输入函数名和输出序号就都有了,PE加载器接下来的工具就跟我们平时动态加载一个DLL获取其输出函数差不多了:PE通过调用LoadLibrary+DLL名加载所需要的动态库,并根据OriginalFirstThunk描述的RVA找到IMAGE_IMPORT_BY_NAME结构指针数组,然后循环遍历该组,为该DLL导入的所有函数填写地址,之后PE加载器会继续遍历下一个DLL直到遇到一个全零的IMAGE_IMPORT_DESCRIPTOR结构结束输入函数初始化,完成IAT的构建。

转载于:https://www.cnblogs.com/maixiaokou/archive/2012/07/08/2581252.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值