目标是在某个EXE代码节空白区手动添加代码弹框
通过DTDebug或OD找到当前电脑的MessageBoxA函数地址:例如我之类的0x75789350

这里添加逻辑是,先CALL该函数然后JMP到OEP地址
观察到CALL指令的硬编码是E8;JMP指令的硬编码是E9;但是指令后跟随的并不是直接的地址
xxxxxxxxxx真正要跳转的地址 = E8这条指令的下一行地址 + X观察到CALL和JMP操作数都是4字节地址,因此下一行地址应该是+5,所以得到以下公式
xxxxxxxxxxX = 要跳转的地址 - (E8的地址 + 5)另外CALL MessageBox需要额外的4个参数,如下图硬编码是6A 00

现在思路已经明确,最终需要写入的字节如下(未知地址暂写为00)
xxxxxxxxxx6A 00 6A 00 6A 00 6A 00 E8 00 00 00 00 E9 00 00 00 00
我的EXE现在的代码节信息如下

计算SizeOfRawData-VirtualSize得到空白区大小8DE显然可以成功写入
节的PointerToRawData是0x1000,所以在文件中,代码节从0x1A000开始到0x1B000结束。于是我们将上文的16个字节写在这里,选择1A730并不是必须,其他地方也可以,只要在该区域内即可

对于其中的地址,需要计算的是内存中的地址而不是文件的地址,程序默认装入的基地址ImageBase是0x00400000,相加得到插入字节的内存偏移是0x0041A730,在E9处的偏移是0x0041A73D
通过公式真正要跳转的地址 = E8这条指令的下一行地址 + X得到X为7536EC13
于是CALL MessageBox为E8 13 EC 36 75
PE工具找到程序开始执行的入口地址OEP为0x000183D7

通过公式真正要跳转的地址 = E9这条指令的下一行地址 + X得到
X = (0x00400000 + 0x000183D7) - (0X00400000 + 0x0001A742) = 0xFFFFDC95
于是JMP OEP为E9 95 DC FF FF
现在需要修改OEP到0x0001A730(不需要考虑ImageBase的0x00400000)

修改完字节后保存到EXE,双击触发
