PE文件 01 导入表
0x01 导入表结构
数据目录表中的第二个成员标记了导入表的RVA和Size大小,由此可以定位到导入表:
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

导入函数的代码位于一个或者多个DLL中,在调用者程序中只保留一些相关的函数信息,包括函数名及其对应的DLL名等。对于磁盘上的PE 文件来说,它无法得知这些输入函数将来在内存中的地址,只有当PE 文件被装入内存后,Windows的 加载器才将相关DLL 装入,并将调用导入函数的指令和函数实际所处的地址联系起来。这就是“动态链接”的概念。动态链接是通过PE 文件中定义的“导入表”来完成的,导入表中保存的正是函数名和其对应的DLL 名等。
导入表的结构成员:
typedef struct _IMAGE_IMPORT_DESCRIPTOR{
union{
DWORD Characteristics;
DWORD OriginalFirstThunk;//输入名称表INT的RAV
};
DWORD TimoeDateStamp; //文件生成时间
DWORD ForwaiderChain;
DWORD Name; //DLL名称的RVA(一个用null作为结束符的ASCII字符串的一个RVA,该字符串是该导入DLL文件的名称,如:KERNEL32.DLL)
DWORD FirstThunk; //输入地址表IAT的RAV
} IMAGE_IMPORT_DESCRIPTOR;
OriginalFirstThunk和FirstThunk是最关键的两个成员,在被PE加载器加载之前,它们都分别指向一个包含一系列IMAGE_THUNK_DATA结构的数组,数组中的每个IMAGE_THUNK_DATA结构定义了一个导入函数的信息,数组最后以一个内容为0的IMAGE_THUNK_DATA结构作为结束。
一个IMAGE_THUNK_DATA结构就是一个联合体双字,把它定义成联合体结构,使得它在不同时刻有不同的含义。
typedef struct _IMAGE_THUNK_DATA32 {
union {
DWORD ForwarderString; //指向一个转向者字符串的RVA
DWORD Function; //被输入的函数的内存地址
DWORD Ordinal; //被输入的函数的序数值
DWORD AddressOfData; //指向IMAGE_IMPORT_BY_NAME
} u1;
} IMAGE_THUNK_DATA32;
typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;
当 IMAGE_THUNK_DATA 值的最高位为 1时,表示函数以序号方式导入,这时候低 31位被看作一个函数序号。(可以用预定义值IMAGE_ORDINAL_FLAG32或80000000h来对最高位进行测试)
当 IMAGE_THUNK_DATA 值的最高位为 0时,表示函数以字符串类型的函数名方式导入,这时双字的值是一个 RVA,指向一IMAGE_IMPORT_BY_NAME 结构。
IMAGE_IMPORT_BY_NAME STRUCT
Hint WORD ?
Name1 BYTE ?
IMAGE_IMPORT_BY_NAME ENDS
IMAGE_IMPORT_BY_NAME 中的Hint 字段也表示函数的序号,不过这个字段是可选的,有些编译器总是将它设置为 0,Name1字段定义了导入函数的名称字符串,这是一个以 0 为结尾的字符串。
0x02 关键问题:
(1)需要两个一样的IMAGE_THUNK_DATA 数组的理由?
当PE文件被装入内存的时候,FirstThunk字段指向的那个数组的值将被修改, Windows装载器会将指令Jmp dword ptr[VA]指定的VA中保存的的RVA替换成真正的函数地址,其实VA处正是FirstThunk字段指向的那个数组的一员。
实际上,当PE文件被装入内存后,内存中的映象就被Windows装载器修正成了下图的样子,其中由FirstThunk字段指向的那个数组中的每个双字都被替换成了真正的函数入口地址,之所以在PE文件中使用两份IMAGE_THUNK_DATA 数组的拷贝并修改其中的一份,是为了最后还可以留下一份拷贝用来反过来查询地址所对应的导入函数名。
(2)导入地址表(Import Address Table)
在PE文件中,所有DLL对应的导入地址数组是被排列在一起的,全部这些数组的组合也被称为导入地址表(Import Address Table),导入表中第一个IMAGE_IMPORT_DESCRIPTOR结构的FirstThunk字段指向的就是IAT的起始地址。也可以通过数据目录表的第13项找到IAT数据块的位置和大小。
加载前:

加载后:

PE文件 01 导入表的更多相关文章
- PE知识复习之PE的绑定导入表
PE知识复习之PE的绑定导入表 一丶简介 根据前几讲,我们已经熟悉了导入表结构.但是如果大家尝试过打印导入表的结构. INT IAT的时候. 会出现问题. PE在加载前 INT IAT表都指向一个名称 ...
- 利用PE数据目录的导入表获取函数名及其地址
PE文件是以64字节的DOS文件头开始的(IMAGE_DOS_HEADER),接着是一段小DOS程序,然后是248字节的 NT文件头(IMAGE_NT_HEADERS),NT的文件头位置由IMAGE_ ...
- 取PE文件的引入表和导出表
直接上代码(这里列出C++和Delphi的代码),Delphi代码中包含导入及导出文件和函数列表,PE结构可参阅资料,很多很详细,需要注意的是,本例中是映射到内存,不是通过PE装载器装入的,所以对于节 ...
- Windows PE 第四章 导入表
第四章 导入表 导入表是PE数据组织中的一个很重要的组成部分,它是为实现代码重用而设置的.通过分析导入表数据,可以获得诸如OE文件的指令中调用了多少外来函数,以及这些外来函数都存在于哪些动态链接库里等 ...
- PE知识复习之PE的导入表
PE知识复习之PE的导入表 一丶简介 上一讲讲解了导出表. 也就是一个PE文件给别人使用的时候.导出的函数 函数的地址 函数名称 序号 等等. 一个进程是一组PE文件构成的. PE文件需要依赖那些 ...
- 导入表 IMPORT_DESCRIPTOR
typedef struct _IMAGE_IMPORT_DESCRIPTOR { union { DWORD Characteristics; // 0 for terminating null i ...
- 深入学习PE文件(转)
PE文件是Win32的原生文件格式.每一个Win32可执行文件都遵循PE文件格式.对PE文件格式的了解可以加深你对Win32系统的深入理解. 一. 基本结构. 上图便是PE文件的基本结构.(注意:DO ...
- 深入剖析PE文件
不赖猴的笔记,转载请注明出处. 深入剖析PE文件 PE文件是Win32的原生文件格式.每一个Win32可执行文件都遵循PE文件格式.对PE文件格式的了解可以加深你对Win32系统的深入理解. 一. ...
- C++PE文件格式解析类(轻松制作自己的PE文件解析器)
PE是Portable Executable File Format(可移植的运行体)简写,它是眼下Windows平台上的主流可运行文件格式. PE文件里包括的内容非常多,详细我就不在这解释了,有兴趣 ...
随机推荐
- logstash配置文件
1. 安装 logstash 安装过程很简单,直接参照官方文档: https://www.elastic.co/guide/en/logstash/current/installing-logsta ...
- Fiddler抓取https数据包
Wireshark和Fiddler的优缺点: ①Wireshark是一种在网络层上工作的抓包工具,不仅自带大量的协议分析器,而且可以通过编写Wireshark插件来识别自定义的协议.虽然Wiresha ...
- CentOS7 安装PHP7的redis扩展:
phpredis-4.2.0.tar.gz:下载:wget https://github.com/phpredis/phpredis/archive/4.2.0.tar.gz $ tar -z ...
- CSS之transform-origin属性
设置旋转元素的基点位置 语法 transform-orign:0 100% 0 transform-origin: x-axis y-axis z-axis; x-axis 定义视图被置于 X 轴的何 ...
- Spring配置表友好性优化思路
Spring配置表需要尽量保证对程序员的友好性,一下提供一种优化思路. 中途未保存,心态炸了,只贴图了,fuuuuuuuuuuuuuck 第一种(最烂,最不友好):以Json的格式保存在配置表中,程序 ...
- Leetcode 1022. 可被 K 整除的最小整数
1022. 可被 K 整除的最小整数 显示英文描述 我的提交返回竞赛 用户通过次数74 用户尝试次数262 通过次数75 提交次数1115 题目难度Medium 给定正整数 K,你需要找出可以被 ...
- MapReduce- 数据的排序处理
MapReduce- 数据的排序处理 package com.huhu.day02; import java.io.DataInput; import java.io.DataOutput; impo ...
- php 循环数组问题
$a = array('abe','ben','cam'); //foreach遍历数组时,实际上是遍历的数组的一个拷贝,并且在开始遍历之前会把指针指向拷贝的开始:,根据cow机制,写时,重新复制一份 ...
- ActiveMQ Message Groups
http://activemq.apache.org/message-groups.html 与Exclusive Consumer相比,Message Groups的对消息分组的粒度更细.具有相同g ...
- CSS:font-family常用字体中英文对照
CSS:font-family常用字体中英文对照如下: 推荐网址:https://www.cnblogs.com/EnSnail/p/6792853.html 微软雅黑: Microsoft YaHe ...