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的地址会变化,所以要用重定位表来解决这个问题