硬编码:E8 和 E9 指令

E8 和 E9 是 calljmp 指令的操作码,后面跟的并不是直接的小端序地址。关键是如何计算跳转的地址。

call 例子:

1
2
call 0x77E5425F
E8 5F 42 E5 77 (这是错的)

jmp 例子:

1
2
jmp 0x2345678
E9 2B 2B 00 00

从这个例子可以看出,E8 和 E9 后面的地址不是直接的小端序转换。要理解如何生成这些字节,我们需要用一个公式来计算。

跳转地址的计算方式

真正要跳转的地址 = E8E9 指令的下一条指令的地址 + X

其中:

  • X = 真正要跳转的地址 - E8E9 指令的下一条指令的地址

具体例子

1
2
3
4
5
6
7
8
func();
00A825E1 E8 62 ED FF FF call func (0A81348h)
return 0;
00A825E6 33 C0 xor eax,eax
00A825E8 5F pop edi
00A825E9 5E pop esi
00A825EA 5B pop ebx
00A825EB 81 C4 C0 00 00 00 add esp,0C0h

解释:

00A825E1call 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

总结

  • E8E9 的操作码后面跟的并不是目标地址的直接小端序,而是目标地址与下一条指令地址的偏移量 X
  • 偏移量的计算公式是:X = 目标地址 - (指令地址 + 5),然后将 X 转换为小端序。

Work

写一个windows程序,功能就是简单地弹出一个窗口

1
2
3
4
5
6
7
8
9
10
11
#include <windows.h>
int WINAPI WinMain(
HINSTANCE hInstance, // 当前实例句柄
HINSTANCE hPrevInstance, // 以前的实例句柄
LPSTR lpCmdLine, // 命令行参数
int nCmdShow // 显示窗口的方式
)
{
MessageBox(0,0,0,0);
return 0;
}

image-20241025213455639

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

image-20241025213848300

记住MessageBox的地址0x75E9AC60image-20241025213938523

用PE Tools打开目标exe文件,查看节表的信息

image-20241025214613208

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

image-20241025215650987

可以看到还是有相当长的空闲区可以写,从0X2E880开始添加Shellcode

1
6A 00 6A 00 6A 00 6A 00 E8 xx xx xx xx E9 xx xx xx xx

E8和E9后为地址,需要计算

image-20241025220625339

查看Image Base

image-20241025220805487

则E8指令的下一条指令的地址为0x42E88D(0x400000+0x2E880)

则x=0x75E9AC60-0x42E88D=0x75A6C3D3

查看Entry Point

image-20241025221221725

Entry Point的地址为0x429008,E9指令的下一条指令的地址为0x42E892

则y=0x429008-0x42E892=0xFFFFA776

将x和y填入,注意小端序

image-20241025221533747

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

image-20241025221657312

修改为0x2E880

image-20241025221733334

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

image-20241026100112688

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

image-20241026100156746

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