解码和理解汇编代码

所以有点背景。 我是c和汇编代码的初学者,我们有一个“炸弹”赋值(用c编写)调用需要某些密码的方法,但代码不可见,我需要通过查看汇编代码来确定正确的密码。

代码表明此方法的密码是6个数字,它作为“输入”传递给方法阶段2(我试图避免触发)。

我感到困惑的部分是从+64跳到+42。 它似乎是一个循环,但我不确定每次传递如何影响堆栈。 如果最后两个数字是相同的,它看起来像循环退出,并且它与添加和减去4有关,但我不确定如何遍历地址。 如果任何人都可以翻译正在发生的事情,或者如果我需要查看任何特定的寄存器/位置,那将会有很大帮助。 还有4个阶段,每个阶段都应该更加复杂,所以我希望能够很好地理解如何阅读这些阶段。

此外,如果任何人有一个良好的资源(如可打印表)与汇编代码关键字也会有所帮助,如果32位和64位寄存器之间有任何差异,我需要担心除寄存器名称之外。 。

82 phase_2(input); (gdb) disas phase_2 Dump of assembler code for function phase_2: 0x000000000040106b : push %rbp 0x000000000040106c : push %rbx 0x000000000040106d : sub $0x28,%rsp 0x0000000000401071 : mov %rsp,%rsi 0x0000000000401074 : callq 0x401457  0x0000000000401079 : cmpl $0x0,(%rsp) 0x000000000040107d : jne 0x401086  0x000000000040107f : cmpl $0x1,0x4(%rsp) 0x0000000000401084 : je 0x40108b  0x0000000000401086 : callq 0x401421  0x000000000040108b : lea 0x8(%rsp),%rbx 0x0000000000401090 : lea 0x18(%rsp),%rbp 0x0000000000401095 : mov -0x8(%rbx),%eax 0x0000000000401098 : add -0x4(%rbx),%eax 0x000000000040109b : cmp %eax,(%rbx) 0x000000000040109d : je 0x4010a4  0x000000000040109f : callq 0x401421  0x00000000004010a4 : add $0x4,%rbx 0x00000000004010a8 : cmp %rbp,%rbx 0x00000000004010ab : jne 0x401095  0x00000000004010ad : add $0x28,%rsp 0x00000000004010b1 : pop %rbx 0x00000000004010b2 : pop %rbp 0x00000000004010b3 : retq 

这是相当于阶段2的C:

 int t[6]; read_six_numbers (t); if ((t[0] != 0) || (t[1] != 1)) { explode_bomb(); } for (int i = 2; i < 6; i++) { if (t[i] != t[i - 2] + t[i - 1]) { explode_bomb(); } } 

所以密码是0,1,1,2,3,5。

我是怎么做到的? 通过逐步用C替换组件

您会注意到堆栈指针(rsp)永远不会改变。 您可以将堆栈视为32位数的数组t。 也就是说,每次移动4个字节,就会移动到下一个元素。 即0(%rsp),4(%rsp),...等于t [0],t [1],...

我会告诉你一个可能会逐渐转变你遇到的麻烦:

  lea 0x8(%rsp),%rbx lea 0x18(%rsp),%rbp : mov -0x8(%rbx),%eax add -0x4(%rbx),%eax cmp %eax,(%rbx) je  callq explode_bomb : add $0x4,%rbx cmp %rbp,%rbx jne phase_2+42 ------------------------------------------------------ rbx = rsp + 8; rbp = rsp + 24; : eax = [rbx - 8]; eax += [rbx - 4]; if (eax == [rbx]) goto ; explode_bomb(); : rbx += 4; if (rbx != rbp) goto phase_2+42; ------------------------------------------------------ rbx = rsp + 8; rbp = rsp + 24; do { eax = [rbx - 8] + [rbx - 4]; if (eax != [rbx]) { explode_bomb(); } rbx += 4; } while (rbx != rbp); ------------------------------------------------------ rbx = 8; do { eax = [rsp + rbx - 8] + [rsp + rbx - 4]; if (eax != [rsp + rbx]) { explode_bomb(); } rbx += 4; } while (rbx < 24); ------------------------------------------------------ i = 2; do { eax = t[i - 2] + t[i - 1]; if (eax != t[i]) { explode_bomb(); } i += 1; } while (i < 6); ------------------------------------------------------ for (int i = 2; i < 6; i++) { if (t[i] != t[i - 2] + t[i - 1]) { explode_bomb(); } } 

如果您花时间了解这些转换,您将能够转换和理解任何组件。