【问题标题】:GDB assembler debuggingGDB 汇编器调试
【发布时间】:2012-08-29 19:57:10
【问题描述】:

我必须对一个类进行一些二进制分析,但我被困在其中一个程序上。当我设置一些断点和 disas 时,我看到它看起来像这样:

Dump of assembler code for function main:
    0x080484e2 <+0>:    push   %ebp
    0x080484e3 <+1>:    mov    %esp,%ebp
    0x080484e5 <+3>:    sub    $0x48,%esp
    0x080484e8 <+6>:    and    $0xfffffff0,%esp
    0x080484eb <+9>:    mov    $0x0,%eax
    0x080484f0 <+14>:   sub    %eax,%esp
    0x080484f2 <+16>:   cmpl   $0x1,0x8(%ebp)
    0x080484f6 <+20>:   jg     0x8048504 <main+34>
    0x080484f8 <+22>:   movl   $0x7,(%esp)
 => 0x080484ff <+29>:   call   0x804833c <exit@plt>
    0x08048504 <+34>:   mov    0xc(%ebp),%eax
    0x08048507 <+37>:   add    $0x4,%eax
    0x0804850a <+40>:   mov    (%eax),%eax
    0x0804850c <+42>:   mov    %eax,(%esp)
    0x0804850f <+45>:   call   0x804832c <atoi@plt>
    0x08048514 <+50>:   mov    %eax,-0x10(%ebp)
    0x08048517 <+53>:   cmpl   $0xd,-0x10(%ebp)
    0x0804851b <+57>:   jne    0x804853b <main+89>
    0x0804851d <+59>:   lea    -0x38(%ebp),%eax
    0x08048520 <+62>:   mov    %eax,(%esp)
    0x08048523 <+65>:   call   0x8048414 <makebuf>
    0x08048528 <+70>:   lea    -0x38(%ebp),%eax
    0x0804852b <+73>:   mov    %eax,0x4(%esp)
    0x0804852f <+77>:   movl   $0x804863b,(%esp)
 ** 0x08048536 <+84>:   call   0x804831c <printf@plt>
    0x0804853b <+89>:   movl   $0x1,(%esp)
    0x08048542 <+96>:   call   0x804833c <exit@plt>
End of assembler dump.

(我在调用 printf@plt 的位置旁边的星号中进行了编辑)。 在我看来,它是一个调用 exit() 的程序,然后构建一个字符串,然后将该字符串打印出来,然后执行另一个 exit()。我认为,如果我可以绕过对 exit() 的第一次调用,它将打印出挑战的答案。设置调用执行NOP的位置是否正确?如果是这样,NOP 的操作码是什么?我尝试设置为 0x0 和 0x00000000。任何帮助将不胜感激!谢谢。

【问题讨论】:

  • 如果这与家庭作业有关,您应该将问题标记为Homework。它仍将被评估。
  • 你说,'它看起来像我'。相反,你应该说,'当我单步执行时......'

标签: assembly gdb binaryfiles elf


【解决方案1】:

看线

0x080484f2 <+16>:   cmpl   $0x1,0x8(%ebp)
0x080484f6 <+20>:   jg     0x8048504 <main+34>

并确定如何让程序跳过第一次退出 - 无需注入

【讨论】:

  • 我真的不知道任何组装。我尝试从我所在的断点跳转到下一条指令,但出现了段错误。我是否应该在这两行之前插入一个中断并跳过所有这些指令?
  • 我假设因为这是“为了一个班级”,所以推断代码在做什么是练习的目的。因此,您需要学习适当的程序集才能成功完成作业。
  • 我显然是想在这里学习,而不仅仅是寻求答案...有没有办法只编辑gdb中的指令参数?
  • 家庭作业的解决方案(不幸的是)在另一个答案中给出(参见 Arash Thr)
  • 打印该变量并不能给出答案。我假设是因为它尚未设置或分配正确的值。我尝试将 $ebp 的存储位置设置为不同的值,但程序以相同的结果结束。不重写整个指令行,有没有什么好办法可以修改函数参数的值?
【解决方案2】:

您可能不想直接退出调用退出。这次你也许可以侥幸逃脱,但在两个退出调用中,它们都在调用之前将退出代码放入堆栈。根据程序的其余部分,这些堆栈值可能会或可能不会被使用。

所以你的选择是要么 NOP MOV 和 CALL 要么强制跳转总是按照你想要的方式进行。

或者最好的方法是弄清楚到底是什么参数使它做你想做的事情。

x86 的标准 NOP 操作码也是 0x90。

【讨论】:

  • 好吧,既然你说使用 NOPing out 调用不是操纵正在运行的程序的好方法,那么强制比较总是导致跳转的好方法是什么?有没有办法让它总是返回 true?
  • 你可以用 jmp 替换 jg,你只需要确保你的数学和指令大小对齐。或者你可以直接退出 jmp mov 和调用。这样堆栈就不会被更改。在这种特定情况下,您可能只对调用进行 noping 就可以侥幸逃脱,但不要养成在确保堆栈正常的情况下这样做的习惯。
【解决方案3】:

如果这是关于家庭作业,那么您应该知道允许做什么。

如果允许打补丁,那么最好的方法是将操作码从 jg 更改为 jng,您必须查看 intel 手册以了解必须更改的内容,但通常是一个字节。

如果不允许打补丁,那么您将必须找到将设置正在比较的变量的函数,并弄清楚如何使该函数将其设置为其他值。

【讨论】:

  • 我可以做任何可以得到我需要的事情。我想我会做一些关于补丁的研究。谢谢!
【解决方案4】:

它不一定退出,因为这条线:

cmpl   $0x1,0x8(%ebp)

在这一行中,程序检查该函数的第一个参数的值是否为 1,如果更大,则跳转。
另外,如果你想在这里看到 printf 的格式,你可以在 gdb 中输入printf "%s", 0x804863b
更新:
如果这个过程是主程序,那么0x8($ebp) 包含所谓的 argc,它是程序的输入数。所以你需要做的是当你运行程序时给它输入。喜欢./a.out blah
您也可以通过在 gdb 中输入 x/2wx $esp 来检查此值。

【讨论】:

  • 所以,我需要更改它以与 1 以外的其他数字进行比较?或操纵作为参数传递的值?如何实现?
  • 在启动程序时给它输入。我已经更新了答案。
【解决方案5】:

0x90 是 x86 的 NOP 指令。因此 0x90 是一条 NOP 指令,0x9090 是两条 NOP 指令,0x90909090 是 4 条 NOP 指令。

仔细检查call 0x804833c 指令的长度。我不相信它有 4 个字节长。

【讨论】:

    猜你喜欢
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-21
    • 1970-01-01
    • 2014-03-15
    相关资源
    最近更新 更多