我对gdb没有丰富的经验,所以我不确定我的问题是否可行,但是可以用gdb编辑代码吗?
运行时(在遇到断点之后),disas看起来像这样:
0x080487d8 <+9>: movl $0x80485e4,0x1c(%esp)
0x080487e0 <+17>: movl $0x8048640,0x20(%esp)
0x080487e8 <+25>: movl $0x804869c,0x24(%esp)
0x080487f0 <+33>: movl $0x8048719,0x28(%esp)
为了尝试更改其中一条说明中的地址,我这样做了:
set (*0x080487e1)=0x5b870408
但不是像我预期的那样简单地改变地址,新的disas看起来像这样:
0x080487d8 <+9>: movl $0x80485e4,0x1c(%esp)
0x080487e0 <+17>: (bad)
0x080487e1 <+18>: or %al,(%edi,%eax,4)
0x080487e4 <+21>: pop %ebx
0x080487e5 <+22>: xchg %al,(%eax,%ecx,1)
0x080487e8 <+25>: movl $0x804869c,0x24(%esp)
0x080487f0 <+33>: movl $0x8048719,0x28(%esp)
所以我有3个问题:我正在尝试做什么?如果是这样,我做错了什么?如果是这样,我做错了什么以及如何解决?
答案 0 :(得分:7)
我正在尝试做什么?
是的,您可以更改二进制文件的.text。
请注意,此更改只会影响当前执行;在run
之后,您的更改将“消失”(如果您想永久修补二进制文件,这也是可能的,但程序不同)。
如果是这样,我做错了吗?
可能的。您没有告诉我们您要将指令更改为什么。
如果是这样,我做错了什么以及如何解决?
使用(gdb) disas/r
将显示实际的原始指令字节,并且可能更容易看到您做错了什么。当我使用它时,我看到了:
0x080483ed <+9>: c7 44 24 1c d0 84 04 08 movl $0x80484d0,0x1c(%esp)
也就是说,上面的指令 [1]的地址(你显然想要覆盖)并不是从&instruction+1
开始,而是从&instruction+4
开始。此外,当您要求GDB写一个单词时,您不应该反转字节(我猜您希望新地址为0x0804785b
而不是0x5b870408
):
(gdb) set *(0x080483ed+4)=0x01020304
(gdb) disas
Dump of assembler code for function main:
0x080483e4 <+0>: push %ebp
0x080483e5 <+1>: mov %esp,%ebp
0x080483e7 <+3>: and $0xfffffff0,%esp
0x080483ea <+6>: sub $0x20,%esp
=> 0x080483ed <+9>: movl $0x1020304,0x1c(%esp)
0x080483f5 <+17>: mov 0x1c(%esp),%eax
0x080483f9 <+21>: mov %eax,(%esp)
0x080483fc <+24>: call 0x8048318 <puts@plt>
0x08048401 <+29>: mov $0x0,%eax
0x08048406 <+34>: leave
0x08048407 <+35>: ret
[1] 非常可能是你的指示:
0x080487e0 <+17>: movl $0x8048640,0x20(%esp)
与我的指令具有相同的编码:
0x080483ed <+9>: movl $0x80484d0,0x1c(%esp)
因为它们是“相同的”,并且具有相同的8字节长度,但正如FrankH所指出的,可能存在相同指令的不同编码。在任何情况下,disas/r
都会向您显示您需要知道的所有信息。
答案 1 :(得分:2)
首先,我从未使用gdb来改变你似乎正在做的程序文本。
您正在更改地址0x080487e1的值,该值位于程序计数器之前。这些值是机器字节码 - 例如movl $ 0x8048640,0x20的编码。
更难的是它们的长度可变,具体取决于指令,所以如果你破坏了一条指令就像你一样,它会改变下一条指令的起始地址,这意味着它将被解释为另一条指令指令即可。这是因为你在两份指令之间写作。
我不知道你在哪里得到0x080487e1或者你正在尝试用它做什么。如果你想查看movl用作第一个参数的地址,你需要知道movl指令的命令字节码是什么样的,然后可能只替换对应于地址值的部分。但是你会被困在如何让gdb只写入某些位(指令甚至没有位对齐)。听起来很可能但很难。
也许您正试图跳转到另一个地址。你可以通过跳转覆盖来做到这一点(请记住,这将是该程序持续时间的永久性更改)。但是同样的规则适用于了解跳跃的格式和行为。