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文件里包括的内容非常多,详细我就不在这解释了,有兴趣 ...
随机推荐
-
AngularJS开发指南9:AngularJS作用域的详解
AngularJS作用域是一个指向应用模型的对象.它是表达式的执行环境.作用域有层次结构,这个层次和相应的DOM几乎是一样的.作用域能监控表达式和传递事件. 作用域的特点 作用域提供APIs($wat ...
-
(原创)jquery插件-可选可填控件
;(function ($) { $.fn.autoFillTextBox = function (options) { var defaults = { nShow: 5, //显示条数 nLen: ...
-
文成小盆友python-num9 socket编程
socket编程 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket. Socket的英文原义是“孔”或“插座”.作为BSD UNIX的进程通信机制,取后一种意思 ...
-
kubernetes资源类别介绍
类别 名称 资源对象 Pod.ReplicaSet.ReplicationController.Deployment.StatefulSet.DaemonSet.Job.CronJob.Horizon ...
-
在Windows下食用Linux工作环境(WSL+cmder)
在Windows下食用Linux工作环境(WSL+cmder) 为什么要这么瞎搞呢?因为最近换了个硬盘,搞了个双系统,然后习惯性地按下 Ctrl+Alt+T 发现什么都没有召唤出来,然后忽然想起换了系 ...
-
uva-270-排序
题意:很多个点,问,最多有多少个点在同一条直线上 #include <algorithm> #include <iostream> #include <string> ...
-
MyBatis打印输出SQL语句
Hibernate是可以配置 show_sql 显示 自动生成的SQL 语句,用 format_sql 可以格式化SQL 语句,但如果用 mybatis 怎么实现这个功能呢?如果你搜索看一下,基本都是 ...
-
mysql 跑存储过程没有权限的问题
1.赋予权限 GRANT ALL PRIVILEGES ON *.* TO root@"%" IDENTIFIED BY "root"; 2.刷新权限 FLUS ...
-
解题:USACO12FEB Nearby Cows
题面 比较简单的树形dp(递推?) 设$dp[i][j]$表示距离$i$距离为$j$的点的数目,先预处理$g[i][j]$表示点$i$的子树中距离这个点距离为$j$的点的数目(猫老师讲过,用一个栈维护 ...
-
The OAuth 2.0 Authorization Framework: Bearer Token Usage
https://tools.ietf.org/html/rfc6750 1.2. Terminology Bearer Token A security token with the property ...