CS APPのEX2爆弾

爆弾を解体CS APP実験2、

ここでgdbデバッガによるLinux環境が行われます

GDBデバッグモードを入力してください

入力端子$ gdb bomb

主な機能を見ます

エントリー(gdb) list main

初期化関数が見つかりinitialize_bomb()、2つのprint、出力プロンプト、および続くinput = read_line()、我々は、パラメータ入力として呼び出しますphase_1機能。

これはphase_1、関数のコンパイルを参照して、入力チェックの関数であること。

phase_1機能

  • エントリー(gdb) disassemble phase_1

出力は以下の

    Dump of assembler code for function phase_1:
        0x08048b80 <+0>:    push   %ebp
        0x08048b81 <+1>:    mov    %esp,%ebp
        0x08048b83 <+3>:    sub    $0x8,%esp
        0x08048b86 <+6>:    movl   $0x8049928,0x4(%esp)
        0x08048b8e <+14>:   mov    0x8(%ebp),%eax
        0x08048b91 <+17>:   mov    %eax,(%esp)
        0x08048b94 <+20>:   call   0x8049067 <strings_not_equal>
        0x08048b99 <+25>:   test   %eax,%eax
        0x08048b9b <+27>:   je     0x8048ba2 <phase_1+34>
        0x08048b9d <+29>:   call   0x804962e <explode_bomb>
        0x08048ba2 <+34>:   leave  
        0x08048ba3 <+35>:   ret    
    End of assembler dump.
  • 二つのレジスタの現在の内容は、EBPをプッシュする前に、前記ESPポインタレジスタとベースレジスタおよび修飾現在のスタックアドレスEBPスタック。

現在の状態

    栈底方向^
    ...
    main
    ...
    参数
    旧ebp  <- ebp, esp寄存器
  • スタックポインタ移動の3行目8つのバイト
    栈底方向^
    ...
    旧ebp <- ebp
    空
    空  <- esp寄存器
  • mov命令と、2つの2つの値がある一つが、位置にスタックから空気ある0x08049928他は、積層方向の底に8バイトEBPスタックコンテンツのオフセット、つまり、私たちの引数であるに基づいていますinput
    栈底方向^
    ...
    旧ebp <- ebp
    0x8049928
    0x8(%ebp)  <- esp寄存器
  • そして、関数を呼び出す<strings_not_equal>ので、私たちはメモリ内にある0x08049928コンテンツを表示するため、私たちは爆弾を解体する必要がある文字列です。
(gdb) x/s 0x8049928

答案是:私たちは...十億を作ることができるのに、なぜ兆を作りますか?

