查看PE文件IMAGE_NT_HEADERS下IMAGE_OPTIONAL_HEDER的 IMPORT Table的值
由上图可知 IDT的地址(RVA)为84CC (在PEView中设置视图选项为RVA)
TestView.exe的IDT存在于.rdara节区。IDT是有IMAGE_IMPORT-descriptor(简称IID)结构体组成的数组,且数组末尾以NULL结构体结束。由于每个导入的DLL文件都对应1个IID结构体(每个IID结构体的大小为14个字节) 所以图中整个IID区域为RVA:84CC~852F(8530? 84cc+64)
在PEView工具栏中视图改为File Offset 可以看到IDT文件偏移为76CC
使用HxD工具打开TexView.exe文件 找到000076CC地址处
IDT的文件偏移位76CC~772F(76CC+64? 7730),整个大小为64字节,共有5个IID结构体,其中最后一个为NULL结构体,从图中可以看出IDT尾部存在其他数据,没有足够空间来添加myhack3.dll的IID结构体
在这种情况下 我们要先把整个IDT转移到其他地方,然后再添加新的IID,可以用以下三种方式
1、查找文件中的空白区域
2、增加文件最后一个节区大小
3、在文件末尾添加新节区(个人推荐)
这里用第一种方式 查找文件中空白区域(程序运行时未使用的区域)
如图 .rdata节区尾部恰好存在大片空白区域(一般来说 节区或文件尾部都存在空白区域,PE文件中这种空白区域称为Null-Padding区域)
接下来要把原IDT移动到该Null-Padding区域(RVA:8C60~8DFF)中合适的位置。
在此之前先确认该区域是否全是空白可用区域,注意并不是文件中的所有区域都会被无条件加载到进程的虚拟内存,只有节区头中明确记录的区域才会被加载。使用PEView工具查看文件的.rdata节区头
节区头中存储着对应节区的位置、大小、属性等信息
从节区头信息可以看出 .rdata节区在磁盘文件与内存中的大小是不同的
.rdata节区在磁盘文件中大小为2E00,而文件执行后被加载到内存时,程序实际使用的数据大小(映射大小)仅为2C56 未被使用的区域大小为1AA(2E00-2C56),所以在这一段空白区创建IDT不会有问题
由于Null-Padding区域可用,接下来要在RVA:8C80(RAW:7E80)位置创建IDT
先复制备份文件
IMAGE_OPTIONAL_HEADER 的导入表结构体成员来指出IDT的位置(RVA)与大小
文件中,导入表的RVA值为84CC 接下来将导入表的RVA值更改为新IDT的RVA值8C80 在Size原值64字节的基础上加14个字节(IID结构体的大小),修改为78字节
以上完成导入表位置修改为RVA:8C80(RAW:7E80)地址处
BOUND IMPORT TABLE(绑定导入表)是一种提高DLL加载速度的技术
若想正常导入dll 需要向绑定导入表添加信息,但幸运的是,该绑定导入表是个可选项,不是必须存在的,可以删除(修改其值为0即可)以获取更大便利,当然绑定导入表完全不存在也没关系,但若存在,且信息记录错误,则会在程序运行时应发错误。本例绑定导入表各项值为0不需要修改,修改其他文件时一定要注意检查绑定导入表中的数据。
创建IDT
先使用Hex完全复制原IDT(RAW:76CC~772F),复制到新IDT的位置(RAW:7E80)
然后在新IDT尾部(RAW:7ED0)添加与myhack3.dll对应的IID
在准确位置(RAW:7ED0)写入相关数据1
2
38D00 RVA to INT
8D10 RVA to DLL Name
8D20 RVA to IAT
接下来设置Name、INT、IAT
前面天假的IID结构体成员拥有指向其他数据结构(Name、INT、IAT )的RVA值,因此,必须准确设置这些数据结构才能保证.exe文件正常运行,由前面设置可知INT、Name、IAT的RVA/RAW值 整理如下
这些地址(RVA:8D00 8D10 8D20)就位于新创建的IDT(RVA:8C80)下方,在HxD编辑器中转到7F00地址处,输入相应值
为了更好理解 使用PEView打开修改好的.exe查看同一区域
8CD0地址存放着myhack3.dll的IID结构体,其中3个主要成员(RVAofINT、RVAofName、RVAofIAT)的值分别是实际INT、NAME、IAT的指针
简单地说 INT(Import Name Table 导入名称表)是RVA数组,数组的各个元素都是一个RVA地址,该地址由导入函数的Ordinal(2个字节)+Func Name String结构体组成,数组的末尾为NULL,上图中INT有1个元素,其值为8D30,该地址处是要导入的函数的Ordinal与函数的名称字符串(”dummy”)
Name是包含导入函数的DLL文件名称字符串,在8D10地址处可以看到“myhack3.dll”字符串
IAT也是RVA数组,各元素即可拥有与INT相同的值,也可以拥有与其他不同值(若INT中的数据准确,IAT也可以拥有其他不通知)反正实际运行时,PE装载器会将虚拟内存中的IAT替换为实际函数地址
修改IAT节区的属性值
加载PE文件到内存时,PE装载器会修改IAT,写入函数的实际地址,所以相关节区一定要拥有WRITE可写属性,使用PEView查看.rdata节区头
向原属性值(Characteristics)400000040添加IMAGE_SCN_MEM_WRITE(80000000)属性值,执行bit OR运算,最终属性值变为C00000040(400000040+80000000?)
至此完成了DLL注入修改
小结:1
2
3
4
5
6先查看是否有足够空间,若有则直接向后添加,若无则寻找空白空间或新添加空间
找到IMAGE_OPTIONAL_HEADER的RVA与大小,修改大小(原size+14*个数)(一个IID结构为14字节)
删除绑定导入表,避免错误
创建新IDT,先将员IDT复制到第一步找到的新地址,然后在尾部添加与你想要添加的.dll对应的IID
设置Name、INT、IAT(注意RVA与RAW换算)
修改IAT节区的属性值为可写