【问题标题】:Rookie Assembly Bomb Defusal cmp Operator新秀组装炸弹拆除 cmp 操作员
【发布时间】:2016-02-24 22:13:21
【问题描述】:

我是组装新手,真的不知道发生了什么。

我正在尝试完成一项家庭作业,其中我们必须通过找出程序五个阶段的正确输入来拆除炸弹。

我尝试在网上寻找我的问题的答案,但我真的不知道要搜索什么才能找到我正在寻找的答案。

我相信我理解下面代码中从<+0><+35> 的所有内容。在<+40> 调用 cmp 运算符来比较$0x2%eax 寄存器中存储的内容。在进行比较时,我相信 %eax 仍在存储对 scanf 的函数调用(如果我错了,请纠正我)。

通过使用 gdb,我知道 scanf 函数的调用如下: scanf("%d %d", &x, &y);

那么在这种情况下,$0x2 到底指的是什么(只是值 2?)以及比较这两个项目时发生了什么?

我相信这是 GAS 语法。

   0x0804870a <+0>:     sub    $0x2c,%esp
   0x0804870d <+3>:     lea    0x1c(%esp),%eax
   0x08048711 <+7>:     mov    %eax,0xc(%esp)
   0x08048715 <+11>:    lea    0x18(%esp),%eax
   0x08048719 <+15>:    mov    %eax,0x8(%esp)
   0x0804871d <+19>:    movl   $0x8048baa,0x4(%esp)
   0x08048725 <+27>:    mov    0x804b040,%eax
   0x0804872a <+32>:    mov    %eax,(%esp)
   0x0804872d <+35>:    call   0x8048480 <__isoc99_fscanf@plt>
   0x08048732 <+40>:    cmp    $0x2,%eax
   0x08048735 <+43>:    je     0x8048743 <phase_1_of_5+57>
   0x08048737 <+45>:    movl   $0x1,(%esp)
   0x0804873e <+52>:    call   0x80486ef <explode>
   0x08048743 <+57>:    mov    0x18(%esp),%eax
   0x08048747 <+61>:    mov    %eax,%edx
   0x08048749 <+63>:    shl    $0x5,%edx
   0x0804874c <+66>:    add    %edx,%eax
   0x0804874e <+68>:    cmp    0x1c(%esp),%eax
   0x08048752 <+72>:    je     0x8048760 <phase_1_of_5+86>
   0x08048754 <+74>:    movl   $0x1,(%esp)
   0x0804875b <+81>:    call   0x80486ef <explode>
   0x08048760 <+86>:    add    $0x2c,%esp
   0x08048763 <+89>:    ret

【问题讨论】:

  • cmp%eax 的值中减去 0x2(十六进制 2 == 十进制 2),相应地设置标志,并保持 %eax 不变。
  • 是的,$2 就是 2。它在比较fscanf 的返回值,这意味着它正在检查您是否输入了 2 个数字。不要误会我的意思,但是如果您甚至无法解决此问题,您以后会遇到更多麻烦,并且询问 SO 可能不是正确的方法。
  • 谢谢大家。感谢您的关注,小丑。我也很确定我会遇到更多麻烦。我只是很难在互联网上找到像样的组装教程。我在一次重要的讲座中失去了注意力(诅咒你加),现在我有点迷失了。我刚刚和我的教授谈过了,但我忘了问那条线,不想再打扰他了。
  • 我认为这是学习 ASM 的一个非常有效且很好的问题。不知道为什么投反对票。它涵盖了使用堆栈、调用 api 和操作码。

标签: c assembly cmp


【解决方案1】:

与 JE 和相关说明的常见混淆。我建议使用调试器来可视化代码在做什么。

cmp 在内部进行减法,但实际上它检查 eax == 2。如果 eax == 2 JE (JUMP IF EQUAL) 它会跳转,因此 EIP 寄存器(执行的下一条指令)变为 0x08048743(“phase_1_of_5+57”的内存地址”)。如果 eax != 2,它会跳过 JE 忽略它。

在您练习自己并再次陷入困境之前,请勿阅读此内容:

所以我们看看http://www.tutorialspoint.com/c_standard_library/c_function_fscanf.htm。 fscanf 做什么。我们看到返回值 2 意味着它需要 2 个输入项。现在我们假设我们输入了两个术语,现在我们遵循 JE。

我们看到了(这就是为什么你需要一个调试器来可视化它)

mov    0x18(%esp),%eax
...
cmp    0x1c(%esp),%eax

0x18 == 6th value on the stack
0x1c == 7th value on the stack
safe to assume these are the two input terms.

0x08048743 <+57>:    mov    0x18(%esp),%eax
0x08048747 <+61>:    mov    %eax,%edx
0x08048749 <+63>:    shl    $0x5,%edx
0x0804874c <+66>:    add    %edx,%eax

这里我们可以假设拆除炸弹的方法是在第一项的 5 处输入左移,添加到第一项。到第二任期。

所以 0 0 应该化解它。

【讨论】:

  • 你不需要“假设”,因为我们可以看到他们的地址被传递给fscanf
  • 0 0 确实化解了炸弹,但我仍然有点困惑。我自己完成了组装,并得出(我认为)与您相同的结论,但我找不到任何其他有效的输入。我发现如果输入被命名为 x 和 y,那么如果 x == y + (y*2^5) 那么炸弹应该被拆除,但它似乎不起作用。知道为什么吗?
  • 移动 5 位并添加原始数字只是乘以 33。因此,任何第二个数字是第一个数字的 33 倍的任何对都应该有效。刚刚检查,确实如此。
  • 啊,有道理。谢谢。
  • 我说假设是因为我们不知道 fscanf 在这种情况下会 100% 确定地做什么(因为我们没有字节码),它可能会被重定向到做一些超出预期的事情,比如通过钩子或函数体字节操作。
猜你喜欢
  • 2017-04-18
  • 1970-01-01
  • 2015-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-28
  • 2020-04-12
  • 1970-01-01
相关资源
最近更新 更多