phase_2機能

  • エントリー(gdb) disassemble phase_1
   0x08048ba4 <+0>:     push    %ebp
   0x08048ba5 <+1>:     mov     %esp,%ebp
   0x08048ba7 <+3>:     sub     $0x28,%esp
   0x08048baa <+6>:     movl    $0x0,-0x4(%ebp)
   0x08048bb1 <+13>:    lea     -0x20(%ebp),%eax
   0x08048bb4 <+16>:    mov     %eax,0x4(%esp)
   0x08048bb8 <+20>:    mov     0x8(%ebp),%eax
   0x08048bbb <+23>:    mov     %eax,(%esp)
   0x08048bbe <+26>:    call    0x8048fd4 <read_six_numbers>
   0x08048bc3 <+31>:    movl    $0x0,-0x8(%ebp)
   0x08048bca <+38>:    jmp     0x8048bf3 <phase_2+79>
   0x08048bcc <+40>:    mov     -0x8(%ebp),%eax
   0x08048bcf <+43>:    mov     -0x20(%ebp,%eax,4),%edx
   0x08048bd3 <+47>:    mov     -0x8(%ebp),%eax
   0x08048bd6 <+50>:    add     $0x3,%eax
   0x08048bd9 <+53>:    mov     -0x20(%ebp,%eax,4),%eax
   0x08048bdd <+57>:    cmp     %eax,%edx
   0x08048bdf <+59>:    je      0x8048be6 <phase_2+66>
   0x08048be1 <+61>:    call    0x804962e <explode_bomb>
   0x08048be6 <+66>:    mov     -0x8(%ebp),%eax
   0x08048be9 <+69>:    mov     -0x20(%ebp,%eax,4),%eax
   0x08048bed <+73>:    add     %eax,-0x4(%ebp)
   0x08048bf0 <+76>:    incl    -0x8(%ebp)
   0x08048bf3 <+79>:    cmpl    $0x2,-0x8(%ebp)
   0x08048bf7 <+83>:    jle     0x8048bcc <phase_2+40>
   0x08048bf9 <+85>:    cmpl    $0x0,-0x4(%ebp)
   0x08048bfd <+89>:    jne     0x8048c04 <phase_2+96>
   0x08048bff <+91>:    call    0x804962e <explode_bomb>
   0x08048c04 <+96>:    leave  
   0x08048c05 <+97>:    ret
  • sub $0x28,%esp

    まず、下向きポインタSP空いた空間40bはM0〜M9と呼ばれる便宜上の0x28、32ビットシステム、10単位の合計であります

  • movl $0x0,-0x4(%ebp)

    番号0Hユニットは、ゼロに設定され、すなわちM0=0

  • lea -0x20(%ebp),%eax; mov %eax,0x4(%esp)

    7番アドレスユニットは、8番のセルに割り当てられています。すなわち、M8=&M7M8は、配列へのポインタであってもよく、それは推論することができ、M7は、配列の最初のアドレスです。

  • mov 0x8(%ebp),%eax;mov %eax,(%esp);call 0x8048fd4 <read_six_numbers>

    最後のユニットM9で引数、およびその関数を呼び出すには、6桁の数字をお読みください。正確に10 6個の素子のアレイからなる6つのユニットを、残り、それは我々がA0〜A5になるM6〜M2に入れなければなりません。

  • $movl 0x0,-0x8(%ebp)

    番号1、M1 = 0をゼロ

  • $cmpl 0x2,-0x8(%ebp);jle 0x8048bcc <phase_2+40>

    M1及び第2比較器、ループ条件は以下であります

  • mov -0x8(%ebp),%eax; mov -0x20(%ebp,%eax,4),%edx

    値EBP-20 + 4 * M1 EDXに、実際には、EDX = A [M1]

  • -0x8(%ebp),%eax; add $0x3,%eax; mov -0x20(%ebp,%eax,4),%eax

    EAX = A [M1 + 3]

  • cmp %eax,%edx; je 0x8048be6 <phase_2+66>; call 0x804962e <explode_bomb>

    このコールexploed_bombと等しくない場合は、EAXとEDXの比較

  • mov -0x8(%ebp),%eax; mov -0x20(%ebp,%eax,4),%eax; add %eax,-0x4(%ebp); incl -0x8(%ebp)

    A [M1]はM0、M1書き込まれる++

  • 推論によって、など本来の機能は、以下の

    void phase_2(char* input){
        int result = 0;
        int a[6];
        input >> a;
        for(int i=0;i<=2;i++){
            if (a[i]!=a[i+3])
                bomb();
            result += a[i];
        }
        if(reuslt == 0)
            bomb()
    }

そう答えは、6つの要素の配列、[I]、およびである[I + 3]と同じ、及び和([0]、 [1]、[2])!= 0 とすることができます。1 2 3 1 2 3または1 1 1 1 1 1

