这几天家里有点事情,所以更新慢了点,本来想把编程的部分一块儿更新了,谁知自己没太看明白.....今天贴一下导入表相关,真是难,看了好几遍,主要讲了3个表,导入表,导入函数地址表和绑定导入表。《PE》中说这部分内容在加壳时有重要应用,看来以后自己还得回过头再学。
4
4.1
导入表
1导入表
12导入函数地址表
11绑定导入表
13延迟加载导入表
实现代码重用
4.2
导入函数地址表的机制————编译时做了地址替换
//知识点1
文件对齐,代码在第一个段,400h
内存对齐,代码在第一个节,1000h
这两个地方开始应该是一样的(按ImageBase装载)
//知识点2
invoke api被编译分解成
压栈×n
call段内调用,跳转到地址XXXXXXXX(代码段)
jmp无条件转移,跳转到地址YYYYYYYY(导入函数地址表),这个地址存的值是API函数在内存中的VA
//知识点3
文件对齐,导入表在第二个段,600h
内存对齐,导入表在第二个节,2000h
//4
装入内存之前,YYYYYYYY存了一个地址A,指向API函数Hint/Name,编译器根据这个值
获取了API函数的VA,覆盖A
导入函数地址表中排列了所有导入函数的地址
4.3
三学导入表:
导入函数地址表的工作机制(get)
导入表
由一系列IMAGE_IMPORT_DECRIPTOR组成
每一个结构对应一个DLL文件
所有结构的最后有一个空结构收尾(全0)
IMAGE_IMPORT_DECRIPTOR
union
Characteristics
OriginalFirstThunk //指向一个双字数组,最后一个内容为0
ends
TimeDatestamp
ForwarderChain
Name //RVA,指向DLL文件名
FirstThunk //指向一个双字数组,最后一个内容为0
由Name找DLL
由双桥寻找具体的函数序号和名
OriginalFirstThunk和FirstThunk各指向一个双字数组,这两个双字数组是一样的
这个双字数组的最高位为1代表函数序号寻找,低位是函数的序号
最高位为0代表函数名寻找,是RVA
两个双字数组指向同一个结构数组,其中存储了函数序号和名
IMGE_IMPORT_BY_NAME
程序被装入内存后FirstThunk指向的双字数组被对应改写成函数的入口地址
这个双字数组就是导入地址表
所以一共有两种方法找到导入地址表
4.5
绑定导入机制
系统负责修正IAT的地址,如果函数多就会占用一些时间
解决办法:
在装载直接手动进行
在装载前由专门程序完成
需要告诉系统这些函数不需要你导入了
即:绑定地址表
但是,不同系统DLL加载的VA是不同的,所以微软又引入了检测错误的机制,
当绑定地址表不能完成任务时,加载程序就会接管
绑定导入表
由IMAGE_BOUND_IMPORT_DECRIPTOR结构数组组成
TimeDataStamp //纠错用
OffsetModuleName //以第一个IMAGE_BOUND_IMPORT_DESCRIPOR为基址,DLL名称字符串的偏移
NumberOfModuleForwarderResfsf //IMAGE_BOUND_IMPORT_DESCRIPOR后IMAGE_BOUND_FORWARDER_REF数组的个数
IMAGE_BOUND_FORWARDER_REF个数不定,为兼容使用