如何化解这个二进制炸弹阶段4

时间:2019-03-06 17:02:02

标签: c linux assembly x86 gdb

我在用汇编语言编写这段代码时遇到了麻烦。 本质上,我必须输入2个与代码要比较的2个数字匹配的数字。 在phase_4的0x08048c47行上,它将第一个输入与2进行比较,因此我知道第一个输入必须为2。然后将第一个输入的4个空格移至下一个输入,然后从中减去2个空格。现在,将(输入2)与2进行比较。如果输入小于或等于2,它将继续执行该指令。我已经用通过比较的数字2,3,4对此进行了测试。其他大于4且小于2的数字将无法通过比较,并且会导致炸弹爆炸。
我被困在这部分上是因为从func4返回的值与phase_4中以0x08048c6e表示的值(8(%esp))不同。在我调试它的计算机上,它显示为8,而对输入2、3、4的答案分别为40、60、80。

disas func4
0x08048bda <+0>:    push   %edi
0x08048bdb <+1>:    push   %esi
0x08048bdc <+2>:    push   %ebx
0x08048bdd <+3>:    mov    0x10(%esp),%ebx
0x08048be1 <+7>:    mov    0x14(%esp),%edi
0x08048be5 <+11>:   test   %ebx,%ebx
0x08048be7 <+13>:   jle    0x8048c14 <func4+58>
0x08048be9 <+15>:   mov    %edi,%eax
0x08048beb <+17>:   cmp    $0x1,%ebx
0x08048bee <+20>:   je     0x8048c19 <func4+63>
0x08048bf0 <+22>:   sub    $0x8,%esp
0x08048bf3 <+25>:   push   %edi
0x08048bf4 <+26>:   lea    -0x1(%ebx),%eax
0x08048bf7 <+29>:   push   %eax
0x08048bf8 <+30>:   call   0x8048bda <func4>
0x08048bfd <+35>:   add    $0x8,%esp
0x08048c00 <+38>:   lea    (%edi,%eax,1),%esi
0x08048c03 <+41>:   push   %edi
0x08048c04 <+42>:   sub    $0x2,%ebx
0x08048c07 <+45>:   push   %ebx
0x08048c08 <+46>:   call   0x8048bda <func4>
0x08048c0d <+51>:   add    $0x10,%esp
0x08048c10 <+54>:   add    %esi,%eax
0x08048c12 <+56>:   jmp    0x8048c19 <func4+63>
0x08048c14 <+58>:   mov    $0x0,%eax
0x08048c19 <+63>:   pop    %ebx
0x08048c1a <+64>:   pop    %esi
0x08048c1b <+65>:   pop    %edi
0x08048c1c <+66>:   ret    



disas phase_4
0x08048c1d <+0>:    sub    $0x1c,%esp
0x08048c20 <+3>:    mov    %gs:0x14,%eax
0x08048c26 <+9>:    mov    %eax,0xc(%esp)
0x08048c2a <+13>:   xor    %eax,%eax
0x08048c2c <+15>:   lea    0x4(%esp),%eax
0x08048c30 <+19>:   push   %eax
0x08048c31 <+20>:   lea    0xc(%esp),%eax
0x08048c35 <+24>:   push   %eax
0x08048c36 <+25>:   push   $0x804a25f
0x08048c3b <+30>:   pushl  0x2c(%esp)
0x08048c3f <+34>:   call   0x8048810 <__isoc99_sscanf@plt>
0x08048c44 <+39>:   add    $0x10,%esp
0x08048c47 <+42>:   cmp    $0x2,%eax
0x08048c4a <+45>:   jne    0x8048c58 <phase_4+59>
0x08048c4c <+47>:   mov    0x4(%esp),%eax
0x08048c50 <+51>:   sub    $0x2,%eax
0x08048c53 <+54>:   cmp    $0x2,%eax
0x08048c56 <+57>:   jbe    0x8048c5d <phase_4+64>
0x08048c58 <+59>:   call   0x8049123 <explode_bomb>
0x08048c5d <+64>:   sub    $0x8,%esp
0x08048c60 <+67>:   pushl  0xc(%esp)
0x08048c64 <+71>:   push   $0x6
0x08048c66 <+73>:   call   0x8048bda <func4>
0x08048c6b <+78>:   add    $0x10,%esp
0x08048c6e <+81>:   cmp    0x8(%esp),%eax
0x08048c72 <+85>:   je     0x8048c79 <phase_4+92>
0x08048c74 <+87>:   call   0x8049123 <explode_bomb>
0x08048c79 <+92>:   mov    0xc(%esp),%eax
0x08048c7d <+96>:   xor    %gs:0x14,%eax
0x08048c84 <+103>:  je     0x8048c8b <phase_4+110>
0x08048c86 <+105>:  call   0x8048790 <__stack_chk_fail@plt>
0x08048c8b <+110>:  add    $0x1c,%esp
0x08048c8e <+113>:  ret    

1 个答案:

答案 0 :(得分:1)

8(%esp)是x86框架下的第一个数字。 输入40 260 380 4应该可以。

等效于以下逻辑

#include <stdio.h>
#include <stdlib.h>

void explode_bomb()
{
    printf("explode bomb.\n");
    exit(1);
}

unsigned func4(int val, unsigned num)
{
    int ret;

    if (val <= 0)
        return 0;

    if (num == 1)
        return 1;

    ret = func4(val - 1, num);
    ret += num;
    val -= 2;
    ret += func4(val, num);
    return ret;
}

void phase_4(const char *input)
{
    unsigned num1, num2;

    if (sscanf(input, "%u %u", &num1, &num2) != 2)
        explode_bomb();

    if (num2 - 2 > 2)
        explode_bomb();

    if (func4(6, num2) != num1)
        explode_bomb();
}

int main()
{
    phase_4("40 2");
    phase_4("60 3");
    phase_4("80 4");
    printf("success.\n");
    return 0;
}