首先,让我们思考一个问题,应用程序是如何找到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>>
加载前
加载后
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2020-11-9 11:21
被Golden_Boy编辑
,原因: