我是gdb和Assembly的新手。我正在尝试将助记符指令从jg
更改为jle
,但是每当我更改助记符时,它也会更改目标地址。例如,
比方说,我正在尝试修改此内容:
4005a5 0f 8f 1e 01 00 00 jg 400c74 <Function_1>
所以,我做到了
$set *0x4005a5 = 0x7e
然后,发生的事情是将400c74更改为某个随机地址,例如400ae4。
我认为这可能是短跳和近跳的问题,
所以我甚至做了= 0x0f8e
= 0x74400c7e
= 0x0f8e400c74
等等。
但是,他们都在改变跳转的位置。
请问有人可以解释为什么会这样吗?
答案 0 :(得分:3)
set *(unsigned short*)0x4005a5 = 0x8e0f
我认为2个问题:
set *0x4005a5 = 0x7e
可能默认为dword存储,写入4个字节而不是1个字节。是的,原始指令使用的是Near encoding (jcc rel32
),其中操作码是2个字节的0f 8f
。您可以知道,因为完整指令的长度是6个字节而不是2个字节,并且以0f
开头(因此它不是单字节操作码。)
您将其替换为1字节的短jle rel8
,因此第二个操作码字节成为rel8。
(原始8086仅对条件跳转使用jcc rel8
,只有像jmp
这样的无条件跳转同时具有rel8和rel16编码;在186和386之间添加了jcc rel16/rel32
编码。 )
您尝试设置0x0f8e
时遇到了字节序问题。 x86是小端的,因此jle
作为小端0F 8E
的操作码unsigned short
的值为0x8e0f
。
8E
是mov Sreg, r/m16
的操作码,因此0x0f8e
(8E 0F
)将作为段reg的mov进行解码,而0F
为ModR / M字节。修改后,使用GDB分解指令。
使用GDB的disas /r
来分解原始十六进制和助记符。