phase_3機能

    Dump of assembler code for function phase_3:
    0x08048c06 <+0>:    push   %ebp
    0x08048c07 <+1>:    mov    %esp,%ebp
    0x08048c09 <+3>:    sub    $0x28,%esp
    0x08048c0c <+6>:    movl   $0x0,-0x8(%ebp)
    0x08048c13 <+13>:   movl   $0x0,-0x4(%ebp)
    0x08048c1a <+20>:   lea    -0x10(%ebp),%eax
    0x08048c1d <+23>:   mov    %eax,0xc(%esp)
    0x08048c21 <+27>:   lea    -0xc(%ebp),%eax
    0x08048c24 <+30>:   mov    %eax,0x8(%esp)
    0x08048c28 <+34>:   movl   $0x804995b,0x4(%esp)
    0x08048c30 <+42>:   mov    0x8(%ebp),%eax
    0x08048c33 <+45>:   mov    %eax,(%esp)
    0x08048c36 <+48>:   call   0x8048868 <sscanf@plt>
    0x08048c3b <+53>:   mov    %eax,-0x4(%ebp)
    0x08048c3e <+56>:   cmpl   $0x1,-0x4(%ebp)
    0x08048c42 <+60>:   jg     0x8048c49 <phase_3+67>
    0x08048c44 <+62>:   call   0x804962e <explode_bomb>
    0x08048c49 <+67>:   mov    -0xc(%ebp),%eax
    0x08048c4c <+70>:   mov    %eax,-0x14(%ebp)
    0x08048c4f <+73>:   cmpl   $0x7,-0x14(%ebp)
    0x08048c53 <+77>:   ja     0x8048c98 <phase_3+146>
    0x08048c55 <+79>:   mov    -0x14(%ebp),%edx
    0x08048c58 <+82>:   mov    0x8049964(,%edx,4),%eax
    0x08048c5f <+89>:   jmp    *%eax
    0x08048c61 <+91>:   addl   $0x2cc,-0x8(%ebp)
    0x08048c68 <+98>:   subl   $0x3a9,-0x8(%ebp)
    0x08048c6f <+105>:  addl   $0x12f,-0x8(%ebp)
    0x08048c76 <+112>:  subl   $0xcb,-0x8(%ebp)
    0x08048c7d <+119>:  addl   $0x5d,-0x8(%ebp)
    0x08048c81 <+123>:  subl   $0x2f4,-0x8(%ebp)
    0x08048c88 <+130>:  addl   $0x2f4,-0x8(%ebp)
    0x08048c8f <+137>:  subl   $0x207,-0x8(%ebp)
    0x08048c96 <+144>:  jmp    0x8048c9d <phase_3+151>
    0x08048c98 <+146>:  call   0x804962e <explode_bomb>
    0x08048c9d <+151>:  mov    -0xc(%ebp),%eax
    0x08048ca0 <+154>:  cmp    $0x5,%eax
    0x08048ca3 <+157>:  jg     0x8048cad <phase_3+167>
    0x08048ca5 <+159>:  mov    -0x10(%ebp),%eax
    0x08048ca8 <+162>:  cmp    %eax,-0x8(%ebp)
    0x08048cab <+165>:  je     0x8048cb2 <phase_3+172>
    0x08048cad <+167>:  call   0x804962e <explode_bomb>
    0x08048cb2 <+172>:  leave  
    0x08048cb3 <+173>:  ret    
    End of assembler dump.
  • 0x08048c06 ~ 0x08048c36

    次のように、アプリケーション10ワード(4B /ワード)空間であったM0=0, M1=0, M6=&M3, M7=&M2,M8=0x804995b, M9=%ebp+8(依然としてEBP-を0x4からEBP-の0x28に、部4Bとしてそれぞれ)、およびその関数を呼び出しますsscanf

    パラメータとしてM9が入力された我々の規則、未知M8、M7、M2は、逆の順序でスタックのパラメータので、M2、M3にポインタ値を渡します。

  • 私たちは、内容M8(0x804995b)のを確認してください

    文字列「%D%D」が格納されている、見つけることができます

    これは正確に二つのポインタによって達成される私たちの2つのデジタル入力と2つのデジタル転送を伝えます。

  • 0x08048c3b~0x08048c44

    上のsscanf1より大きいかどうかを確認するためのチェックの結果、そうでない場合は、コール爆弾()

  • 0x08048c49~0x08048c53

    チェックするNUM1は7以上ではないが必要です。

  • 0x08048c55~0x08048c5f

    無条件ジャンプステートメントは、(NUM1が4 + 0x8049964 *)、注意が外にジャンプし*、分岐先がないnum1*4+0x8049964電流範囲がより7 num1を、少しではないので、しかし、メモリ内のアドレスの値すばらしいです

  • 0x08048c61~0x08048c96

    この部分は位置、すなわちM1のプラスまたはマイナスの一定数をジャンプするジャンプ文でなければなりません。

  • 0x08048c9d~0x08048ca3

    次いでNUM1と必要ない5つ以上のチェック、再びスコープ本明細書NUM1を低減

  • 0x08048ca5~0x08048cab

    そして、NUM2はM1、同等の要件と比較します

したがって、値NUM1が5以下であるが、我々は、NUM2算出された位置-519 5を取ることができ、M1のNUM2演算結果でなければなりません

