小甲鱼PE详解之输入表(导入表)详解2(PE详解08)
在上一节课我们像小鹿一样的乱撞,终于撞到了输入表里边包含的函数名称,嘿嘿,不过地址,我们还是没能找着……这节课我们将深入来剖析输入表的结构,通过结合实例分析来帮助大家理解输入表的工作原理。
输入表结构
回顾一下,在 PE文件头的 IMAGE_OPTIONAL_HEADER 结构中的 DataDirectory(数据目录表) 的第二个成员就是指向输入表的。而输入表是以一个 IMAGE_IMPORT_DESCRIPTOR(简称IID) 的数组开始。每个被 PE文件链接进来的 DLL文件都分别对应一个 IID数组结构。在这个 IID数组中,并没有指出有多少个项(就是没有明确指明有多少个链接文件),但它最后是以一个全为NULL(0)
的 IID 作为结束的标志。
IMAGE_IMPORT_DESCRIPTOR 结构定义如下:
IMAGE_IMPORT_DESCRIPTOR STRUCT
OriginalFirstThunk DWORD ?
ends
TimeDateStamp
DWORD ?
ForwarderChain
DWORD ?
Name
DWORD ?
FirstThunk
DWORD ?
IMAGE_IMPORT_DESCRIPTOR ENDS
成员介绍:
OriginalFirstThunk
它指向first thunk,IMAGE_THUNK_DATA,该 thunk 拥有 Hint 和 Function name 的地址。
TimeDateStamp
该字段可以忽略。如果那里有绑定的话它包含时间/数据戳(time/data stamp)。如果它是0,就没有绑定在被导入的DLL中发生。在最近,它被设置为0xFFFFFFFF以表示绑定发生。
ForwarderChain
一般情况下我们也可以忽略该字段。在老版的绑定中,它引用API的第一个forwarder chain(传递器链表)。它可被设置为0xFFFFFFFF以代表没有forwarder。
Name
它表示DLL 名称的相对虚地址(译注:相对一个用null作为结束符的ASCII字符串的一个RVA,该字符串是该导入DLL文件的名称,如:KERNEL32.DLL)。
FirstThunk
它包含由IMAGE_THUNK_DATA定义的 first thunk数组的虚地址,通过loader用函数虚地址初始化thunk。在Orignal First Thunk缺席下,它指向first thunk:Hints和The Function names的thunks。
这个OriginalFirstThunk 和 FirstThunk明显是亲家,两家伙首先名字就差不多哈。那他们有什么不可告人的秘密呢?来,我们看下面一张图(画的很辛苦,大家仔细看哈):

我们看到:OriginalFirstThunk 和 FirstThunk
他们都是两个类型为IMAGE_THUNK_DATA 的数组,它是一个指针大小的联合(union)类型。每一个IMAGE_THUNK_DATA 结构定义一个导入函数信息(即指向结构为IMAGE_IMPORT_BY_NAME
的家伙,这家伙稍后再议),然后数组最后以一个内容为0 的 IMAGE_THUNK_DATA 结构作为结束标志。
我们得到 IMAGE_THUNK_DATA
结构的定义如下:
IMAGE_THUNK_DATA
STRUC
union u1
ForwarderString DWORD ? ; 指向一个转向者字符串的RVA
Function DWORD ? ; 被输入的函数的内存地址
Ordinal DWORD ? ; 被输入的API
的序数值
AddressOfData DWORD ? ; 指向 IMAGE_IMPORT_BY_NAMEends
IMAGE_THUNK_DATA ENDS
我们可以看出由于是union结构,所以IMAGE_THUNK_DATA 事实上是一个双字大小。该结构在不同时候赋予不同的意义(伟大神奇不得鸟……)。其实union这种数据结构很容易理解:说白了就是当时穷,能省就省,再说白了,就是几兄弟姐妹轮流穿一条裤子去相亲!理解了吧?哈哈~
那我们怎么来区分何时是何意义呢?
规定如下:
当 IMAGE_THUNK_DATA 值的最高位为 1时,表示函数以序号方式输入,这时候低 31位被看作一个函数序号。
当 IMAGE_THUNK_DATA 值的最高位为 0时,表示函数以字符串类型的函数名方式输入,这时双字的值是一个 RVA,指向一个 IMAGE_IMPORT_BY_NAME 结构。(演示请看小甲鱼解密系列视频讲座)
好,那接着我们讨论下指向的这个 IMAGE_IMPORT_BY_NAME 结构。IMAGE_IMPORT_BY_NAME
结构仅仅只有一个字型数据的大小,存有一个输入函数的相关信息结构。其结构如下:
IMAGE_IMPORT_BY_NAME STRUCT
Hint WORD ?
Name BYTE ?
IMAGE_IMPORT_BY_NAME ENDS
结构中的 Hint 字段也表示函数的序号,不过这个字段是可选的,有些编译器总是将它设置为 0,Name 字段定义了导入函数的名称字符串,这是一个以 0 为结尾的字符串。
整个过程看起来有点绕有点烦,别急,后边我们有演示哈。
输入地址表(IAT)
为什么由两个并行的指针数组同时指向 IMAGE_IMPORT_BY_NAME 结构呢?第一个数组(由 OriginalFirstThunk 所指向)是单独的一项,而且不能被改写,我们前边称为 INT。第二个数组(由 FirstThunk 所指向)事实上是由 PE 装载器重写的。
好了,那么 PE 装载器的核心操作时如何的呢?这里就给大家揭秘啦~
PE 装载器首先搜索 OriginalFirstThunk ,找到之后加载程序迭代搜索数组中的每个指针,找到每个 IMAGE_IMPORT_BY_NAME 结构所指向的输入函数的地址,然后加载器用函数真正入口地址来替代由 FirstThunk 数组中的一个入口,因此我们称为输入地址表(IAT)。所以,当我们的
PE 文件装载内存后准备执行时,刚刚的图就会转化为下图:

