首页
社区
课程
招聘
[原创][原创]脱壳系列2_IAT重定向及其修复
发表于: 2020-10-19 19:49 25456

[原创][原创]脱壳系列2_IAT重定向及其修复

2020-10-19 19:49
25456

   

  首先,让我们思考一个问题,应用程序是如何找到API的地址的?

 找到一个API调用


enter 跟进

这里是一个间接跳转表,(这里有人可能会有疑问,为什么不直接用API的地址)考虑到操作系统的版本,各个dll的版本,考虑到兼容问题,操作系统必须提供一些措施来确保应用程序可以在其他版本的windows操作系统和dll版本下也能正常运行。

我们看看4031ac处是什么,右键->follow in dump->memory in address

这里保存的是74d9f8b0,这一片地方包含了该程序调用的所有API的地址,我们称它为IAT,因为间接跳转(jmp xxx)所以在不同版本操作系统上仍能找到API的地址,只要将不同系统中的API函数地址填充到IAT中,就能解决不同操作系统兼容的问题

将API的地址填充到IAT中是由操作系统自动完成的,那么操作系统是如何做到的那,我们选中74d9f8b0右键->view executable file,看看4031ac对应的可执行文件中的文件偏移

可执行文件中对应的内容为603300,我们看看该位置处是什么

同时定位到可执行文件中

发现是同样的内容

是MessageBoxA这个字符串

总结一下,操作系统根据这个指针定位到API函数的名称,然后调用GetProcAddress获取地址填充到IAT中.我们来看看GetProcAddress这个函数,这里,MSDN给出了解释

好了,让我们总结一下程序启动时操作系统将正确地址填充到IAT中的充分条件是什么:可执行文件的IAT所对应的文件偏移处必须是一个指针,同时,这个指针指向该API的名称.

我们给该程序加壳,定位到相同地址处

此处竟然是空的,为什么会这样?因为壳把IAT给破坏了,我们运行到OEP

此时IAT已经填上了正确的地址

这期间发生了什么?壳首先会执行解密例程,读取API的名称指针,然后定位到API的地址,将其填入IAT中,此时,API名称字符串已经不需要了.换言之,壳只需要获得API的名字,所以,有的壳会将API的名称加密,以密文的形式保存到某个地址处,以防止被破解.

就算我们在OEP处将程序dump出来,程序依旧无法运行,因为IAT已经被破坏了,壳被拿掉,填充IAT的任务由操作系统完成,但是,这个时候填充IAT的信息是不足的.

下面我们来dump

在OEP处打开LoadPE

右键active dump engine->intellidump->select,然后右键 dump full,这里我把它放到了桌面上,注意,本过程全部在虚拟机中然后双击直接运行


报错.

下面我们来修复IAT,OD定位到OEP处,不要关闭OD

我们在原程序中随便找一处API调用,enter跟进,我们来到跳转表

定位到IAT后将数据窗口上下滚动,如上图

注意:有些壳会在IAT的界限处填上垃圾数据来误导我们,还有的直接将IAT部分填零

好了,现在我们得到了IAT的起始地址和结束地址

OEP:1000 (401000-400000) RVA:3184 (IAT的起始地址,403184-400000) Size:108(40328c-403184)

填入IMPORT REC,然后单机get imports

单击fix dump 选中之前dump出来的文件

双击运行




下面来介绍一下导入表(IT)在PE中的叫法为IMAGE_IMPORT_DESCRIPTOR(这里可以参考<<加密与解密4>>讲的很详细)


   

typedef struct _IMAGE_IMPORT_DESCRIPTOR {

    union {

        DWORD   Characteristics;            // 0 for terminating null import descriptor

        DWORD   OriginalFirstThunk;         // RVA to original unbound IAT (PIMAGE_THUNK_DATA)

    } DUMMYUNIONNAME;

    DWORD   TimeDateStamp;                  // 0 if not bound,

                                            // -1 if bound, and real date\time stamp

                                            //     in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)

                                            // O.W. date/time stamp of DLL bound to (Old BIND)

 

    DWORD   ForwarderChain;                 // -1 if no forwarders

    DWORD   Name;

    DWORD   FirstThunk;                     // RVA to IAT (if bound this IAT has actual addresses)

} IMAGE_IMPORT_DESCRIPTOR;

typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;


IMAGE_IMPORT_DESCRIPTOR简称IID,每组20个字节,  name是指向DLL名称的指针,FirstThunk指向该DLL导入的所有API

这里我们了解一下导入表的双桥结构作为延伸,感兴趣的参考<<加密与解密4>>

加载前


加载后


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2020-11-9 11:21 被Golden_Boy编辑 ,原因:
收藏
免费 3
支持
分享
最新回复 (8)
雪    币: 12
活跃值: (60)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
请问3184跟328C是从哪里找出来的?
2020-11-9 10:12
0
雪    币: 183
活跃值: (6634)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
3
edens 请问3184跟328C是从哪里找出来的?
算的,不是给公式了吗
2020-11-9 10:16
0
雪    币: 12
活跃值: (60)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
抱歉我刚才没问清楚
我是指以这张图来看 JMP的第一行跟最后一行吗?
IAT的起始地址和结束地址的部份
https://bbs.pediy.com/upload/attach/202010/830337_X2GU5WMRNBGEYBZ.jpg
2020-11-9 13:16
0
雪    币: 183
活跃值: (6634)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
5
edens 抱歉我刚才没问清楚 我是指以这张图来看 JMP的第一行跟最后一行吗? IAT的起始地址和结束地址的部份 https://bbs.pediy.com/upload/attach/202010/83 ...
右键follow in dump,转到数据窗口中
2020-11-9 17:32
0
雪    币: 249
活跃值: (93)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
实验用的程序能发一下吗
2020-12-10 13:30
0
雪    币: 249
活跃值: (93)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
第一个程序加的是什么壳
2020-12-10 21:13
0
雪    币: 377
活跃值: (5996)
能力值: ( LV4,RANK:55 )
在线值:
发帖
回帖
粉丝
8
不错,以前还在想失效的是什么,那时候没深入研究,现在明白了原来是重定向了
2021-5-14 17:10
0
游客
登录 | 注册 方可回帖
返回
//