-3

これはファイルの単なるクリップです。これは、爆弾のレベルの 1 つです。各レベルは、ユーザーによる入力によって解除されます。逆アセンブルされたコードを解釈して、その入力がどうあるべきかを判断することになっています。この特定のレベルでは、ユーザーは 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 である必要があります。

  • 4 回反復し、各数値が現在のインデックスの数値よりも小さいことを確認する 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 でなければなりません。
  • 2 番目は 1 番目よりも小さくする必要があります。
  • 3 番目は 2 番目よりも小さくする必要があります。
  • 4 番目は 3 番目よりも小さくする必要があります。
  • (1 * second + 2 * third + 3 * fourth)は、5 番目の数値の負数に等しくなければなりません。
于 2012-05-18T14:37:55.317 に答える