c - このバイナリ爆弾のフェーズ4を解除する方法

原文 c linux assembly x86 gdb

このアセンブリ言語のコードに問題があります。
基本的に、コードが比較する2つの数値に一致する2つの数値を入力する必要があります。
phase_4の行0x08048c47で、最初の入力を2と比較しているので、最初の入力は2でなければならないことがわかります。次に、最初の入力から次の入力に4スペースを移動し、2を減算します。これで(input-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    
答え
8(%esp)は、x86のフレームワークにおける最初の番号です。
40 2または60 3または80 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;
}
関連記事

c - LCDに間違った値が表示される

c - 32ビットタイプの特定の位置に設定されたビットをカウントする

c++ - cmakeでコンパイルのみの依存関係を追加する方法

python - Cヘッダーファイルで定義のリストを取得する方法

c - ある文字列のプレフィックスと別の文字列のサフィックスから新しい文字列を作成したい

c - GTK3.0でgstreamerを使用してビデオとオーディオを同時に再生する方法

c - 整数ではない無効な入力がある場合、printステートメントの開始時に余分なゼロ

c - ELFファイルの.dynamicセクションのDT_USEDエントリ

c - Cクイックソートセグメンテーションエラー

c - アドレスを使用して、構造体型の値をgdbに出力します