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文件里包括的内容非常多,详细我就不在这解释了,有兴趣 ...
随机推荐
- eclipse---->自己常用的快捷键
organize imports----> ctrl+shift+o 导入其他工程的类(在学习springboot的注解@EnableAutoConfiguration时用到) 关闭当前窗口的 ...
- openstack中数据库连接数太多--pymysql.err.OperationalError,1040, u'Too many connections'
1.出现问题: openstack运行过程中出现如下问题: OperationalError: (pymysql.err.OperationalError) (1040, u'Too many con ...
- uva11552
将字符串分为len/k块.用dp[i][j]表示第i个块必须以j结尾的最小划分.当第i块没有字符j时,dp[i][j]多计一个.如果当前块只有1种字符,那么就等于dp[i-1][j].否则对于第i块的 ...
- es-aggregations聚合分析
聚合分析的格式: "aggregations" : { "<aggregation_name>" : { "<aggregation ...
- appium自动化环境搭建(python语言开发)
简述 1.安装jdk,配置环境变量 2.安装AndroidSDK,配置环境变量 3.安装Python 4.安装Python集成开发环境PyCharm 5.安装node 6.安装appium服务端 7. ...
- Jamie and Tree CodeForces - 916E (换根)
大意: n节点树, 每个点有权值, 三种操作: 1,换根. 2, lca(u,v)的子树权值全部增加x. 3, 查询子树权值和. 先不考虑换根, 考虑子树x加v的贡献 (1)对fa[x]到根的树链贡献 ...
- JavaScript基础一
1.1 javascript简介 Web前端有三层: HTML:从语义的角度,描述页面结构 CSS:从审美的角度,描述样式(美化页面) JavaScript:从交互的角度,描述行为(提升用户体验) J ...
- BIT-区间修改单点查询
正好刷题时碰到了这个之前遇到过的问题,类似的还有区间修改区间查询,以后学了会补上. 我们知道BIT只支持单点修改区间查询,如果现在问题变成每次让一个区间的数同时变化,然后询问的是某一个点得值的时候该怎 ...
- ajax代码整理
$.ajax({ type: "post", [以POST或GET的方式请求.默认GET.PUT和DELETE也可以用,有的浏览器不支持] url: url, [请求的目的地址,须 ...
- 121. Best Time to Buy and Sell Stock 买卖股票的最佳时机
网址:https://leetcode.com/problems/Best-Time-to-Buy-and-Sell-Stock/ 第一想法是滑动窗口法,稍微尝试后发现不可行,至少我不会... 而后想 ...