此时,输入表中其他部分就不重要了,程序依靠 IAT 提供的函数地址就可正常运行。
输入表实例分析:(具体过程将在视频中演示,这里不啰嗦啦~)
工具:PEinfo.exe, UltraEdit, LordPE
解剖对象:hello.exe
小甲鱼PE详解之输入表(导入表)详解2(PE详解08)的更多相关文章
- PE文件结构详解(四)PE导入表
PE文件结构详解(二)可执行文件头的最后展示了一个数组,PE文件结构详解(三)PE导出表中解释了其中第一项的格式,本篇文章来揭示这个数组中的第二项:IMAGE_DIRECTORY_ENTRY_IMPO ...
- 《初识PE》导入表
最近听别人讲的我晕晕乎乎的,于是上网上百度下,感觉这篇还不错. 链接:http://www.blogfshare.com/pe-export.html 一.导入表简介 在编程中常常用到"导 ...
- 小甲鱼Python第四讲课后习题
1while语句中,当条件为真时,它会一直循环下去,比如下面的例子,不过可以用Ctral + C来强制结束 while 'C': print("i love you") 2.观察打 ...
- Windows PE 第四章 导入表
第四章 导入表 导入表是PE数据组织中的一个很重要的组成部分,它是为实现代码重用而设置的.通过分析导入表数据,可以获得诸如OE文件的指令中调用了多少外来函数,以及这些外来函数都存在于哪些动态链接库里等 ...
- Windows PE 第八章 延迟加载导入表
延迟加载导入表 延迟加载导入表是PE中引入的专门用来描述与动态链接库延迟加载相关的数据,因为这些数据所引起的作用和结构与导入表数据基本一致,所以称为延迟加载导入表. 延迟加载导入表和导入表是相互分离的 ...
- 小甲鱼PE详解之输入表(导出表)详解(PE详解09)
小甲鱼PE详解之输出表(导出表)详解(PE详解09) 当PE 文件被执行的时候,Windows 加载器将文件装入内存并将导入表(Export Table) 登记的动态链接库(一般是DLL 格式)文件一 ...
- 小甲鱼PE详解之输入表(导入表)详解(PE详解07)
捷径并不是把弯路改直了,而是帮你把岔道堵上! 走得弯路跟成长的速度是成正比的!不要害怕走上弯路,弯路会让你懂得更多,最终还是会在终点交汇! 岔路会将你引入万劫不复的深渊,并越走越深…… 在开始讲解输入 ...
- 小甲鱼PE详解之区块表(节表)和区块(节)续(PE详解05)
这一讲我们结合实例来谈谈区块表的定义以及各个属性的含义. 首先,我们先用之前学过的一点知识在二进制文件中手动翻找区块表,这样做的好处是可以使你很快的对PE结构牢记于心.学来的东西就是能用的东西,不能用 ...
- 小甲鱼PE详解之区块表(节表)和区块(节)(PE详解04)
到此为止,小甲鱼和大家已经学了许多关于 DOS header 和 PE header 的知识.接下来就该轮到SectionTable (区块表,也成节表).(视频教程:http://fishc.com ...
随机推荐
- Jetty和tomcat的比较
转自: http://blog.csdn.net/classicbear/article/details/6968930 相同点: 1. Tomcat和Jetty都是一种Servlet引擎, ...
- JAVA命令大全
1.java.exe:======================运行java程序,这个相信每一位用Java的人知道了. 2.javac.exe:======================编译的Ja ...
- 5个常用Java代码混淆器 助你保护你的代码
[IT168 技术文档] 从事Java编程的人都知道,可以通过逆向工程反编译得到Java程序的源代码,这种反编译工具之一就是JAD.因此,为保护我们的劳动成果,尽可能给反编译人员制造障碍,我们可以使用 ...
- Emmet插件使用方法总结
Emmet插件使用方法总结 在前端开发的过程中,一大部分的工作是写 HTML.CSS 代码.特别是手动编写 HTML 代码的时候,效率会特别低下,因为需要敲打很多尖括号,而且很多标签都需要闭合标签等. ...
- thinkphp-1
thinkphp网站: http://thinkphp.cn, http://bbs.thinkphp.cn 在设置文件夹查看试图的时候, 只点" 应用到所有文件夹" 不要点&qu ...
- js返回上一步
用按钮来链接返回上一步. <input type ="button" value="返回上一步" onclick="javascript:his ...
- [Effective JavaScript 笔记]第38条:在子类的构造函数中调用父类的构造函数
示例 场景类 场景图(scene)是在可视化的过程中(如游戏或图形仿真场景)描述一个场景的对象集合.一个简单的场景包含了在该场景中的所有对象(称角色),以及所有角色的预加载图像数据集,还包含一个底层图 ...
- 基于贪心算法的几类区间覆盖问题 nyoj 12喷水装置(二) nyoj 14会场安排问题
1)区间完全覆盖问题 问题描述:给定一个长度为m的区间,再给出n条线段的起点和终点(注意这里是闭区间),求最少使用多少条线段可以将整个区间完全覆盖 样例: 区间长度8,可选的覆盖线段[2,6],[1, ...
- 【ERROR】使用jquery的ajax出现error:readyState=4,status=500
使用jquery的ajax出现error:readyState=4,status=500,ajax代码如下: $.ajax({ url : "../toBeFinMisManage/show ...
- 反转字符串--C和Python
将字符串反转,即“abcde”->"edcba" C语言实现: [转自http://www.kanzhun.com/mianshiti/456.html?sid=mail_1 ...