试图拆卸

trying to disassemble

作业是解释一些汇编代码以找到一个将 运行 而无需调用 "explode bomb" 的短语。我正在使用 gdb 反汇编当前阶段。我被困住了,非常感谢任何关于我是否朝着正确方向前进的建议。

0x0000000000400fb5 <+0>:    sub    [=10=]x18,%rsp           
0x0000000000400fb9 <+4>:    lea    0x8(%rsp),%r8
0x0000000000400fbe <+9>:    lea    0xf(%rsp),%rcx
0x0000000000400fc3 <+14>:   lea    0x4(%rsp),%rdx

我相信正在发生的事情是我们正在查看 %rsp 中的短语(基指针指向的内容)。我认为它是保存在内存中的四个东西,在 (%rsp)、0x4(%rsp)、0x8(%rsp) 和 0xf(%rsp),我认为这使它成为三个整数和其他东西,但我不是当然可以。

0x0000000000400fc8 <+19>:   mov    [=11=]x4028f6,%esi           

地址$0x4028f6 的值为“%d %c %d”。我知道它正在被转移到注册 %esi,但我不确定它是如何被使用的。

0x0000000000400fcd <+24>:   mov    [=12=]x0,%eax            
0x0000000000400fd2 <+29>:   callq  0x400c80 <__isoc99_sscanf@plt>

不确定这里发生了什么。我查看了 0x400c80 并发现了以下内容:

0x0000000000400c80 <+0>:    jmpq   *0x20340a(%rip)          
0x0000000000400c86 <+6>:    pushq  [=13=]x12
0x0000000000400c8b <+11>:   jmpq   0x400b50

我没有看到 %rip 被用作寄存器,所以我不太确定该做什么或去哪里找。我认为它将 0x12 放入 %eax,但我不确定它跳到哪里,因为 0x400b50 不是有效地址。无论如何,回到原来的功能:

0x0000000000400fd7 <+34>:   cmp    [=14=]x2,%eax            
0x0000000000400fda <+37>:   jg     0x400fe1 <phase_3+44>
0x0000000000400fdc <+39>:   callq  0x401719 <explode_bomb>

我想我们只是将 0x18 推到 %eax 上,所以它肯定会大于 0x2,程序将跳过 "explode bomb"。我只想知道在那之前我在哪里搞砸了。

很遗憾,您似乎缺少关键知识。你应该重新审视你可能拥有的任何 material 否则你将不会对剩下的作业有太多的运气,这实际上将涉及一些不那么琐碎的代码。

也就是说,到目前为止您引用的块仅执行以下操作:

int x, y;
char c;
if (sscanf(foo, "%d %c %d", &x, &c, &y) <= 2) explode_bomb();

第一个块分配 3 个局部变量,并将每个变量的地址加载到相应 sscanf 参数的适当寄存器中。请注意,x86-64 调用约定使用寄存器 rdirsircxrdxr8r9 作为前六个参数(假设它们是合适的)并且值在 rax.

中返回

你不需要看0x400c80,你只需要找到最终跳转到sscanf本身的PLT条目。我们已经从符号名称中知道它是 sscanf

如果你自己想出来会更有趣,所以我只是给出提示

  • 从堆栈指针中减去是在进入函数时为局部范围变量分配 space 的一种相当标准的方法

  • google 用于 intel 操作码,例如 "lea" 类似于 "load effective address"。它不加载数据

  • google sscanf,一个标准的C库函数,有C99 C语言标准。它从字符串中读取数据,并获取一个数据字符串、一个带有 % 转义转换说明符的格式字符串,以及指向放置扫描和转换数据的变量的指针。无需追踪 sscanf 的内部结构,但请查看其 return 值

  • C 函数最常 return 它们的结果在 %eax 中。调用前清除%eax,调用后测试,根据结果有条件地避免(或不)炸弹

这应该足以让您弄明白。玩得开心!