导入表解析,IAT表解析【滴水逆向三期53笔记】

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 导入表解析,IAT表解析【滴水逆向三期53笔记】

我们再上一章节简要介绍了IAT表,我们知道如果程序调用dll中的函数时,必须通过IAT表来找到函数,我们基本了解了IAT表之后,我们今天来讲解一下导入表,通过本章节的学习,我们可以了解导入表,也能对IAT表有一个更深入的了解。

一.导入表是什么?

我们可以将导入表比作餐厅的菜单,而dll中函数的地址,就可以被比作为菜单上的菜品。

也就是说,导入表记录了dll中的函数名称和地址,exe在调用dll中的函数的时候,就可以通过导入表来找到函数。这里注意区分导入表和IAT表,IAT表是exe在调用dll中的函数时,通过IAT表中记录的地址来找到函数,而导入表记录了dll的名称,还有dll中函数的地址和名称(也有函数的导出序号)。

那么我们来看看导入表的结构:

typedef struct_IMAGE_IMPORRT_DESCRIPTOR{
  union{
  DWORD Characteristics;
  DWORD OriginaFirstThunk;//指向IMAGE_THUNK_DATA(输入名称表)结构数组的RVA
  }
  DWORD TimeDateStamp;//时间戳(当可执行文件不与被输入的DLL进行绑定时,此字段为0)
  DWORD ForwarderChain;//第一个被转向的API索引
  DWORD Name;//指向被输入的DLL的名称字符串的第一个字符RVA
  DWORD FirstThunk;//指向输入地址表(IAT表)的RVA,IAT是一个IMAGE_THUNK_DATA结构的数组
}IMAGE_IMPORT_DESCRIPTOR;
typedef IMAGE_IMPORT_DESCRIPOTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;

解析:

该导入表结构中:

OriginaFIrstThunk中存储的是一个地址,指向IMAGE_THUNK_DATA(导入名称表)该表中记录了导入函数的名称,也被叫做INT表,该表的结束标志和很多表一样:最后一张表的数据全为0。

Name中存储的是指向该dll文件名的RVA

FirstThunk中存储的是该文件的IAT(import address table)表的RVA,因为导入表和IAT表都和调用的dll文件中的函数有密切关系,所以他俩总是在一起,该表的结束标志和很多表一样:最后一张表的数据全为0。

找到IAT表有两种方式:一种是通过数据目录的第13个项目的VirtualAddress找到,另一种方式是通过导入表的FirstTrunk找到

我们知道一个程序可能调用了很多dll文件,所以导入表也不只一张,VirtualAddress(数据目录中的第二个元素为导入表) 指向多个一样的导入表结构。

二.导入表详解

我们想要了解导入表,必须通过程序运行前和程序运行中两种状态来了解,也就是程序未被加载前和程序和调用的dll都被加载到独立4GB空间两种状态下:

我们给出图来帮助我们理解:

程序未被加载前:

我们可以很清楚地观察到,在程序未被加载前,INT(导入名称表)和IAT(导入地址表)中存储的地址都指向同一个地方:该处存储了函数名称字符串或函数导出序号,我们在上一章中也在程序二进制文件中观察到存储了MessageBoxA(上一章节存储了MessageBoxA是因为我写的程序调用了MessageBox函数),那么我们如何判断INT(导入名称表)中的元素到底是函数导出名称还是导出序号呢?

这里给出判断INT表中某一项方法:

在INT(导入名称)表中,若该项最高位为1,那么去除最高位,剩下的就是该函数的导出序号

若该项最高位为0,那么这一项就是RVA,指向IMAGE_TRUNK_BY_NAME。

