滴水-day22-PE空白区添加代码
手动在代码空白区添加代码
注意文件与内存对齐。
添加代码的地址是ImageBuffer中的偏移,而不是文件中的。
call(E8)跳转的地址不是真正的地址,而是由真正的地址经过运算得到的硬编码
call(E8) X (X是四字节)
X = E8 - (E8当前地址+5)
这些地址说的都是内存中的。
对于文件对齐与内存对齐不一样的程序在计算E8后面的位置和E9后面的位置的时候计算方式不再是直接加上ImageBase了。
由于对齐不同,需要计算文件地址在内存中的地址,也就是文件偏移到内存偏移
计算公式:
内存偏移 = (文件偏移(File Offset) - 该地址所在节的物理偏移(Raw Offset) + 该地址所在节的虚拟偏移(Virtual Offset)) + 基地址(ImageBase)
例如我的A程序
.text 00011000 00005509 00000400 00005600 60000020
我想要在5918处添加CALL MessageBox(76150F40)
那么CALL的地址计算方式就是:
((5918+5) - 0x400 + 0x11000) + 0x400000 = 41651D
76150F40 - 41651D = 75D3AA23
75D3AA23就是CALL的地址
JMP的计算方式与这个一样,都是计算文件偏移到内存偏移
PS:在计算call的地址时候尽量关闭程序的随机基地址,否者call的地址与实际地址不同
JMP不受影响
练习
PETool 1.0.0.5.exe文件注入代码
MessageBoxA地址:76150F40
E8 X
X = 76150F40 - (233E8 + 5 == 233ED - 1000 + 1000)+ 00400000 = 4233ED = 75D2DB53
004233ED
E8 53 DB D2 75
E9 X
X = 000193BE + 00400000 - (233ED + 5 - 1000 + 1000) + 00400000 = 4233F2 = FFFF5FCC
E9 CC 5F FF FF
修改OEP
233E0
小记
在修改OEP的时候,尽量使用相对虚拟地址而不是虚拟地址。
相对虚拟地址:虚拟地址 - 该地址所在节的物理偏移 + 该地址所在节的虚拟偏移
而在修改E8 E9后的地址的时候尽量使用虚拟地址,因为这些是需要直接运行的代码,也就是在内存中的状态而虚拟地址就是在内存中的状态
虚拟地址:相对虚拟地址+基地址
为何OEP不能使用虚拟地址呢?
因为在程序在运行后会自动拉伸代码,自动计算入口点,入口点就是OEP+基地址。这些程序会自动完成,如果在文件中OEP使用了虚拟地址那么程序在拉伸后就是虚拟地址+基地址。这样肯定是不行的,因为虚拟地址已经是可运行状态了。
相对虚拟地址也可以理解为是FileBuffe,经过ImageBuffer运行后转为可执行地址。
Shellcode使用虚拟地址(VA)****:因为在程序运行时,代码段在内存中的位置是虚拟地址。
OEP使用相对虚拟地址(RVA):因为OEP在程序加载时是相对于模块基地址的偏移,操作系统会自动将其转换为虚拟地址。