[日本語] [English]

Badseed

テキストファイル pwntools_intro と、ELFファイル badseed が与えられた。

badseedGhidra で逆コンパイルすると、以下の関数を順に実行していることがわかった。

  1. init()
    • バッファリングとタイムアウトの設定を行う。
  2. question_one()
    1. 計算を行い、何らかの値を生成する。
    2. scanf関数の書式 %d を用い、値を読み込む。
    3. 生成した値と読み込んだ値が違っていれば、実行を終了する。
  3. question_two()
    1. time関数を用い、時刻を取得する。
    2. scanf関数の書式 %d を用い、値を読み込む。
    3. 取得した時刻を引数として srand関数を呼び出す。
    4. rand関数を2回呼び出す。
    5. 2回目に呼び出された時のrand関数の返り値と読み込んだ値を比較し、違っていたら実行を終了する。
  4. question_three()
    1. time関数で時刻を取得し、それを引数として srand関数を呼び出す。
    2. rand 関数を呼び出し、その返り値を引数として srand 関数を呼び出す。
    3. rand 関数を呼び出す。
    4. 最初のrand関数の返り値を2番目のrand関数の返り値で割り、さらにその結果を 1000 で割った余りを求める。
    5. scanf関数の書式 %d を用い、値を読み込む。
    6. 求めた余りと読み込んだ値を比較し、違っていたら実行を終了する。
  5. gz()
    • system("/bin/sh"); を実行する。

まず、question_one 関数で入力するべき値を調べるため、badseedCS50 IDEにアップロードし、GDB上で実行した。
この値をメモリに保存した直後である 0x40132b にブレークポイントを設定し、メモリに保存した値が入っているRAXレジスタの値を出力させると、この値は 662 であるとわかった。

question_two関数とquestion_three関数に関しては、同様の処理で値を求める以下のプログラムを用意した。

solve.c

サーバに前の関数用の値を入力する際に時計を見て時刻を確認し、以下のページでUNIX時間に変換した。

日付⇒UNIX時間変換 - 高精度計算サイト

得られたUNIX時間をコマンドライン引数とし、CS50 IDE上でこのプログラムを実行することで、サーバに入力すると処理を進めることができる値が得られた。

処理を進めるとシェルが起動するので、ls -al コマンドを実行すると、ファイル flag.txt があることがわかった。
cat flag.txt コマンドを実行すると、flagが得られた。

flag{i_0_w1th_pwn70ols_i5_3a5y}

writeup by MikeCAT

K3RN3L CTF