phase_4機能

    Dump of assembler code for function phase_4:
        0x08048ce3 <+0>:    push   %ebp
        0x08048ce4 <+1>:    mov    %esp,%ebp
        0x08048ce6 <+3>:    sub    $0x28,%esp
        0x08048ce9 <+6>:    lea    -0xc(%ebp),%eax
        0x08048cec <+9>:    mov    %eax,0x8(%esp)
        0x08048cf0 <+13>:   movl   $0x8049984,0x4(%esp)
        0x08048cf8 <+21>:   mov    0x8(%ebp),%eax
        0x08048cfb <+24>:   mov    %eax,(%esp)
        0x08048cfe <+27>:   call   0x8048868 <sscanf@plt>
        0x08048d03 <+32>:   mov    %eax,-0x4(%ebp)
        0x08048d06 <+35>:   cmpl   $0x1,-0x4(%ebp)
        0x08048d0a <+39>:   jne    0x8048d13 <phase_4+48>
        0x08048d0c <+41>:   mov    -0xc(%ebp),%eax
        0x08048d0f <+44>:   test   %eax,%eax
        0x08048d11 <+46>:   jg     0x8048d18 <phase_4+53>
        0x08048d13 <+48>:   call   0x804962e <explode_bomb>
        0x08048d18 <+53>:   mov    -0xc(%ebp),%eax
        0x08048d1b <+56>:   mov    %eax,(%esp)
        0x08048d1e <+59>:   call   0x8048cb4 <func4>
        0x08048d23 <+64>:   mov    %eax,-0x8(%ebp)
        0x08048d26 <+67>:   cmpl   $0x78,-0x8(%ebp)
        0x08048d2a <+71>:   je     0x8048d31 <phase_4+78>
        0x08048d2c <+73>:   call   0x804962e <explode_bomb>
        0x08048d31 <+78>:   leave  
        0x08048d32 <+79>:   ret    
    End of assembler dump.
  • 0x08048ce3~0x08048cfe

    アプリケーション・スタック空間4B * 10、及びM2を(次のように行わebp-0xc)アドレスM7(書き込みesp+0x8)、0x8049984その後呼び出し、書き込みM8は、上部M9に入ってくるパラメータを渡します<sscanf@plt>

    我々は0x8049984文字列であり、チェック%d、可視リードライトポインタM2 M7と整数

  • 0x08048d03~0x08048d06

    sscanf戻り値、それが唯一の数値入力が必要ですチェック

  • 0x08048d0c~0x08048d11

    入力要求の数をチェックすると、0より大きい

  • 0x08048d18~0x08048d1e

    入力パラメータとして、呼び出しFUNC4

  • FUNC4チェック

    見つけることができ、FUNC4は、再帰的な階乗関数です。

  • 0x08048d23~0x08048d2a

    FUNC4 M1、M1、および0x78とに戻り値が必要と等しい、すなわちクレームにおけるM1の== 120と比較されます

5:私たちはちょうどその答えの120ビットの結果の数値の階乗を見つける必要があります

phase_5

    (gdb) disassemble phase_5
    Dump of assembler code for function phase_5:
        0x08048d33 <+0>:    push   %ebp
        0x08048d34 <+1>:    mov    %esp,%ebp
        0x08048d36 <+3>:    sub    $0x18,%esp
        0x08048d39 <+6>:    mov    0x8(%ebp),%eax
        0x08048d3c <+9>:    mov    %eax,(%esp)
        0x08048d3f <+12>:   call   0x804903d <string_length>
        0x08048d44 <+17>:   mov    %eax,-0x4(%ebp)
        0x08048d47 <+20>:   cmpl   $0x6,-0x4(%ebp)
        0x08048d4b <+24>:   je     0x8048d52 <phase_5+31>
        0x08048d4d <+26>:   call   0x804962e <explode_bomb>
        0x08048d52 <+31>:   movl   $0x0,-0x8(%ebp)
        0x08048d59 <+38>:   movl   $0x0,-0xc(%ebp)
        0x08048d60 <+45>:   jmp    0x8048d7e <phase_5+75>
        0x08048d62 <+47>:   mov    -0xc(%ebp),%eax
        0x08048d65 <+50>:   add    0x8(%ebp),%eax
        0x08048d68 <+53>:   movzbl (%eax),%eax
        0x08048d6b <+56>:   movsbl %al,%eax
        0x08048d6e <+59>:   and    $0xf,%eax
        0x08048d71 <+62>:   mov    0x804a5c0(,%eax,4),%eax
        0x08048d78 <+69>:   add    %eax,-0x8(%ebp)
        0x08048d7b <+72>:   incl   -0xc(%ebp)
        0x08048d7e <+75>:   cmpl   $0x5,-0xc(%ebp)
        0x08048d82 <+79>:   jle    0x8048d62 <phase_5+47>
        0x08048d84 <+81>:   cmpl   $0x49,-0x8(%ebp)
        0x08048d88 <+85>:   je     0x8048d8f <phase_5+92>
        0x08048d8a <+87>:   call   0x804962e <explode_bomb>
        0x08048d8f <+92>:   leave  
        0x08048d90 <+93>:   ret    
    End of assembler dump.
  • 0x08048d33~0x08048d44

    アプリケーション・スタック空間4B * 6、関数は入力と呼ばれ<string_length>、その結果M0、すなわちを書き込み、M0=length(input)

  • 0x08048d47~0x08048d4d

    請求項6に入力長、長さをチェックします。

  • 0x08048d52~0x08048d60

    0に割り当てられたM1、M2、ジャンプ

  • 0x08048d62~0x08048d6e

    (入力+ M2)0は、入力文字列と等価である、という事実であるため、対応するアドレス値で除去EAX、EAXに拡張eax=input[M2]、8つのEAX後に採取し、符号拡張をライトバックし、最後に撮影しました最後の4桁の数字。ここで入力としてASCIIコードであるので、0〜127の符号拡張の範囲を拡張しなければなりません。4つの入力に相当する操作の最終的な一連の各文字のASCIIコード値を取ります。

  • 0x08048d71~0x08048d78

    基づいて撮影0x804a5c0シフトメモリの内容、M1に蓄積

  • 0x08048d7b~0x08048d82

    M2増分は、サイクルを続け、5以下が決定されています

  • 0x08048d84

    請求項中の0x49ビット累算結果

  • チェック0x804a5c0内容を

    対応する値:2、10、6、1、12、16、9、3、4、7、14、5、11、8、15、

    我々は6を取る、と等しい0x49を加えた場合

