0x00 前言

前一篇了解了区块虚拟地址和文件地址转换的相关知识,这一篇该把我们所学拿出来用用了。这篇我们将了解更为重要的一个知识点——输入表和输出表的知识。

0x01 输入表

首先我们有疑问。这个输入表是啥?为啥有输入表?其实输入表就是记录PE输入函数相关信息的一张表。那为什么要有这张表?答:原来PE文件运行过程中并不是独立运行的,它必须要借助window系统的需对函数才能完成其功能。常见的如USER32,KERNEL32等DLL。

输入表所起的作用就是帮助载入的PE找到所需调用的函数。

在PE文件中,有个专门的数组,他们分别对每个被输入的DLL程序。每个这样的结构都给出了被输入DLL的名称并且指向一组函数指针,这组函数指针就是输入地址表(Import Address Table 简称ITA)。

在之前讲过的PE文件头的IMAGE_OPTIONAL_HAEDER结构中的数据目录表即DataDirectory[16]中第二个成员Imaport Table指向输入表。输入表是一个由IMAGE_IMPORT_DESCRIPORT(简称IID)的结构组成的数组。IID的结构如下:

typedef struct _IMAGE_IMPORT_DESCRIPTOR {

DWORD    OriginalFirstThunk;

DWORD    TimeDateStamp;

DWORD     ForwarderChain;

DWORD     Name;

DWORD      FirstThunk;

} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR;

下面介绍几个重要字段:

OriginalFirstThunk:这个字段包含指向输入名称表(简称INT)的RVA,INT是一个IMAGE_THUNK_DATA结构的数组,数组中的每个IMAGE_THUNK_DATA结构指向IMAGE_IMPORT_BY_NAME结构,数组最后以一个内容为0的IMAGE_THUNK_DATA结构结束。

直接看这个描肯定感觉很绕,下面看看这几个结构的关系图,希望能够帮助理解:

其实就是1指向2再指向3

Name:输入的DLL的名字指针,它是一个以00结尾的ASCII字符的RVA地址,该字符串包含输入的DLL名。例如:KERNEL32.DLL,或者USER32.DLL。

FirstThunk:包含指向输入地址表(IAT)的RVA。IAT也是指向IAMGE_THUNK_DATA结构。

这里的FristThunk和OringinalFristThunk极为相似,作用也很类似,但是作用的先后有不同,后面将会做详细讲解。

下面来重点看看这个起着巨大作用的IMAGE_THUNK_DATA结构。

typedef struct _IMAGE_THUNK_DATA32 {
union {
PBYTE ForwarderString;
PDWORD Function;
DWORD Ordinal;
PIMAGE_IMPORT_BY_NAME AddressOfData;
} u1;
} IMAGE_THUNK_DATA32;

ForwarderString 指向一个转向者字符串的RVA;

Function 被输入的函数的内存地址

Ordinal 被输入的API的序数值

AddressOfData 指向IMAGE_IMPORT_BY_NAME

标识位黄色的这几个字段都很重要,是的这个结构的字段全都很重要!

下面来看看AddressOfData字段指向的IMAGE_IMPORT_BY_NAME结构

typedef struct _IMAGE_IMPORT_BY_NAME {

WORD Hint;

BYTE Name[1];

} IMAGE_IMPORT_BY_NAME;

这个结构很简单,只有两个字段:

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

NAME字段:这个字段比较重要。它含有输入函数的函数名,函数名是一个ASCII码字符串,并以NULL结尾。注意,这里虽然将NAME的大小定义为字节,其实他是可变的。

  0x02 输入地址表

接下来要讲的才是本文里最为关键的部分。通过上面的了解大概我们都会疑惑为啥这两个数组都要指向IMAGR_IMPORT_BY_NAME结构?原因如下:

第一,第一个由OriginalFrist通过IMAGE_THUNK_DATA结构所指向的IMAGE_IMPORT_BY_NAME是单独的一项,而且IMAGE_THUNK_DATA的值不可以更改,这个IMAGE_THUNK_DATA组成的数组就是INT,其实它是为FristThunk做为提示用的。

第二,第二个由FristThunk所指向的IMAGE_THUNK_DATA的值是由PE装载器填写的,他们的值构成了IAT。PE装载器首先搜索OringinalFristThunk,通过它所指向的INT结构中的每个IMAGE_IMPORT_BY_NAME所指向的每个被载入函数的地址。然后通过加载器将值填充到FristThunk指向的IAT表中。

接下来对比一下加载前后的INT表和IAN表值变化:

加载前

加载后,显示IAT的值已经填充了函数地址

我们最后要用到的即使PE加载后的ITA表。

0x03 实例讲解如何找到输入表的FileOffset

前面我们已经详细讲解了怎么找到数据目录表,这里就不再缀述。我们直接找到数据目录表的第二项,它的位置在180h处如下图:

由此可知输入表的RVA值为3000h,大小为52h。

其实我们也可以可以直接在lordPE的区段表中找到FileOffset的值如下图:

值为A00h。

用hexwrokshop直接跳转到该位置(大小为52h)。如下图:

由于IMAGE_THUNK_DATA的五个字段都是双字,因此按照八个字节依次读出数组中第一个结构的每个字段:第一个OriginnalFristThunk为:0000 3028 第一个TimeDateStamp为00000000。第一个ForwardChain为:00000000。第一个Name值为:00003038,第一个FristThunk值为:00003030

也可以用LordPE查看IMAGE_THUNK_DATA的字段值及名字如下图:

