参考自《加密与解密》(第4版)第12章 注入技术
- 实验环境:Windows XP SP2 家庭版
- 实验素材:作者提供的MsgDLL.dll。此处的待注入DLL使用消息弹框来证明自己注入成功,实际中可以进行各种可怕又邪恶的动作。
- 修改对象:系统自带记事本
- 修改目标:记事本启动后,自动加载MsgDLL.dll
DLL文件代码细节省略,通过使用MessageBox函数来显示消息框,仅此而已。关于dll文件的编写,也是日后要好好学习的点。dll文件也有自己的主函数,博主未编写用于攻击的dll(即使编写了也不敢公然发),故在此一笔带过了。
本文的重点是修改输入表,故我们需对输入表的功能和结构有一个清晰的认识。
输入表,也称导入表,保存着PE文件载入时,一并加载的函数名和其驻留的DLL名等动态链接所需的信息。不想把各位朋友用理论烦走了,所以自己妄自总结一句话:就是指明PE文件执行时所使用的各个函数,这个过程中有对dll文件的装入,也有对每个dll文件中的函数进行实际定位最后写入函数名或序号与虚拟地址的映射关系表IAT。可以这么说,没有输入表,PE文件执行时就会像个无头苍蝇,更别提我们以后的加壳等练习了。
输入表的结构简称为IID,一个输入表就是一个数组,结构如下:
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
_ANONYMOUS_UNION union { //00h
DWORD Characteristics;
DWORD OriginalFirstThunk;
} DUMMYUNIONNAME;
DWORD TimeDateStamp; //04h
DWORD ForwarderChain; //08h
DWORD Name; //0Ch
DWORD FirstThunk; //10h
} IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR;
这里修改输入表,因为考虑增加的dll会增大导入表,进而可能将与之关联的OriginalFirstThunk和FirstThunk覆盖,故不如将其整体迁移到新的地址,最后修改一下导入表的地址就可以了。
新辟一块领土作为导入表,首先当然想找一个因为对齐带来的空洞,但往往我们很少有这样的机会。因此退而求其次,扩展最后一个节,或者增加一个节。本文使用了前者进行实现。
关于记事本,作为宿主,我们必须对其进行分析。首先我们看一下区段信息:
因为要满足两个条件,意识VirtualSize小雨RawSize,然后空洞大小要大于0xDC。这个数值是对上方输入表的结构研究后,newIIDSize=OldSize+sizeof(输入表)。如此我们就验证了前面说的,得到一个装得下新输入表的空洞,是很困难的。这里我们记录两个数值,用来扩展最后一个区段使用:
- 文件偏移:0x8400+0x8000=0x10400
- 内存偏移:0xB000+0x8000=0x13000
对IID的修改我们要使用十六进制编辑工具,推荐windbg,微软的产品,在windows上使用也是这样顺畅。这里我因为虚拟机的原因,使用Hex Workshop。
在LordPE分析notepad.exe的基础上,我们查看输入表的RVA:
可以看到,RVA为0x7604,则RawOffset=0x7604-0x1000+0x400=0x6A04,在HexShop中前往目标偏移地址:
如图,增加一项新的IID结构对象后,还要以全0来结尾,因此必然不能直接在这里添加。(会不会觉得我比较啰嗦)
把导入表送入的新地点,是在上方我们计算的0x10400开始的区域,如图:
如此,粘贴一下先:
继续添加00,确定待会儿新纪录的添加位置:
按部就班来,现在要返回原IID区域构造新的OriginalFirstThunk、FirstThunk和Name结构。Name此处即为Msg,但因其在不同例子下情况不一样,因此我们把两个偏移地址表放在前面。
- DLLName RawOffset = 0x6A14,RVA = 0x6A14-0x400+0x1000=0x7614
- IMPORT_BY_NAME RawOffset = 0x6A20 ,RVA=0x6A20-0x400+0x1000=0x7620
接着,我们填充OriginalFirstThunk、FirstThunk:
- OriginalFirstThunk RawOffset=0x6A04,RVA=0x7604
- FirstThunk RawOffset=0x6A0C,RVA=0x760C
修改时要注意字节的顺序,从后往前写。注:下面的偏移全部是内存偏移。
填写新的输入表IID结构:
如此,我们要修改输入表目录的位置信息和大小:
接着要修正新区块的属性,.text节原来的属性是0x60000020,为了增加可写属性,即在原来的属性上加上0x80000000,结果为0E000020,这样我们继续在对应位置修改:
最后:
ok了