为什么要修复IAT?
首先得说一下程序调用DLL导出函数的原理,
PE调用DLL里的函数,一般是先加载这个DLL模块到它的进程地址空间,
然后在加载后的地址范围内找到每个调用函数的地址,
在程序中你可以使用LoadLibrary()这个系统API去动态去加载某个DLL,
再通过GetProcAddress()系统API来找到DLL导出的某个函数地址,
得到函数地址了你才能使用这个函数。
用户DLL被加载后的基址可发生变化,导入的函数地址不是固定的,你不能使用固定的地址。
系统DLL虽然基址固定,函数地址固定,但是一般不会直接使用函数硬地址,
还是要GetProcAddress()这个API来得到地址,因为XP、win7等每个系统的这些地址
是不一样的,会导致兼容性问题。
关于导入表,
而为了开发更方便和更人性化,编译器提供了这个静态导入函数的功能,
也就是说你在编程的时候不需要LoadLibrary(),不必每次调用一个函数都GetProcAddress(),
你只需要在源代码中写函数名和参数即可,编译器会将你使用的<函数名>和函数所在的<DLL文件名>
两个信息填写到输入表里,当程序启动运行时由操作系统根据这两个信息给程序加载
所需的DLL,并将所需要的函数地址写入IAT。
IAT是指PE导入地址表,每个IAT就对应了一个DLL文件导入函数的地址表,
你的程序里调用的地址不是直接调用DLL里函数的地址,因为你不知道地址是多少,
而是直接调用了IAT里的地址。程序启动时操作系统加载所需的DLL并填充导入名称表INT对应的
函数地址到地址表IAT对应PIMAGE_THUNK_DATA结构里,然后程序就可以正常调用IAT中这些函数地址了。
壳的工作原理,
某些加壳程序加壳后会修改了原来导入目录表的位置为壳的导入表,
这样默认的导入表指向壳部分的导入表,你就看不到原来的导入表的内容了。
程序启动后,操作系统为壳的导入表加载,
在壳代码运行完成之后,壳代码会跳到原程序的入口点OEP,壳模拟操作系统填充
原来导入表IAT,这样保证代码段能正常调用函数。
一般壳的工作原理也就是这样了,随着现在加壳加密技术的进步,不是所有加壳软件都会这样。
脱壳原理,
首先修改被加壳程序的入口点到程序原来的OEP,
然后修改PE程序导入表目录地址为原来导入表地址,或者新建一个节,
将这个新节作为导入表节,并将原导入表内容写入新节导入表。
脱壳过程,
OD跟踪,让壳运行到原程序OEP(不一定非得OEP,程序领空导入表一般都是处于还原状态,
OEP要知道),这时候可以用PE DUMP脱壳插件或者用LordPe等工具脱壳,
程序当前的内存映像被dump出来,里面IAT结构完整很容易被发现。
dump后程序不能正常运行很可能是导入表位置错误(也可能是程序有自校验),
因为dump出来的只是内存中的映像快照,导入表目录还是指向壳的导入表,
这时,需要用导入表修复软件查找dump出的PE文件原导入表首地址,
然后修正导入表目录中导入表的位置,或重建导入表。
Import Fix导入表修复软件会新建一个节来保存原导入表数据,并将导入表目录指向新节导入表位置。
在搜索导入表时可能导入表被破坏,Import Fix会识别出一些无效的IAT项,可以将其剔除掉。
by 小覃 2012,06,10 看雪论坛
http://www.qinrihong.com/
http://www.weibo.com/qinrihong
以上是个人的描述,如有不正确之处欢迎大牛们指正!