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文件里包括的内容非常多,详细我就不在这解释了,有兴趣 ...
随机推荐
- 决策论 | 信息论 | decision theory | information theory
参考: 模式识别与机器学习(一):概率论.决策论.信息论 Decision Theory - Principles and Approaches 英文图书 What are the best begi ...
- java ----> 类转换异常
com.rr.domain.Department_$$_javassist_5 cannot be cast to javassist.util.proxy.Proxy 两个原因: 1.懒加载 在we ...
- 从华为数字化转型看IT自动化运维重要性
关注嘉为科技,获取运维新知 8月有幸聆听了华为CIO陶总(陶景文)关于“华为数字化转型秘诀:坚定“以客户为中心”的思想”的演讲,获益良多.其中陶总也分享了IT运营平台的建设对于华为实现数字化转型的重要 ...
- hdu-2709整数划分 技巧
整数划分变形,由2^k组成. 整数划分中一个节约内存的技巧,平时我们使用dp[i][j]维护用不大于j的数组合成i的方案数,所以必须dp[i-j][j]->dp[i][j].这样就需要二位,如果 ...
- Binary Gap(二进制空白)
中文标题[二进制空白] 英文描述 A binary gap within a positive integer N is any maximal sequence of consecutive zer ...
- php 中文字符串反转
/** * * 中文字符串倒序 * @param str $str * return str **/ function str_en_desc($str){ $len=mb_strlen($str); ...
- iphone手机在网页返回上一页时,部分字体变大问题
最近做一个项目是,发现了一个iphone的兼容性问题,在返回上一页后,部分字体会变大,刷新就会正常. 经过总结,发现都是span标签里面的字体变大.经过查询发现,需要给span添加一个属性:displ ...
- 利用tablespace特性将数据库移动到新磁盘
目前开发一台EC2的PostgreSQL服务器的磁盘空间已经严重不足,该磁盘非LVM,所以不考虑磁盘扩容方法,研发希望可以分区/data/02对应的/dev/xvdl1磁盘分担部分数据库的数据,这样也 ...
- 查看某一职责下对应的菜单&功能&请求(转)
原文地址:查看某一职责下对应的菜单&功能&请求 查看菜单&功能 SELECT res.RESPONSIBILITY_NAME 职责名称, menu.MENU_NAME 菜单编码 ...
- Nginx+Tomcat集群配置
Nginx+Tomcat集群配置 一台虚拟机作为Nginx服务 两太虚拟机配置Tomcat+jdk环境 Nginx测试 启动: cd usr/local/nginx/sbin ./nginx ---& ...