文字列を取ることができるようにここで、私は、限り、4つの条件を満足することができるよう、2,5,5,5,5,7 6の標準番号を削除します255557

phase_6

    (gdb) disassemble phase_6
    Dump of assembler code for function phase_6:
        0x08048e25 <+0>:    push   %ebp
        0x08048e26 <+1>:    mov    %esp,%ebp
        0x08048e28 <+3>:    sub    $0x18,%esp
        0x08048e2b <+6>:    movl   $0x804a660,-0x8(%ebp)
        0x08048e32 <+13>:   mov    0x8(%ebp),%eax
        0x08048e35 <+16>:   mov    %eax,(%esp)
        0x08048e38 <+19>:   call   0x8048858 <atoi@plt>
        0x08048e3d <+24>:   mov    %eax,-0xc(%ebp)
        0x08048e40 <+27>:   mov    -0x8(%ebp),%eax
        0x08048e43 <+30>:   mov    %eax,(%esp)
        0x08048e46 <+33>:   call   0x8048d91 <fun6>
        0x08048e4b <+38>:   mov    %eax,-0x8(%ebp)
        0x08048e4e <+41>:   mov    -0x8(%ebp),%eax
        0x08048e51 <+44>:   mov    %eax,-0x4(%ebp)
        0x08048e54 <+47>:   movl   $0x1,-0x10(%ebp)
        0x08048e5b <+54>:   jmp    0x8048e69 <phase_6+68>
        0x08048e5d <+56>:   mov    -0x4(%ebp),%eax
        0x08048e60 <+59>:   mov    0x8(%eax),%eax
        0x08048e63 <+62>:   mov    %eax,-0x4(%ebp)
        0x08048e66 <+65>:   incl   -0x10(%ebp)
        0x08048e69 <+68>:   cmpl   $0x4,-0x10(%ebp)
        0x08048e6d <+72>:   jne    0x8048e5d <phase_6+56>
        0x08048e6f <+74>:   mov    -0x4(%ebp),%eax
        0x08048e72 <+77>:   mov    (%eax),%eax
        0x08048e74 <+79>:   cmp    -0xc(%ebp),%eax
        0x08048e77 <+82>:   je     0x8048e7e <phase_6+89>
        0x08048e79 <+84>:   call   0x804962e <explode_bomb>
        0x08048e7e <+89>:   leave  
        0x08048e7f <+90>:   ret    
    End of assembler dump.
  • 0x08048e25~0x08048e3d

    アプリケーションスタック空間4B * 6になる0x804a660M1を入れ、入力引数として呼び出され<atoi@plt>、その結果を返しますがM2書かれています

  • 0x08048e40~0x08048e4b

    引数としてM1、fun6を呼び出すには、M1の結果を書き戻す戻ります

  • emmm、fun6は見ていません

ハッハッハ、継続するには

おすすめ

転載: www.cnblogs.com/Axi8/p/11670088.html