深入了解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 ...
随机推荐
- EntityFramework.Extended.Update.Ambiguous column name
异常描述 c#代码 dbcontext.Table.Where(x => x.B > 0).Update( x => new Table() { A = x.B } ) 抛出异常: ...
- 基于邮件系统的远程实时监控系统的实现 Python版
人生苦短,我用Python~ 界内的Python宣传标语,对Python而言,这是种标榜,实际上,Python确实是当下最好用的开发语言之一. 在相继学习了C++/C#/Java之后,接触Python ...
- HTML5+CSS3实现的响应式垂直时间轴
<!DOCTYPE HTML><html><head><meta charset="utf-8"><meta name=&qu ...
- 新技术探究之 GraphQL
What? GraphQL 是一种类似于 SQL 的结构化查询语言,由 facebook 于2012年创造,于2015年开源.SQL 在服务端定义,GraphQL 在客户端定义,也就是说 GraphQ ...
- 在SOUI中使用网格布局
在实现网格布局前,SOUI支持两种布局形式:相对布局,和线性布局,其中线性布局是2017年2月份才支持的布局. 这两年工作都在Android这里,Android里有号称5大布局(RelativeLay ...
- 最长非降子序列的O(n^2)解法
这次我们来讲解一个叫做"最长非下降子序列"的问题及他的O(n^2)解法. 首先我们来描述一下什么是"最长非下降子序列". 给你一个长度为n的数组a,在数组a中顺 ...
- 基于Spring MVC 实现拦截器
Spring MVC 拦截器 一,具体内容: 在所有的开发之中拦截器属于一个重要的组件,可以说几乎所有的项目都会提供的概念应用,不管是Spring MVC,还是Struts 2.x都是提供有拦截器的, ...
- 不用EF框架,完成完美实体映射,且便于维护!(AutoMapper,petapoco)
最近,需要搭建一个新项目,在需求分析时确定数据库中需要创建多个存储过程.所以如果还是用原来EF框架生成ADO.net实体模型的话,不利于修改. 主要是解决以下两个问题: 1.比如前端需要一个值,如果存 ...
- 高级Java程序员的技术进阶之路
据不完全统计,截至目前(2017.07)为止,中国Java程序员的数量已经超过了100万.而且,随着IT培训业的持续发展和大量的应届毕业生进入社会,Java程序员面临的竞争压力越来越大.那么,作为 ...
- 平板点餐软件编程体会---记我的Android编程之路
前言 想开发一个平板点餐系统,研究下陈江根大侠分享的一个很高水准的实例,只是个单机版无实用意义. (如需运行源码请回复联系邮箱) 实现 Mysql 数据库+Tomcat WEb服务器,使用Servle ...