博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PE格式详细讲解8 - 系统篇08|解密系列
阅读量:5106 次
发布时间:2019-06-13

本文共 3599 字,大约阅读时间需要 11 分钟。

PE格式详细讲解8 - 系统篇08

 

让编程改变世界

Change the world by program


  在此之前,我们已经对这个输入表进行了一些实践和理解,这有助于大家对这个概念更进一步的加深认识。 小甲鱼觉得,越是复杂的问题我们应该越是去动手操作它,认识它,这样才容易熟悉它!   在上一节课我们像小鹿一样的乱撞,终于撞到了输入表里边包含的函数名称,嘿嘿,不过地址,我们还是没能找着…… 这节课我们将深入来剖析输入表的结构,通过结合实例分析来帮助大家理解输入表的工作原理。  

输入表结构

  回顾一下,在 PE文件头的 IMAGE_OPTIONAL_HEADER 结构中的 DataDirectory(数据目录表) 的第二个成员就是指向输入表的。 而输入表是以一个 IMAGE_IMPORT_DESCRIPTOR(简称IID) 的数组开始。 每个被 PE文件链接进来的 DLL文件都分别对应一个 IID数组结构。 在这个 IID数组中,并没有指出有多少个项(就是没有明确指明有多少个链接文件),但它最后是以一个全为NULL(0) 的 IID 作为结束的标志。   IMAGE_IMPORT_DESCRIPTOR 结构定义如下: [codesyntax lang="php"]
IMAGE_IMPORT_DESCRIPTOR STRUCT     union         Characteristics           DWORD   ?         OriginalFirstThunk        DWORD   ?     ends     TimeDateStamp                 DWORD   ?     ForwarderChain                DWORD   ?     Name                          DWORD   ?     FirstThunk                    DWORD   ?IMAGE_IMPORT_DESCRIPTOR ENDS
[/codesyntax]  

成员介绍:

 

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明显是亲家,两家伙首先名字就差不多哈。那他们有什么不可告人的秘密呢? 来,我们看下面一张图(画的很辛苦,大家仔细看哈): [caption id="attachment_1601" align="alignnone" width="581"] FirstThunk[/caption]     我们看到:OriginalFirstThunk 和 FirstThunk 他们都是两个类型为IMAGE_THUNK_DATA 的数组,它是一个指针大小的联合(union)类型。 每一个IMAGE_THUNK_DATA 结构定义一个导入函数信息(即指向结构为IMAGE_IMPORT_BY_NAME 的家伙,这家伙稍后再议)。 然后数组最后以一个内容为0 的 IMAGE_THUNK_DATA 结构作为结束标志。   我们得到 IMAGE_THUNK_DATA 结构的定义如下: [codesyntax lang="asm"]
IMAGE_THUNK_DATA STRUC    union u1    ForwarderString      DWORD  ?        ; 指向一个转向者字符串的RVA    Function             DWORD  ?        ; 被输入的函数的内存地址    Ordinal              DWORD  ?        ; 被输入的API 的序数值    AddressOfData        DWORD  ?        ; 指向 IMAGE_IMPORT_BY_NAME    endsIMAGE_THUNK_DATA ENDS
[/codesyntax]   我们可以看出由于是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 结构仅仅只有一个字型数据的大小,存有一个输入函数的相关信息结构。 其结构如下: [codesyntax lang="c"]
IMAGE_IMPORT_BY_NAME STRUCT    Hint      WORD      ?     Name      BYTE      ?IMAGE_IMPORT_BY_NAME ENDS
[/codesyntax]   结构中的 Hint 字段也表示函数的序号,不过这个字段是可选的,有些编译器总是将它设置为 0。 Name 字段定义了导入函数的名称字符串,这是一个以 0 为结尾的字符串。 整个过程看起来有点绕有点烦,别急,后边我们有演示哈。  

输入地址表(IAT)

  为什么由两个并行的指针数组同时指向 IMAGE_IMPORT_BY_NAME 结构呢?第一个数组(由 OriginalFirstThunk 所指向)是单独的一项,而且不能被改写,我们前边称为 INT。 第二个数组(由 FirstThunk 所指向)事实上是由 PE 装载器重写的。 好了,那么 PE 装载器的核心操作时如何的呢?这里就给大家揭秘啦~   PE 装载器首先搜索 OriginalFirstThunk ,找到之后加载程序迭代搜索数组中的每个指针,找到每个 IMAGE_IMPORT_BY_NAME 结构所指向的输入函数的地址,然后加载器用函数真正入口地址来替代由 FirstThunk 数组中的一个入口,因此我们称为输入地址表(IAT)。 所以,当我们的 PE 文件装载内存后准备执行时,刚刚的图就会转化为下图: [caption id="attachment_1602" align="alignnone" width="579"] 输入地址表(IAT)[/caption]   此时,输入表中其他部分就不重要了,程序依靠 IAT 提供的函数地址就可正常运行。 输入表实例分析:(具体过程将在视频中演示,这里不啰嗦啦~) 工具:PEinfo.exe, UltraEdit, LordPE 解剖对象:hello.exe [buy]   [/buy] [Downlink href='http://kuai.xunlei.com/d/LCPUCHCOYQNV']视频下载[/Downlink]

转载于:https://www.cnblogs.com/LoveFishC/archive/2011/06/20/3847096.html

你可能感兴趣的文章
贪心——洛谷P1016 旅行家的预算
查看>>
【学习整理】树状数组 区间修改+查询
查看>>
你知道电脑硬盘怎么分区吗?
查看>>
去除Visual Studio引号中的内容和注释中出现的波浪下划线
查看>>
C#多线程方法 可传参
查看>>
[zz]一个简单加密病毒的框架
查看>>
supervisor配置详解
查看>>
java 获取当月第一天和最后一天 获取前一个月第一天和最后一天
查看>>
js 获得日期相差天数
查看>>
速度环加位置环进行电机控制
查看>>
发布.net core项目 System.AggregateException: 发生一个或多个错误
查看>>
空间滤波
查看>>
学习Memcached:1基本配置与安装
查看>>
C#.NET 生成分页SQL代码(NOT IN/TOP TOP/Top MAX)三种方法,支持ACCESS
查看>>
【循序渐进学Python】5.Python常用流程控制及其他语句
查看>>
深入理解linux启动过程
查看>>
Python建立Web应用
查看>>
php
查看>>
使用requests模块post payload请求
查看>>
javascript console
查看>>