我是gdb和汇编的新手。我正在尝试将助记符指令从jg
更改为jle
,但每当我更改助记符时,它也会更改目标地址。例如,
假设我正在尝试修改这个:
4005a5 0f 8f 1e 01 00 00 jg 400c74 <Function_1>
所以我做了
$set *0x4005a5 = 0x7e
然后,会发生什么,它将400c74更改为某个随机地址,如400ae4。我认为这可能是短跳和近跳的问题,所以我甚至做了= 0x0f8e
= 0x74400c7e
= 0x0f8e400c74
等等。
但是,他们都在改变跳跃到位置..
谁能解释为什么会这样呢?拜托?
set *(unsigned short*)0x4005a5 = 0x8e0f
我认为有两个问题:
set *0x4005a5 = 0x7e
可能默认为双字存储,写入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
的尝试有一个endian问题。 x86是little-endian,所以jle
的操作码0F 8E
作为小端unsigned short
具有值0x8e0f
。
8E
是mov Sreg, r/m16
的操作码,因此0x0f8e
(8E 0F
)将解码为段reg的mov,其中0F
为ModR / M字节。修改后使用GDB反汇编指令。
使用GDB的disas /r
来解析原始十六进制和助记符。