typedef struct _IMAGE_THUNK_DATA32 {            
    union {           
        PBYTE  ForwarderString;           
        PDWORD Function;            
        DWORD Ordinal;             //序号
        PIMAGE_IMPORT_BY_NAME  AddressOfData;//指向IMAGE_IMPORT_BY_NAME
    } u1;           
} IMAGE_THUNK_DATA32;           
typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;           
typedef struct _IMAGE_IMPORT_BY_NAME {            
    WORD    Hint;           //可能为空,编译器决定 如果不为空 是函数在导出表中的索引
    BYTE    Name[1];            //函数名称,以0结尾
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;   

IMAGE_IMPORT_BY_NAME 中的 Name 并不只有 1 个字节,而是一直遍历到元素为 ‘\0’ 为止,OriginalFirstThunk 和 FirstThunk 的遍历 具体详见下图(这俩的遍历都一样的,其实都是遍历的 IMAGE_THUNK_DATA)。

程序和调用的dll被加载后:

我们来思考一个问题:既然INT表和IAT表都指向同一个地方,那么我们为什么需要两张表呢?

我们再上一章简单解析了IAT表,我们知道程序在调用dll中的函数时,要通过IAT表来间接寻址,如果只用一张表的话,在程序被加载后,IAT表中的项目被改为函数地址,那么程序不就不知道函数名称了吗?这就是为什么要有INT表和IAT表的原因。

我们可以观察到:在程序和调用的dll被加载后,IAT表中的项目不再指向函数名称,通过上一章节的简析,我们知道它指向了函数被加载后的真正地址,当程序调用函数时,通过IAT表就可以找到函数真正的位置了。

IAT 表在文件加载完成后系统会调用 GetProcAddress() 函数,就是做的我们前面写过的根据导出表函数序号或函数名字找到函数地址的功能。系统会循环 INT 表,根据表内的名字或序号调用 GetProcAddr() 得到地址,依次添加到 IAT 表中。

注意 IMAGE_IMPORT_BY_NAME 中的 Hint 不是导出序号,而是当前这个函数在导出表函数地址表中的索引。但基本没用,所以不一定是准确的,可以全部为0。而Name并不是一字节,而是以’\0’结尾的不定长字符串。

三.打印一个程序的导入表的信息(作业思路)

这里先给出基本思路(这里是打印程序未被加载前的导入表):

1.通过数据目录的第二项的VirtualAddress转换为FOA在文件中找到导入表

2.输出dll名(导入表中Name字段转换为FOA在文件中找到)

3.遍历OriginalFirstTrunk(OriginalFirstTrunk字段转换为FOA在文件中找到),打印导出序号或导出名称(需要转换为FOA在文件中找到)

4.遍历FirstTrunk(导入表中FirstTrunk字段转换为FOA在文件中找到)

5.找到下一张导入表,循环2,3,4,直到某张表的导入表内数据全为零结束

相关文章
|
6月前
|
SQL 关系型数据库 MySQL
ClickHouse(18)ClickHouse集成ODBC表引擎详细解析
ClickHouse使用ODBC集成表引擎通过`clickhouse-odbc-bridge`安全连接外部数据库,支持Nullable类型。创建ODBC表引擎的SQL示例:`CREATE TABLE ... ENGINE = ODBC(connection_settings, db, table)`. 用户需配置`odbc.ini`,如在Ubuntu+MySQL上,为`clickhouse`用户授予权限。查询示例展示如何从MySQL检索数据到ClickHouse。查阅更多详情:[ClickHouse经典中文文档分享](https://zhangfeidezhu.com/?p=468)。
91 12
|
6月前
|
Java 关系型数据库 MySQL
ClickHouse(17)ClickHouse集成JDBC表引擎详细解析
ClickHouse通过JDBC桥接器`clickhouse-jdbc-bridge`连接到外部数据库,支持Nullable类型。使用`CREATE TABLE`语句配置JDBC引擎,如`ENGINE = JDBC(datasource_uri, db, table)`。示例展示了如何与MySQL交互,创建本地表并从远程MySQL表中查询和插入数据。此外,ClickHouse还支持JDBC表函数,允许临时查询远程表。相关系列文章在指定链接中提供。
388 7
|
3月前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
480 37
http数据包抓包解析课程笔记
http数据包抓包解析课程笔记
|
4月前
|
JSON 开发框架 JavaScript
【Azure Developer】使用.Net Core解析JSON的笔记
【Azure Developer】使用.Net Core解析JSON的笔记
|
4月前
|
数据采集 运维 监控
运维笔记:流编辑器sed命令用法解析
运维笔记:流编辑器sed命令用法解析
68 5
|
4月前
|
开发者 API 开发框架
Xamarin 在教育应用开发中的应用:从课程笔记到互动测验,全面解析使用Xamarin.Forms构建多功能教育平台的技术细节与实战示例
【8月更文挑战第31天】Xamarin 作为一款强大的跨平台移动开发框架,在教育应用开发中展现了巨大潜力。它允许开发者使用单一的 C# 代码库构建 iOS、Android 和 Windows 应用,确保不同设备上的一致体验。Xamarin 提供广泛的 API 支持,便于访问摄像头、GPS 等原生功能。本文通过一个简单的教育应用示例——课程笔记和测验功能,展示了 Xamarin 在实际开发中的应用过程。从定义用户界面到实现保存笔记和检查答案的逻辑,Xamarin 展现了其在教育应用开发中的高效性和灵活性。
49 0
|
6月前
|
存储 编解码
FFmpeg开发笔记(三十)解析H.264码流中的SPS帧和PPS帧
《FFmpeg开发实战》书中介绍了音视频编码历史,重点讲述H.264的成功在于其分为视频编码层和网络抽象层。H.264帧类型包括SPS(序列参数集,含视频规格参数),PPS(图像参数集,含编码参数)和IDR帧(立即解码刷新,关键帧)。SPS用于计算视频宽高和帧率,PPS存储编码设置,IDR帧则标志新的解码序列。书中还配以图片展示各帧结构详情,完整内容可参考相关书籍。
262 7
FFmpeg开发笔记(三十)解析H.264码流中的SPS帧和PPS帧
|
4月前
|
Go
【go笔记】使用标准库flag解析命令行参数
【go笔记】使用标准库flag解析命令行参数
|
6月前
|
SQL 缓存 关系型数据库
ClickHouse(19)ClickHouse集成Hive表引擎详细解析
Hive引擎允许对HDFS Hive表执行 `SELECT` 查询。目前它支持如下输入格式: -文本:只支持简单的标量列类型,除了 `Binary` - ORC:支持简单的标量列类型,除了`char`; 只支持 `array` 这样的复杂类型 - Parquet:支持所有简单标量列类型;只支持 `array` 这样的复杂类型
227 1

推荐镜像

更多