Badseed
テキストファイル pwntools_intro
と、ELFファイル badseed
が与えられた。
badseed
をGhidra で逆コンパイルすると、以下の関数を順に実行していることがわかった。
init()
question_one()
- 計算を行い、何らかの値を生成する。
scanf
関数の書式 %d
を用い、値を読み込む。
- 生成した値と読み込んだ値が違っていれば、実行を終了する。
question_two()
time
関数を用い、時刻を取得する。
scanf
関数の書式 %d
を用い、値を読み込む。
- 取得した時刻を引数として
srand
関数を呼び出す。
rand
関数を2回呼び出す。
- 2回目に呼び出された時の
rand
関数の返り値と読み込んだ値を比較し、違っていたら実行を終了する。
question_three()
time
関数で時刻を取得し、それを引数として srand
関数を呼び出す。
rand
関数を呼び出し、その返り値を引数として srand
関数を呼び出す。
rand
関数を呼び出す。
- 最初の
rand
関数の返り値を2番目のrand
関数の返り値で割り、さらにその結果を 1000
で割った余りを求める。
scanf
関数の書式 %d
を用い、値を読み込む。
- 求めた余りと読み込んだ値を比較し、違っていたら実行を終了する。
gz()
system("/bin/sh");
を実行する。
A text file pwntools_intro
and a ELF file badseed
were given.
Decompiling badseed
via Ghidra, I found it executing these functions in this order:
init()
- Configure buffering and timeout.
question_one()
- Generate a value by some calculation.
- Read a value using the function
scanf
with the format specifier %d
.
- Terminate execution if the generated value and the value read differ.
question_two()
- Obtain the time using the function
time
.
- Read a value using the function
scanf
with the format specifier %d
.
- Call the function
srand
using the time obtained as the argument.
- Call the function
rand
twice.
- Compare the second return value of the function
rand
and the value read, and terminate execution if they differ.
question_three()
- Obtain the time using the function
time
, and call the function srand
using that as the argument.
- Call the function
rand
, and call the function srand
using the return value of as the argument.
- Call the function
rand
.
- Divide the first return value of
rand
by the second return value, and divide the quotient by 1000 to obtain the remainder.
- Read a value using the function
scanf
with the format specifier %d
.
- Compare the remainder and the value read, and terminate execution if they differ.
gz()
- Execute
system("/bin/sh");
.
まず、question_one
関数で入力するべき値を調べるため、badseed
をCS50 IDEにアップロードし、GDB上で実行した。
この値をメモリに保存した直後である 0x40132b
にブレークポイントを設定し、メモリに保存した値が入っているRAX
レジスタの値を出力させると、この値は 662
であるとわかった。
question_two
関数とquestion_three
関数に関しては、同様の処理で値を求める以下のプログラムを用意した。
Firstly, to determine the value to input for the function question_one
, I uploaded badseed
to CS50 IDE and ran on GDB.
I set a breakpoint to 0x40132b
, which is just after storing the value to the memory, and checked the value of the RAX
register, which has the value stored to the memory. As a result, I found that the value is 662
.
To determine the values for the function question_two
and question_three
, I created this program to obtain values via the process used in the functions.
solve.c
サーバに前の関数用の値を入力する際に時計を見て時刻を確認し、以下のページでUNIX時間に変換した。
日付⇒UNIX時間変換 - 高精度計算サイト
得られたUNIX時間をコマンドライン引数とし、CS50 IDE上でこのプログラムを実行することで、サーバに入力すると処理を進めることができる値が得られた。
処理を進めるとシェルが起動するので、ls -al
コマンドを実行すると、ファイル flag.txt
があることがわかった。
cat flag.txt
コマンドを実行すると、flagが得られた。
I checked the time on a clock when I enter the values for functions executed before the targets to the server, and converted the time to UNIX timestamp using this page:
Convert Date & Time to Unix timestamp Calculator - High accuracy calculation
I succeeded to obtain the values to have the server move on the next steps by executing the program on CS50 IDE using the UNIX timestamps as the command-line argument.
The shell is launched after some proceeding. I executed a command ls -al
and found that there is a file flag.txt
.
I obtained the flag by executing a command cat flag.txt
.
flag{i_0_w1th_pwn70ols_i5_3a5y}
writeup by MikeCAT
K3RN3L CTF