深入了解IAT原理
---------------------------编辑时突然死机自动保存也没有用真的痛苦回头补上------------------
输入表中的这些间接跳转是无法正常运行的,因为在正常情况,操作系统必须知道指向各个API函数名称字符串的指针,然后通过GetProcAddress定位到各个API函数正确的入口地址并填充到IAT中,这样这些间接跳转才能起作用。可我们脱壳之后没有这些指针了自然也就无法运行了。
搞明白了问题下一步就着手重建输入表,下面我们来看看未加壳程序的IAT。
我们来定位该CrackMe PE结构中一些重要字段。首先在数据窗口中定位400000地址处。

单击鼠标右键选择-Special-PE header切换到PE头的显示模式。

往下拉。我们可以看到PE头的偏移为100。即PE头位于400100地址处。

继续往下拉,我们可以看到IT(导入表)的指针,这里大家不要将其跟IAT搞混淆了。
IT = 导入表
IAT = 输入函数地址表
我们知道当程序启动之前操作系统会将各个API函数的地址填充到IAT中,那么IT(导入表)又是怎么一回事呢?首先我们定位到导入表,该导入表偏移值为3000(即虚拟地址为403000),长度为670(十六进制),
即403670为导入表的结尾。我们一起来看一看。

我们将数据窗口的显示模式切换为正常状态,这就是导入表了,我们来介绍一下导入表的结构吧。

我们选中的这20个字节是导入表的描述符结构。官方的叫法为IMAGE_IMPORT_DESCRIPTOR。每组为20个字节,IMAGE_IMPORT_DESCRIPTOR包含了一个的字符串指针,
该指针指向了某个的动态链接库名称字符串。
这里我们将IMAGE_IMPORT_DESCRIPTOR简称为IID。这里选中的部分为导入表中的第一个IID,共五个DWORD,其中5个DWORD字段的含义如下:
OriginalFirstThunk
TimeDateStamp 时间戳
ForwarderChain 链表的前一个结构
Name1 指向DLL名称的指针
FirstThunk 指向的链表定义了针对Name1这个动态链接库引入的所有导入函数
前三个字段不是很重要,对于我们Cracker来说,我们只对第4,5字段感兴趣。
我们来看个例子:
正如大家所看到的,第4个字段为指向DLL名称字符串的指针,我们来看看403290处是哪个DLL的名称。
这里我们可以看到是USER32.DLL,第5个字段指向了USER32.DLL对应IAT项的起始地址,即403184。(不过我觉得位置不太对啊这也不是第四个DWORD啊而且403184在哪啊看不到啊)

既然我们已经知道了对应IAT的起始地址,那就跳到403184看看

这样我们就到达了IAT,导入表的结束地址为403670(根据起始地址和长度计算得到)。导入表中的每个IID项指明了DLL的名称以及其对应IAT项的起始地址。紧凑的排列在一起,供操作系统使用。
大量实验表明,IAT并不一定位于在导入表中。IAT可以位于程序中任何具有写权限的地方,只要当可执行程序运行起来时,操作系统可以定位到这些IID项,然后根据IAT中标明的API函数名称获取到函数地址即可。
下面我们来总结一下操作系统填充IAT的具体步骤:
1:定位导入表
2:解析第一个IID项,根据IID中的第4个字段定位DLL的名称
3:根据IID项的第5个字段DLL对应的IAT项的起始地址
4:根据IAT中的指针定位到相应API函数名称字符串
5:通过GetProcAddress获取API函数的地址并填充到IAT中
6:当定位到的IAT项为零的时候表示该DLL的API函数地址获取完毕了,接着继续解析第二个IID,重复上面的步骤。
下面我们来手工的体验一下这个步骤:
1)定位导入表

2)定位到导入表的起始地址

3)根据第一个IID项中的第四个字段得到DLL名称字符串的指针,这里指向的是USER32.DLL

根据第五个字段的内容定位到IAT项的起始地址,这里是403184,我们定位到该地址处。


这里我们可以看到已经被填充了正确的API函数的入口地址,跟我们dump出来的结果一样,我们再来看看相应的可执行文件偏移处的内容是什么。

这里我们可以看到第一个API函数的名称位于4032CC地址处,我们定位到该地址处。

第一个API函数是KillTimer,我们在OD中看到的KillTimer的入口地址是操作系统调用GetProcAddress获取到的。

这里我们可以看到KillTimer的入口地址为75EC79DB。该地址将被填充到IAT相应单元中去覆盖原来的值,我们看到已经被覆盖了。

这里是IAT中的第一元素。
我们再来看下一个元素,向后偏移4就是,是2f 7d ec 75这里,来看一看该API函数名称字符串的指针是多少。
定位到可执行文件的相应偏移处:

32D8即4032D8,来看看该API函数的名称是什么,这里由于该指针不为零,说明该API函数还是位于USER32.DLL中的。

这里我们可以看到第二个API函数是GetSystemMetrics,通过该函数名称可以通过GetProcAddress获取到其函数地址然后填充到IAT中。接下来按照以上步骤依次获取USER32.DLL中的其他的函数地址,直到遇到的IAT项为零为止。我们来看一看可执行文件中结束项位于哪里。
我们可以看到当IAT中元素为零的时候表明USER32.DLL就搜索完毕了,我们接着来看下一个IID。

这里我们根据第4,5字段分别可以知道第二个DLL的名称,以及对应IAT项的起始地址。
DLL的名称字符串位于40329B地址处。

