【问题标题】:Live editing code with gdb使用 gdb 实时编辑代码
【发布时间】:2012-02-24 06:22:44
【问题描述】:

我在 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 个问题:我正在尝试做的事情可能吗?如果是这样,我做错了吗?如果是这样,我做错了什么,我该如何解决?

【问题讨论】:

标签: assembly gdb


【解决方案1】:

我正在尝试做的事情可能吗?

是的,您可以更改二进制文件的 .text。

请注意,此更改只会影响当前执行;在run 之后,您的更改将“蒸发”(如果您想永久修补二进制文件,这也是可能的,但过程不同)。

如果是这样,我是不是做错了什么?

很可能。你没有告诉我们你想把指令改成什么。

如果是这样,我做错了什么,我该如何解决?

使用(gdb) disas/r 将向您显示实际的原始指令字节,并且可能更容易看出您做错了什么。当我使用它时,我看到了这个:

   0x080483ed <+9>: c7 44 24 1c d0 84 04 08 movl   $0x80484d0,0x1c(%esp)

也就是说,上面的指令 [1] 的地址(您显然想覆盖)不是从&amp;instruction+1 开始,而是从&amp;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 会告诉你所有你需要知道的。

【讨论】:

  • 简明扼要,喜欢。仅一条评论,“开始于&amp;instruction+4”对于此特定 mov 指令是正确的;其他采用 32 位地址/偏移量的 x86 指令可能在不同的偏移量处包含所述值。您提到使用disas/r 非常相关;-)
  • 这很好用。抱歉,我的问题不是很具体。 :)
【解决方案2】:

首先,我从未像您那样使用 gdb 更改程序文本。

您正在更改地址 0x080487e1 处的值,该地址位于程序计数器之前。这些值是机器字节码 - 例如movl $0x8048640,0x20 的编码。

更困难的是,它们的长度取决于指令,所以如果你像你一样破坏一条指令,它会改变下一条指令的起始地址,这意味着它将被解释为另一条指令说明。这是因为您在指令之间书写。

我不确定你从哪里得到 0x080487e1 或者你想用它做什么。如果要更改 movl 用作第一个参数的地址,则需要知道 movl 指令的命令字节码是什么样的,然后可能只替换与地址值对应的部分。但是随后您会遇到如何让 gdb 仅写入某些位的问题(指令甚至没有位对齐)。听起来可能但很难。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 2019-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    • 2020-12-10
    相关资源
    最近更新 更多