使用gdb实时编辑代码

时间:2012-02-24 06:22:45

标签: assembly gdb

我对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个问题:我正在尝试做什么?如果是这样,我做错了什么?如果是这样,我做错了什么以及如何解决?

2 个答案:

答案 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只写入某些位(指令甚至没有位对齐)。听起来很可能但很难。

也许您正试图跳转到另一个地址。你可以通过跳转覆盖来做到这一点(请记住,这将是该程序持续时间的永久性更改)。但是同样的规则适用于了解跳跃的格式和行为。

相关问题