`
cfree
  • 浏览: 17895 次
  • 性别: Icon_minigender_1
  • 来自: 成都
最近访客 更多访客>>
社区版块
存档分类
最新评论

压缩与脱壳-PE文件格式 六

阅读更多

Import Table (引入表)
本课我们将学习引入表。先警告一下,对于不熟悉引入表的读者来说,这是一堂又长又难的课,所以需要多读几遍,最好再打开调试器来好好分析相关结构。各位,努力啊!

理论 :
  首先,您得了解什么是引入函数。一个引入函数是被某模块调用的但又不在调用者模块中的函数,因而命名为 "import (引入) " 。引入函数实际位于一个或者更多的 DLL 里。调用者模块里只保留一些函数信息,包括函数名及其驻留的 DLL 名。现在,我们怎样才能找到 PE 文件中保存的信息呢 ? 转到 data directory 寻求答案吧。再回顾一把,下面就是 PE header:

IMAGE_NT_HEADERS STRUCT
Signature dd ?
FileHeader IMAGE_FILE_HEADER <>
OptionalHeader IMAGE_OPTIONAL_HEADER <>
IMAGE_NT_HEADERS ENDS



optional header 最后一个成员就是 data directory (数据目录) :
MAGE_OPTIONAL_HEADER32 STRUCT
....
LoaderFlags dd ?
NumberOfRvaAndSizes dd ?
DataDirectory IMAGE_DATA_DIRECTORY 16 dup(<>)
IMAGE_OPTIONAL_HEADER32 ENDS


data directory 是一个 IMAGE_DATA_DIRECTORY 结构数组,共有 16 个成员。如果您还记得节表可以看作是 PE 文件各节的根目录的话,也可以认为 data directory 是存储在这些节里的逻辑元素的根目录。明确点, data directory 包含了 PE 文件中各重要数据结构的位置和尺寸信息。 每个成员包含了一个重要数据结构的信息。


上面那些金色显示的是我熟悉的。了解 data directory 包含域后,我们可以仔细研究它们了。 data directory 的每个成员都是 IMAGE_DATA_DIRECTORY 结构类型的,其定义如下所示 :
IMAGE_DATA_DIRECTORY STRUCT
VirtualAddress dd ?
isize dd ?
IMAGE_DATA_DIRECTORY ENDS


VirtualAddress 实际上是数据结构的相对虚拟地址 (RVA) 。比如,如果该结构是关于 import symbols 的,该域就包含指向 IMAGE_IMPORT_DESCRIPTOR 数组的 RVA 。

  isize 含有 VirtualAddress 所指向数据结构的字节数。

  下面就是如何找寻 PE 文件中重要数据结构的一般方法 :

从 DOS header 定位到 PE header 从 optional header 读取 data directory 的地址。 IMAGE_DATA_DIRECTORY 结构尺寸乘上找寻结构的索引号 : 比如您要找寻 import symbols 的位置信息,必须用 IMAGE_DATA_DIRECTORY 结构尺寸 (8 bytes) 乘上 1 ( import symbols 在 data directory 中的索引号)。 将上面的结果加上 data directory 地址,我们就得到包含所查询数据结构信息的 IMAGE_DATA_DIRECTORY 结构项。
  现在我们开始真正讨论引入表了。 data directory 数组第二项的 VirtualAddress 包含引入表地址。引入表实际上是一个 IMAGE_IMPORT_DESCRIPTOR 结构数组。每个结构包含 PE 文件引入函数的一个相关 DLL 的信息。比如,如果该 PE 文件从 10 个不同的 DLL 中引入函数,那么这个数组就有 10 个成员。该数组以一个全 0 的成员结尾。下面详细研究结构组成 :

IMAGE_IMPORT_DESCRIPTOR STRUCT
union
Characteristics dd ?
OriginalFirstThunk dd ?
ends
TimeDateStamp dd ?
ForwarderChain dd ?
Name1 dd ?
FirstThunk dd ?
IMAGE_IMPORT_DESCRIPTOR ENDS


结构第一项是一个 union 子结构。 事实上,这个 union 子结构只是给 OriginalFirstThunk 增添了个别名,您也可以称其为 "Characteristics" 。 该成员项含有指向一个 IMAGE_THUNK_DATA 结构数组的 RVA 。

  什么是 IMAGE_THUNK_DATA ? 这是一个 dword 类型的集合。通常我们将其解释为指向一个 IMAGE_IMPORT_BY_NAME 结构的指针。注意 IMAGE_THUNK_DATA 包含了指向一个 IMAGE_IMPORT_BY_NAME 结构的指针 : 而不是结构本身。

  请看这里 : 现有几个 IMAGE_IMPORT_BY_NAME 结构,我们收集起这些结构的 RVA ( IMAGE_THUNK_DATAs ) 组成一个数组,并以 0 结尾,然后再将数组的 RVA 放入 OriginalFirstThunk 。

  此 IMAGE_IMPORT_BY_NAME 结构存有一个引入函数的相关信息。再来研究 IMAGE_IMPORT_BY_NAME 结构到底是什么样子的呢 :

IMAGE_IMPORT_BY_NAME STRUCT
Hint dw ?
Name1 db ?
IMAGE_IMPORT_BY_NAME ENDS


Hint 指示本函数在其所驻留 DLL 的引出表中的索引号。该域被 PE 装载器用来在 DLL 的引出表里快速查询函数。该值不是必须的,一些连接器将此值设为 0 。

  Name1 含有引入函数的函数名。函数名是一个 ASCIIZ 字符串。注意这里虽然将 Name1 的大小定义成字节,其实它是可变尺寸域,只不过我们没有更好方法来表示结构中的可变尺寸域。 The structure is provided so that you can refer to the data structure with descriptive names.

  TimeDateStamp 和 ForwarderChain 可是高级东东 : 让我们精通其他成员后再来讨论它们吧。

  Name1 含有指向 DLL 名字的 RVA ,即指向 DLL 名字的指针,也是一个 ASCIIZ 字符串。

  FirstThunk 与 OriginalFirstThunk 非常相似,它也包含指向一个 IMAGE_THUNK_DATA 结构数组的 RVA( 当然这是另外一个 IMAGE_THUNK_DATA 结构数组 ) 。

  好了,如果您还在犯糊涂,就朝这边看过来 : 现在有几个 IMAGE_IMPORT_BY_NAME 结构,同时您又创建了两个结构数组,并同样寸入指向那些 IMAGE_IMPORT_BY_NAME 结构的 RVAs ,这样两个数组就包含相同数值了 ( 可谓相当精确的复制啊 ) 。 最后您决定将第一个数组的 RVA 赋给 OriginalFirstThunk , 第二个数组的 RVA 赋给 FirstThunk ,这样一切都很清楚了。



现在您应该明白我的意思。不要被 IMAGE_THUNK_DATA 这个名字弄糊涂 : 它仅是指向 IMAGE_IMPORT_BY_NAME 结构的 RVA 。 如果将 IMAGE_THUNK_DATA 字眼想象成 RVA ,就更容易明白了。 OriginalFirstThunk 和 FirstThunk 所指向的这两个数组大小取决于 PE 文件从 DLL 中引入函数的数目。比如,如果 PE 文件从 kernel32.dll 中引入 10 个函数,那么 IMAGE_IMPORT_DESCRIPTOR 结构的 Name1 域包含指向字符串 "kernel32.dll" 的 RVA ,同时每个 IMAGE_THUNK_DATA 数组有 10 个元素。

下一个问题是 : 为什么我们需要两个完全相同的数组 ? 为了回答该问题,我们需要了解当 PE 文件被装载到内存时, PE 装载器将查找 IMAGE_THUNK_DATA 和 IMAGE_IMPORT_BY_NAME 这些结构数组,以此决定引入函数的地址。然后用引入函数真实地址来替代由 FirstThunk 指向的 IMAGE_THUNK_DATA 数组里的元素值。因此当 PE 文件准备执行时,上图已转换成 :


由 OriginalFirstThunk 指向的 RVA 数组始终不会改变,所以若还反过头来查找引入函数名, PE 装载器还能找寻到。

  当然再简单的事物都有其复杂的一面。 有些情况下一些函数仅由序数引出,也就是说您不能用函数名来调用它们 : 您只能用它们的位置来调用。此时,调用者模块中就不存在该函数的 IMAGE_IMPORT_BY_NAME 结构。不同的,对应该函数的 IMAGE_THUNK_DATA 值的低位字指示函数序数,而最高二进位 (MSB) 设为 1 。例如,如果一个函数只由序数引出且其序数是 1234h ,那么对应该函数的 IMAGE_THUNK_DATA 值是 80001234h 。 Microsoft 提供了一个方便的常量来测试 dword 值的 MSB 位,就是 IMAGE_ORDINAL_FLAG32 ,其值为 80000000h 。

  假设我们要列出某个 PE 文件的所有引入函数,可以照着下面步骤走 :

校验文件是否是有效的 PE 。 从 DOS header 定位到 PE header 。 获取位于 OptionalHeader 数据目录地址。 转至数据目录的第二个成员提取其 VirtualAddress 值。 利用上值定位第一个 IMAGE_IMPORT_DESCRIPTOR 结构。 检查 OriginalFirstThunk 值。若不为 0 ,顺着 OriginalFirstThunk 里的 RVA 值转入那个 RVA 数组。若 OriginalFirstThunk 为 0 ,就改用 FirstThunk 值。有些连接器生成 PE 文件时会置 OriginalFirstThunk 值为 0 ,这应该算是个 bug 。不过为了安全起见,我们还是检查 OriginalFirstThunk 值先。 对于每个数组元素,我们比对元素值是否等于 IMAGE_ORDINAL_FLAG32 。 如果该元素值的最高二进位为 1 , 那么函数是由序数引入的,可以从该值的低字节提取序数。 如果元素值的最高二进位为 0 ,就可将该值作为 RVA 转入 IMAGE_IMPORT_BY_NAME 数组,跳过 Hint 就是函数名字了。 再跳至下一个数组元素提取函数名一直到数组底部 ( 它以 null 结尾 ) 。现在我们已遍历完一个 DLL 的引入函数,接下去处理下一个 DLL 。 即跳转到下一个 IMAGE_IMPORT_DESCRIPTOR 并处理之,如此这般循环直到数组见底。 ( IMAGE_IMPORT_DESCRIPTOR 数组以一个全 0 域元素结尾 )

  • 大小: 30.8 KB
  • 大小: 43.5 KB
  • 大小: 40.3 KB
分享到:
评论

相关推荐

    PE文件的UPX脱壳算法的实现

    都会使计算机产生安全隐患或者使软件的核心技术被窃取,所以保护PE文件不被修改是一件很重要的工作,当前通常采用加壳的方法对PE文件进行保护,这其中UPX是具有代表性的压缩类外壳。 本文首先对PE文件格式进行了全面...

    .Net 脱壳 反混淆神器De4dot-3.1.41592最新版

    有些模糊处理一个Win32 PE等包装.NET程序集里面的.NET反编译器无法读取该文件。 移除大多数/所有的垃圾类添加混淆。 修复了一些的peverify错误。许多混淆器是马车和创建无法验证的代码错误。 还原类型的方法的参数和...

    红黑全能自动脱壳机——全能脱壳机

    这个工具的工作原理,它的壳特征和编译器特征保存在HackFans.txt里面,能识别出来的壳,基本上都有对应的脱壳函数,用壳特征脱壳,可以脱壳,对于一些不好特殊的壳你可以用OEP侦测来脱壳,这要依赖编译器特征,你也可以自己...

    脱壳AspackDie

    - 询问用户是否继续解压缩不能解压缩的文件 (不知道是谁提的建议) 1.3d: (2002.3.26) --------------------- - 支持另外的一个未知的 Aspack 版本 (感谢: Proggi Killa) 1.3c: (2002.3.21) --------------------- ...

    脱壳入门初级教学(CHM格式)

    第一课 PE格式 第二课 SEH技术 第三课 认识壳 第四课 常见压缩壳与加密壳 第五课 文件类型分析 第六课 寻找OEP 第七课 Dump内存映像 第八课 重建输入表 第九课 手动确定IAT的地址与大小 第十课 DLL文件脱壳 第十一课...

    软件脱壳破解工具

    AspackDie——AsPack的脱壳利器, 这是一个小小的PE 文件解压缩器 (EXE, DLL, ...) 她可以解压缩自Aspack 2000 以后的任何Aspack 版本. 包括: - Aspack 2000 - Aspack 2001 - Aspack 2.1 - Aspack 2.11 - Aspack 2.11...

    ASPack脱壳

    这是一个小小的 PE 文件解压缩器 (EXE, DLL, ...) 她可以解压缩 自 Aspack 2000 以后的任何 Aspack 版本. 包括: - Aspack 2000 - Aspack 2001 - Aspack 2.1 - Aspack 2.11 - Aspack 2.11c/d - Aspack 2.12 - Aspack...

    rordbg辅助脱壳工具

    答:点击“打开被分析文件”,出现Windows标准的文件打开对话框,选择欲分析的文件(必须是PE格式的EXE文件), 这时,被调试程序已经加载,可以先设置断点等调试条件,如果希望研究壳的技术,可以点选“遇到异常...

    软件加密技术内幕 chm

    第1章 PE文件格式深入研究 1.1 PE文件格式格式纵览 1.1.1 区块(Section) 1.1.2 相对虚拟地址(Relative Virtual Addresses) 1.1.3 数据目录 1.1.4 输入函数(Importing Functions) 1.2 PE文件结构 ...

    全能脱壳机

    这个工具的工作原理,它的壳特征和编译器特征保存在HackFans.txt里面,能识别出来的壳,基本上都有对应的脱壳函数,用壳特征脱壳,可以脱壳,对于一些不好特殊的壳你可以用OEP侦测来脱壳,这要依赖编译器特征,你也可以自己...

    多种脱壳软件

    现在为了适应脱壳的需要,发现原来的代码对非标准格式的PE文件的处理有些小问题, 所以代码基本都重写过了,但是基本处理步骤还是一致的,外表上看不出来 3.cooldebugger plugin(调试插件) 完全自主开发的插件,说是调试...

    软件加密技术内幕

    1.1 PE文件格式格式纵览 1.1.1 区块(Section) 1.1.2 相对虚拟地址(Relative Virtual Addresses) 1.1.3 数据目录 1.1.4 输入函数(Importing Functions) 1.2 PE文件结构 1.2.1 The MS-DOS头部 1.2.2 IMAGE...

    加密解密.技术内幕.chm

    第1章 PE文件格式深入研究1.1 PE文件格式格式纵览 1.1.1 区块(Section) 1.1.2 相对虚拟地址(Relative Virtual Addresses) 1.1.3 数据目录 1.1.4 输入函数(Importing Functions)1.2 PE文件结构 1.2.1 The MS-...

    强大UPX加壳压缩工具(Free UPX) v1.7汉化版.rar

    UPX 加壳压缩工具绿色版本,无需安装,Free UPX1.4,在编程开发过程中我们可以利用其对EXE, DLL, OCX, BPL, CPL 等格式文件加壳,使用方便快速、而且是免费的! UPX(the Ultimate Packer for eXecutables)是一个...

    Windows应用程序捆绑核心编程光盘代码

    2.2 PE文件格式概述 28 2.2.1 PE文件结构布局 28 2.2.2 PE文件内存映射 30 2.2.3 Big-endian和Little-endian 31 2.2.4 3种不同的地址 31 2.3 PE文件结构 32 2.3.1 MS-DOS头部 32 2.3.2 IMAGE_NT_HEADER头部 ...

    软件破解入门教程.txt

    PE文件格式 认识脱壳 自动脱壳 手动脱壳 脱壳高级篇 第9章 注册机和补丁制作 概念介绍 补丁制作 注册机制作工具 rufeng教程 第一章 如何成为一个Cracker 第二章 破解软件的基础 第三章 破解windows 95...

    完全掌握加密解密实战超级手册.z01

    462.1.3 PE文件格式的头结构 462.1.4 设置Optional Header可执行信息 492.1.5 Section Table结构数组 512.1.6 Import Table输入表 522.1.7 Export Table输出表 532.1.8 重定位表 542.2 简述代码分析实战 552.2.1 ...

    易语言程序免安装版下载

    注意:静态编译后常量数据位于PE文件的.rdata段中,只可读不可写,编程时请避免修改它们。譬如以下的代码,静态编译后就可能会出现问题: a = " " GetWindowTextA(hWnd, a, 20) 正确的代码为: a = 取空白文本 ...

Global site tag (gtag.js) - Google Analytics