可以知道调用了的是USE32.DLL。

数组中的其余值也可以依次读写出来

PE文件格式详解(五)的更多相关文章

  1. PE文件格式详解,第一讲,DOS头文件格式

    PE文件格式详解,第一讲,DOS头文件格式 今天讲解PE文件格式的DOS头文件格式 首先我们要理解,什么是文件格式,我们常说的EXE可执行程序,就是一个文件格式,那么我们要了解它里面到底存了什么内容 ...

  2. PE文件格式详解(七)

    PE文件格式详解(七)   Ox00 前言 前面好几篇在讲输入表,今天要讲的是输出表和地址的是地址重定位.有了前面的基础,其实对于怎么找输出表地址重定位的表已经非常熟悉了.   0x01 输出表结构 ...

  3. PE文件格式详解,第二讲,NT头文件格式,以及文件头格式

    PE文件格式详解,第二讲,NT头文件格式,以及文件头格式 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) PS:本篇博客 ...

  4. PE文件格式详解,第三讲,可选头文件格式,以及节表

    PE文件格式详解,第三讲,可选头文件格式,以及节表 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) 一丶可选头结构以及作 ...

  5. PE文件格式详解(六)

    0x00 前言 前面两篇讲到了输出表的内容以及涉及如何在hexWorkShop中找到输出表及输入DLL,感觉有几个地方还是没有理解好,比如由数据目录表DataDirectory[16]找到输出表表后以 ...

  6. PE文件格式详解(下)

    作者:MSDN译者:李马 预定义段 一个Windows NT的应用程序典型地拥有9个预定义段,它们是.text..bss..rdata..data..rsrc..edata..idata..pdata ...

  7. PE文件格式详解(上)

    作者:MSDN 译者:李马 摘要 Windows NT 3.1引入了一种名为PE文件格式的新可执行文件格式.PE文件格式的规范包含在了MSDN的CD中(Specs and Strategy, Spec ...

  8. PE 文件格式详解

    PE文件 是微软 Win32 环境下可执行文件的标准格式. 所谓的可执行文件并不仅仅是常见的 EXE 文件,DLL,SYS,VXD 等文件也都属于 PE 格式. |-------> DOS_MZ ...

  9. PE文件格式详解(一)

    PE文件格式介绍(一) 0x00 前言 PE文件是portable File Format(可移植文件)的简写,我们比较熟悉的DLL和exe文件都是PE文件.了解PE文件格式有助于加深对操作系统的理解 ...

随机推荐

  1. CMAKE工具学习

    最近在学习各大物联网平台的SDK包,发现其工程都使用了一种叫cmake的工具在管理代码.于是花了一天时间简单学习了解了cmake工具,其目的是让自己能读懂使用该工具管理的代码,并能简单使用该工具管理我 ...

  2. kvm的命令简单使用

    virsh命令常用参数总结   参数 参数说明 基础操作 list 查看虚拟机列表,列出域 start 启动虚拟机,开始一个(以前定义的)非活跃的域 shutdown 关闭虚拟机,关闭一个域 dest ...

  3. ES索引操作

    1.创建测试索引 PUT /test_index{ "mappings": { "test_type":{ "properties": { ...

  4. PMBOK 基础知识(1)

    启动.结束过程 项目管理计划 第一章  引论 第2章项目运行环境 第3章 项目经理的角色 第4章 项目整合管理 第5章 项目范围管理 第6章 项目进度管理 第7章 项目成本管理 第8章 项目质量管理  ...

  5. 变分(图)自编码器不能直接应用于下游任务(GAE, VGAE, AE, VAE and SAE)

        自编码器是无监督学习领域中一个非常重要的工具.最近由于图神经网络的兴起,图自编码器得到了广泛的关注.笔者最近在做相关的工作,对科研工作中经常遇到的:自编码器(AE),变分自编码器(VAE),图 ...

  6. eclipse中testNG的两种安装方式

    今天给大家带来两种关于testNG中的安装方式:1.在线安装(本人亲测有效!!!)2.离线安装 一.在线安装testNG插件的步骤: 1.给大家提供一个testNG在线的安装的地址:http://dl ...

  7. DeDecms远程写入漏洞webshell (dedecms漏洞)

    解释下Apache解析文件的流程: 当Apache检测到一个文件有多个扩展名时,如1.php.bak,会从右向左判断,直到有一个Apache认识的扩展名.如果所有的扩展名Apache都不认识,那么变会 ...

  8. spring cloud系列教程第八篇-修改服务名称及获取注册中心注册者的信息

    spring cloud系列教程第八篇-修改服务名称及获取注册中心注册者的信息 本文主要内容: 1:管理页面主机名及访问ip信息提示修改 2:获取当前注册中心的服务列表及每个服务对于的服务提供者列表 ...

  9. 链式前向星存树图和遍历它的两种方法【dfs、bfs】

    目录 一.链式前向星存图 二.两种遍历方法 一.链式前向星存图:(n个点,n-1条边) 链式前向星把上面的树图存下来,输入: 9 ///代表要存进去n个点 1 2 ///下面是n-1条边,每条边连接两 ...

  10. 面向对象存储框架:Obase快速入门

    在项目中完成对象建模后,可以使用Obase来进行对象的管理(例如对象持久化),本篇教程将创建一个.NET Core控制台应用,来展示Obase的配置和对象的增删改查操作.本篇教程旨在指引简单入门. 本 ...