PE3-17 代码节空白区添加代码
硬编码:E8 和 E9 指令
E8 和 E9 是 call 和 jmp 指令的操作码,后面跟的并不是直接的小端序地址。关键是如何计算跳转的地址。
call 例子:
1 | call 0x77E5425F |
jmp 例子:
1 | jmp 0x2345678 |
从这个例子可以看出,E8 和 E9 后面的地址不是直接的小端序转换。要理解如何生成这些字节,我们需要用一个公式来计算。
跳转地址的计算方式
真正要跳转的地址 = E8 或 E9 指令的下一条指令的地址 + X
其中:
X= 真正要跳转的地址 -E8或E9指令的下一条指令的地址
具体例子
1 | func(); |
解释:
在 00A825E1 的 call func 指令中,操作码 E8 后面的字节是 62 ED FF FF,它表示要跳转的偏移量。这个偏移量是如何计算出来的?
根据公式:
1 | X = 真正要跳转的地址 - (E8 指令地址 + 5) |
- 0xA81348 是
func的地址 E8的地址是0xA825E1- 下一条指令的地址是
0xA825E6(因为 E8 是 5 个字节)
所以:
1 | X = 0xA81348 - 0xA825E6 = 0xFFFFED62 |
转换成小端序格式:
1 | 62 ED FF FF |
因此,指令 E8 62 ED FF FF 就表示跳转到地址 0xA81348。
总结
E8和E9的操作码后面跟的并不是目标地址的直接小端序,而是目标地址与下一条指令地址的偏移量X。- 偏移量的计算公式是:
X = 目标地址 - (指令地址 + 5),然后将X转换为小端序。
Work
写一个windows程序,功能就是简单地弹出一个窗口
1 |
|

用x32dbg打开目标exe文件,在messagebox下断点(bp MessageBoxA)

记住MessageBox的地址0x75E9AC60
用PE Tools打开目标exe文件,查看节表的信息

可以看到在文件中,.text结束的地址是Raw Size +Raw Offset=0x2F000,放到010Editor里看看

可以看到还是有相当长的空闲区可以写,从0X2E880开始添加Shellcode
1 | 6A 00 6A 00 6A 00 6A 00 E8 xx xx xx xx E9 xx xx xx xx |
E8和E9后为地址,需要计算

查看Image Base

则E8指令的下一条指令的地址为0x42E88D(0x400000+0x2E880)
则x=0x75E9AC60-0x42E88D=0x75A6C3D3
查看Entry Point

Entry Point的地址为0x429008,E9指令的下一条指令的地址为0x42E892
则y=0x429008-0x42E892=0xFFFFA776
将x和y填入,注意小端序

最后再修改Entry Point的地址为0x2E880,由原来的Entry Point的地址为0x29008找到Entry Point的位置

修改为0x2E880

另存为后重新打开则会弹出弹窗

关闭弹窗后程序仍旧可以正常运行

但是这种改法仍旧有问题,因为每次messagebox的地址会变化,所以要用重定位表来解决这个问题