我们可以看到第二个DLL为KERNEL32.DLL,该DLL对应的IAT项起始地址为40321C。
这里我们可以看到前一个DWORD是零,表示USER32.DLL的API函数的结尾。40321C表示KERNEL32.DLL的API函数地址项的开始。
根据这些指针我们就可以定位到kernel32.dll中的各个API函数名称字符串,进而获取到其函数入口地址,接着填充到对应的IAT项中覆盖原来的内容。
本章这里就结束了,我给大家描述了IAT被填充的整个过程,了解这个过程对大家来说是很有必要的,这部分内容是重建IAT必备的基础知识,大家只有理解了其基本原理,然后配上适当的工具,就可以方便进行IAT的修复工作了。
好了,下一章我们将介绍具体如何修复IAT。
仅允许非商业转载,转载请注明出处
深入了解IAT原理的更多相关文章
- IAT Hook 原理分析与代码编写
Ring 3层的 IAT HOOK 和 EAT HOOK 其原理是通过替换IAT表中函数的原始地址从而实现Hook的,与普通的 InlineHook 不太一样 IAT Hook 需要充分理解PE文件的 ...
- 浅谈IAT加密原理及过程
上一次做完代码段加密后,又接触到了新的加密方式:IAT加密 IAT加密是通过隐藏程序的导入表信息,以达到增加分析程序的难度.因为没有导入表,就无法单纯的从静态状态下分析调用了什么函数,动态调试时,也无 ...
- 手动修复IAT
现在我们已经了解了IAT的的工作原理,现在我们来一起学习手动修复IAT,一方面是深入了解运行过程一方面是为了避免遇到有些阻碍自动修复IAT的壳时不知所措. 首先我们用ESP定律找到加了UPX壳后的OE ...
- JSON Web Token(JWT)原理和用法介绍
JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案.今天给大家介绍一下JWT的原理和用法. 官网地址:https://jwt.io/ 一.跨域身份验证 Internet服务无法与 ...
- JWT认证原理及使用
一.JWT原理: 参考文章:https://www.jianshu.com/p/180a870a308a 1.传统的登录方式: 浏览器输入用户名密码,服务端校验通过,根据用户信息生成一个token,将 ...
- Visual Leak Detector原理剖析
认识VLD VLD(Visual Leak Detector)是一款用于Visual C++的开源内存泄漏检测工具,我们只需要在被检测内存泄漏的工程代码里#include “vld.h”就可以开启内存 ...
- Dll注入:修改PE文件 IAT注入
PE原理就不阐述了, 这个注入是PE感染的一种,通过添加一个新节注入,会改变PE文件的大小,将原有的导入表复制到新节中,并添加自己的导入表描述符,最后将数据目录项中指向的导入表的入口指向新节. 步骤: ...
- pandas DataFrame的查询方法(loc,iloc,at,iat,ix的用法和区别)
pandas DataFrame的增删查改总结系列文章: pandas DaFrame的创建方法 pandas DataFrame的查询方法 pandas DataFrame行或列的删除方法 pand ...
- IAT Hook
@author: dlive 0X01 IAT Hook的优缺点 优点:工作原理与实现都比较简单 缺点:如果想钩取的API不在目标进程的IAT中,那么就无法使用该技术进行钩取操作.即如果要钩取的API ...
随机推荐
- JAVA IO流结构图
InputStreamReader和OutputStreamWriter分别继承自java.io包中的Reader和Writer,对他们中的抽象的未实现的方法给出实现.如: public int re ...
- iOS 输入限制之 InputKit
前言 最近接手了两个 O2O 的老项目,其中的 Bug 也不言而喻,单看项目中的布局就有 n 种不同的方式,有用纯代码的,有用 Masonry 的,有用 VFL 的,也有用 Xib 的,更有用代码约束 ...
- [leetcode-593-Valid Square]
Given the coordinates of four points in 2D space, return whether the four points could construct a s ...
- 用php+mysql+ajax实现淘宝客服或阿里旺旺聊天功能 之 后台页面
在上一篇随笔中,我们已经看了如何实现前台的对话功能:前台我限定了店主只有一人,店铺只有一个,所有比较单一,但后台就不一样了,而后台更像是我们常见的聊天软件:当然,前台也应该实现这种效果,但原理懂了,可 ...
- JQuery——banner旋转木马效果
博主在浏览网页时无意间发现了一种banner图的轮播方式--像旋转木马一样的轮播方式,博主感觉非常新颖独特,经过查阅资料,观看某课网教程总算搞了出来的,其原理主要利用了JQuery代码实现,好了不多说 ...
- Ext秒表
Ext秒表 显示分和秒 js Ext.define('xy.StopWatchWindow', { extend: 'Ext.window.Window', width: 300, modal: tr ...
- Cordova(PhoneGap) 环境搭建与基础
Cordova(PhoneGap) 创建步骤:官方Guide 环境准备 安装 Node.js nodejs.org 安装 git git-scm.com (bin目录添加到path) 安装 cordo ...
- UGUI 字体背景长度自适应
本文实现以下需求: 在UGUI中 Text为动态添加 要使Text字体背景随着Text的长度而变化 之前还在赞叹UGUI的强大 转念一想,UGUI中好像没有可以实现此功能的组件 也想出了一种办法 把背 ...
- Building Apps for Windows 10 on LattePanda–Jump Start
1.引言 目前来看,LattePanda应该是最小的运行Full Windows 10系统的开发板了(注意,不是Windows 10 for Mobile,也不是Windows 10 IoT系列,而是 ...
- java 中的重载与重写 抽象类与接口的区别
. 重载与重写的区别: 重载(overload) | 重写(override) 1 方法的名称相同,参数个数.类型不同 | 方法名称.参数列表.返回值类型与父类完全相同 2 ...