更改PE文件加载动态库
最近看了《逆向工程核心原理》,其中第25.4节讲了更改PE文件让目标文件加载我们的动态库。现在做一下完整介绍。
PE文件的导入DLL信息存储在IDT中,于是我们只需将DLL加到目标PE文件的IDT中,这时我们得先看一下IDT的空间大小。
1.查看IDT:
首先用PEView查看目标程序,看IMPORT Directory Table内容
可见地址范围从76CC---772F,用HxD观察该范围内存空间
我们可以看到IDT由一个个结构体构成,每个结构体大小为0x14(20)字节
观察该地址范围,发现无法写下一个IMAGE_IMPORT_DIRECTORY结构体,于是我们需要寻找一个更大的空间去存储IDT
2.移动IDT
移动IDT我们有三种方法:
1.查找文件中的空闲区域
2.增加最后一个节区的大小
3.增加一个新节区
首先我们尝试第一种方法。
我们可以看到在节区的.rdata最后部分存在大量空白区域,PE文件称这种空白区域称为Null-Padding
这时我们还要确认这个部分是否可用,我们观察.rdata大小为2E00,但是实际使用大小为2C56于是,我们可以用剩下的1AA字节地址
我们在RAW:7E80(RVA:8C80)处创建IDT
数据的文件偏移=(数据RVA
- 节RVA) + 节的文件偏移
RVAtoRAW
RAW -PorinterToRawData = RVA- VirtualAddress
RAW = RVA -VirtualAddress+PointerToRawData(Address of Entry Point)
所以RVA=7E80(当前RAW)-5200(.rdata节起始RAW)+6000(.rdata节RVA)
现在新加入一个导入函数,导致IDT增大0x14字节,所以在更改文件160处的IDT的RVA为8C80,Size为78
3.删除绑定导入表
若要正常导入DLL,需要向绑定导入表添加信息。但是绑定导入表是个可选项,所以为了方便可删除。如果绑定导入表信息错误,则运行失败,但是没有绑定导入表反而没有问题。本例的绑定导入表信息为0,所以不用删除,但是其他文件需注意。
4.创建新的IDT
完全复制原IDT内容(76CC---772F ),然后覆盖到新的IDT地址处
5。设置NAME,INT,IAT
INT RVA=7F00-5200+6000=8D00
NAME RVA=7F10-5200+6000=8D10
IAT RVA=7F20-5200+6000=8D20
6.修改.rdata的属性
向IAT节区头添加IMAGE_SEC_MEM_WRITE(80000000)属性
至此,我们任务完成。
我们发现原文件的IAT也位于.rdata节区,且原.rdata节区并没有可写属性,为什么也可以正常运行呢?这是因为在PE头中的IMAGE_OPTIONAL_HEADER结构的DataDirectory数组中存在IAT,若IAT存在于该区域,即使相应的节区没有可写属性也没事。