-3

这只是文件的一个片段。这是炸弹的级别之一。每个级别都由用户输入来消除。我们应该解释反汇编代码以找出输入应该是什么。在这个特定级别中,用户必须输入 5 个数字。一旦提供了 5 个数字,就会在这个反汇编代码中检查它们。如果它们不起作用,那么炸弹就会爆炸。我已经完成了它并提出了一些数字规则,但有些部分我无法解释。主要是当涉及到循环时。

以下是反汇编代码供参考:

8048eae:       55                      push   %ebp
8048eaf:       89 e5                   mov    %esp,%ebp
8048eb1:       83 ec 28                sub    $0x28,%esp
8048eb4:       c7 45 f8 00 00 00 00    movl   $0x0,0xfffffff8(%ebp)
8048ebb:       8d 45 e4                lea    0xffffffe4(%ebp),%eax
8048ebe:       89 44 24 04             mov    %eax,0x4(%esp)
8048ec2:       8b 45 08                mov    0x8(%ebp),%eax
8048ec5:       89 04 24                mov    %eax,(%esp)
8048ec8:       e8 69 06 00 00          call   8049536 <read_five_numbers>
8048ecd:       8b 45 e4                mov    0xffffffe4(%ebp),%eax
8048ed0:       83 f8 1a                cmp    $0x1a,%eax
8048ed3:       74 05                   je     8048eda <level_3+0x2c>
8048ed5:       e8 a6 10 00 00          call   8049f80 <explode_bomb>
8048eda:       c7 45 fc 00 00 00 00    movl   $0x0,0xfffffffc(%ebp)
8048ee1:       eb 2c                   jmp    8048f0f <level_3+0x61>
8048ee3:       8b 45 fc                mov    0xfffffffc(%ebp),%eax
8048ee6:       8b 54 85 e4             mov    0xffffffe4(%ebp,%eax,4),%edx
8048eea:       8b 45 fc                mov    0xfffffffc(%ebp),%eax
8048eed:       83 c0 01                add    $0x1,%eax
8048ef0:       8b 44 85 e4             mov    0xffffffe4(%ebp,%eax,4),%eax
8048ef4:       39 c2                   cmp    %eax,%edx
8048ef6:       7f 05                   jg     8048efd <level_3+0x4f>
8048ef8:       e8 83 10 00 00          call   8049f80 <explode_bomb>
8048efd:       8b 45 fc                mov    0xfffffffc(%ebp),%eax
8048f00:       8b 44 85 e4             mov    0xffffffe4(%ebp,%eax,4),%eax
8048f04:       0f af 45 fc             imul   0xfffffffc(%ebp),%eax
8048f08:       01 45 f8                add    %eax,0xfffffff8(%ebp)
8048f0b:       83 45 fc 01             addl   $0x1,0xfffffffc(%ebp)
8048f0f:       83 7d fc 03             cmpl   $0x3,0xfffffffc(%ebp)
8048f13:       7e ce                   jle    8048ee3 <level_3+0x35>
8048f15:       8b 45 f4                mov    0xfffffff4(%ebp),%eax
8048f18:       f7 d8                   neg    %eax
8048f1a:       3b 45 f8                cmp    0xfffffff8(%ebp),%eax
8048f1d:       74 05                   je     8048f24 <level_3+0x76>
8048f1f:       e8 5c 10 00 00          call   8049f80 <explode_bomb>
8048f24:       c9                      leave  
8048f25:       c3                      ret   

到目前为止,我有以下规则来查找数字:

  • 由于与 0x1a 比较,第一个数字应该是 26。

  • 有一个 for 循环迭代 4 次并确保每个数字都小于当前索引处的数字这是我不确定的规则

  • 前四个数字的总和应该小于等于某个值。
  • 最后一个数字应该是第一个数字的负数
4

1 回答 1

1

根据函数的开头,您可以这样查看堆栈布局:

int v[5], c0, c1;

ebp+e4 | v1
ebp+e8 | v2
ebp+ec | v3
ebp+f0 | v4
ebp+f4 | v5
ebp+f8 | c0
ebp+fc | c1

我已将代码转录为伪代码,它应该可以回答您的问题。当然do/while,一旦您了解发生了什么,goto 可以转换为循环以提高可读性。

8048eae push  %ebp                           
8048eaf mov   %esp,%ebp                      
8048eb1 sub   $0x28,%esp                     

8048eb4 movl  $0x0,0xfffffff8(%ebp)          c0 = 0;
8048ebb lea   0xffffffe4(%ebp),%eax          
8048ebe mov   %eax,0x4(%esp)                 
8048ec2 mov   0x8(%ebp),%eax                 
8048ec5 mov   %eax,(%esp)                    
8048ec8 call  8049536 <read_five_numbers>    read_five_numbers(v);
8048ecd mov   0xffffffe4(%ebp),%eax          eax = v[0];
8048ed0 cmp   $0x1a,%eax                     
8048ed3 je    8048eda <level_3+0x2c>         unless(eax == 0x1A)
                                             {
8048ed5 call  8049f80 <explode_bomb>           explode_bomb();
                                             }
8048eda movl  $0x0,0xfffffffc(%ebp)          c1 = 0;
8048ee1 jmp   8048f0f <level_3+0x61>         goto loop_condition;
                                             loop_body:
8048ee3 mov   0xfffffffc(%ebp),%eax          eax = c1;
8048ee6 mov   0xffffffe4(%ebp,%eax,4),%edx   edx = v[eax];
8048eea mov   0xfffffffc(%ebp),%eax          eax = c1;
8048eed add   $0x1,%eax                      ++eax;
8048ef0 mov   0xffffffe4(%ebp,%eax,4),%eax   eax = v[eax];
8048ef4 cmp   %eax,%edx                      
8048ef6 jg    8048efd <level_3+0x4f>         unless(edx > eax)
                                             {
8048ef8 call  8049f80 <explode_bomb>           explode_bomb();
                                             }
8048efd mov   0xfffffffc(%ebp),%eax          eax = c1;
8048f00 mov   0xffffffe4(%ebp,%eax,4),%eax   eax = v[eax];
8048f04 imul  0xfffffffc(%ebp),%eax          eax *= c1;
8048f08 add   %eax,0xfffffff8(%ebp)          c0 += eax;
8048f0b addl  $0x1,0xfffffffc(%ebp)          ++c1;
                                             loop_condition:
8048f0f cmpl  $0x3,0xfffffffc(%ebp)          if(c1 <= 3) {
8048f13 jle   8048ee3 <level_3+0x35>           goto loop_body;
                                             }
8048f15 mov   0xfffffff4(%ebp),%eax          eax = v[4];
8048f18 neg   %eax                           eax = -eax;
8048f1a cmp   0xfffffff8(%ebp),%eax          
8048f1d je    8048f24 <level_3+0x76>         unless(c0 == eax)
                                             {
8048f1f call  8049f80 <explode_bomb>           explode_bomb();
                                             }
8048f24 leave                                
8048f25 ret                                  

因此,如果我没看错,您的数字必须是:

  • 第一个必须等​​于 0x1A。
  • 第二个必须小于第一个。
  • 第三个必须小于第二个。
  • 第四个必须小于第三个。
  • (1 * second + 2 * third + 3 * fourth)必须等于第五个数字的负数。
于 2012-05-18T14:37:55.317 回答