【问题标题】:Understanding x86 syntax regarding a C 'bomb'了解有关 C 'bomb' 的 x86 语法
【发布时间】:2015-05-03 05:24:45
【问题描述】:

我收到了一个最初用 C 语言编写的可执行文件,用于玩猜谜游戏。我作为玩家应该猜 5 个数字,如果我猜对了,炸弹就不会爆炸。然而,一旦我错过了一个,我就输了,炸弹爆炸了。到目前为止,我解决这个问题的方法是反汇编可执行文件并尝试从那里读取解决方案。我知道在某些时候会调用 strcmp 函数,这意味着我的猜测与键值将在此之前存储到寄存器中。我迷失的是在哪里找到它,以及如何访问存储该数字的正确字符串。

这是我得到的汇编代码:

0804856a <main>:
804856a:    55                      push   %ebp
804856b:    89 e5                   mov    %esp,%ebp
804856d:    83 e4 f0                and    $0xfffffff0,%esp
8048570:    57                      push   %edi
8048571:    56                      push   %esi
8048572:    53                      push   %ebx 
8048573:    81 ec 14 02 00 00       sub    $0x214,%esp //prologue code ends
8048579:    8b 35 fc 98 04 08       mov    0x80498fc,%esi
804857f:    83 7d 08 02             cmpl   $0x2,0x8(%ebp)
8048583:    75 18                   jne    804859d <main+0x33>
8048585:    c7 44 24 04 fb 86 04    movl   $0x80486fb,0x4(%esp)
804858c:    08 
804858d:    8b 45 0c                mov    0xc(%ebp),%eax
8048590:    8b 40 04                mov    0x4(%eax),%eax
8048593:    89 04 24                mov    %eax,(%esp)
8048596:    e8 65 fe ff ff          call   8048400 <fopen@plt>
804859b:    89 c6                   mov    %eax,%esi
804859d:    bb 01 00 00 00          mov    $0x1,%ebx
80485a2:    bf e4 98 04 08          mov    $0x80498e4,%edi
80485a7:    3b 35 fc 98 04 08       cmp    0x80498fc,%esi
80485ad:    75 10                   jne    80485bf <main+0x55>
80485af:    89 5c 24 04             mov    %ebx,0x4(%esp)
80485b3:    c7 04 24 fd 86 04 08    movl   $0x80486fd,(%esp)
80485ba:    e8 51 fe ff ff          call   8048410 <printf@plt>
80485bf:    89 74 24 08             mov    %esi,0x8(%esp)
80485c3:    c7 44 24 04 00 02 00    movl   $0x200,0x4(%esp)
80485ca:    00 
80485cb:    8d 44 24 10             lea    0x10(%esp),%eax
80485cf:    89 04 24                mov    %eax,(%esp)
80485d2:    e8 09 fe ff ff          call   80483e0 <fgets@plt>
80485d7:    85 c0                   test   %eax,%eax
80485d9:    74 22                   je     80485fd <main+0x93>
80485db:    8b 14 9f                mov    (%edi,%ebx,4),%edx
80485de:    89 54 24 04             mov    %edx,0x4(%esp)
80485e2:    89 04 24                mov    %eax,(%esp)
80485e5:    e8 56 fe ff ff          call   8048440 <strcmp@plt> //call to strcmp, so the two parameters (my guess vs. key) must be stored before it. 
80485ea:    85 c0                   test   %eax,%eax
80485ec:    74 05                break<main+0x89>
80485ee:    e8 4d ff ff ff          call   8048540 <bomb>
80485f3:    83 c3 01                add    $0x1,%ebx
80485f6:    83 fb 05                cmp    $0x5,%ebx
80485f9:    7e ac                   jle    80485a7 <main+0x3d>
80485fb:    eb 05                   jmp    8048602 <main+0x98>
80485fd:    83 fb 05                cmp    $0x5,%ebx
8048600:    7e a5                   jle    80485a7 <main+0x3d>
8048602:    e8 19 ff ff ff          call   8048520 <success>
8048607:    b8 00 00 00 00          mov    $0x0,%eax
804860c:    81 c4 14 02 00 00       add    $0x214,%esp //epilogue code begins
8048612:    5b                      pop    %ebx
8048613:    5e                      pop    %esi
8048614:    5f                      pop    %edi
8048615:    89 ec                   mov    %ebp,%esp
8048617:    5d                      pop    %ebp
8048618:    c3                      ret    

到目前为止,在这个项目中,我一直在使用 GNU 调试器来尝试破解程序。但是,我似乎无法理解它。这是我第一次接触 x86 asm。我的理论是必须将字符串保存到 80485db/de/e2 行的 %edi/%edx/%eax 中,但我不明白这些字符串将如何存储在那里,而不是如何获取它们。我非常感谢更有经验的编码人员提供的任何帮助,因为这让我困惑了好几天。

【问题讨论】:

  • 您没有明确提出问题 - 您是在尝试找出正确的数字序列,还是修补用户输入检查代码以使其始终通过?
  • 可能没有存储正确数字的字符串。
  • 在炸弹(监控你的击键)爆炸之前尝试逆向工程代码是一个更好的游戏;-)
  • 在 Apple ][ Dracula's Castle 游戏中,如果您使用反汇编器或制表器查看代码,您会看到大量包含提示的字符串,这些提示都是红鲱鱼 -真实的东西不是那么容易看到的。
  • 如果它确实是对硬编码字符串进行简单比较,您可以尝试在您的可执行文件上运行程序strings。即strings &lt;exename&gt;

标签: c assembly x86 parameter-passing reverse-engineering


【解决方案1】:

您已正确识别出80485db 周围的临界区。让我们从strcmp 调用向后工作。比较需要两个操作数,它们从寄存器%eax%edx 中的前两行放入堆栈。我们可以看到%eaxfgets的返回值,也就是输入的文本。 %edxmov (%edi,%ebx,4),%edx 加载,不幸的是它依赖于另外两个寄存器。 %edi 比较简单,它由mov $0x80498e4,%edi 设置为一个常量地址。 %ebx804859d 处初始化为1,然后在80485f3 处递增,并在稍后与5 进行比较。因此,我们可以看到它是循环计数器,显示我们正在处理的输入。将这一切放在一起意味着%edx 是从包含预期字符串的数组中加载的。第一个字符串将位于0x80498e4+4,因为 ebx 从 1 开始。因此,gdb 中的x/5s *0x80498e8 应该向您显示拆除炸弹所需的输入。

【讨论】:

  • 这正是我需要的帮助,非常感谢。让我感到困惑的是在将 %edi 放入 %edx 之前对其进行的操作。一旦你解释了这意味着什么,我就能够弄清楚它,并且我考虑了如何通过其中的代码追溯寄存器的内容。为下一次作业做好了充分的准备,非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-07
  • 2021-11-22
  • 2015-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多