TCPサーバの接続情報、サーバのプログラム(C言語のソースコードとELFファイル)、
そしてELFファイルlibc.so.6とld-linux-x86-64.so.2が与えられた。
与えられたソースコードを読むと、gets関数で入力を読み込む処理を含む関数verifyを呼び出していた。
objdumpで逆アセンブルした結果より、
読み込み先はRBPの0x100バイト前で、RBPの8バイト先にリターンアドレスがあることが読み取れた。
そこで、リターンアドレスの手前までを埋めるデータplaceholder.binと、
ROP (Return-Oriented Programming) を用いて以下の処理を行うデータleak.binを用意した。
pop rsi; pop r15; retというgadgetを用い、RSIをputsのアドレスが格納されているアドレスに設定する。pop rdi; retというgadgetを用い、RDIを"Hi %s!\n"のアドレスに設定する。printf関数を呼び出す。verify関数の先頭 (スタックのアラインメントを考え、プロローグの次) に制御を移す。
Information to connect to a TCP server, the program of the server (C source code and a ELF file),
and ELF files libc.so.6 and ld-linux-x86-64.so.2 were given.
Reading the source code given, I found that a function verify that reads some input via the function gets called.
Disassembling via objdump in
Based on these, I created a data to fill the stack before the return address placeholder.bin
and a data to do following things via ROP (Return-Oriented Programming) leak.bin.
puts is stored via a gadget pop rsi; pop r15; ret."Hi %s!\n" via a gadget pop rdi; ret.printf function.verify (after the function prologue, considering the stack alignment).
placeholder.bin、leak.binの順に送信し、
puts関数のアドレスを知り、
再び入力を受け付けさせることができた。
次の手順の準備のため、libc.so.6をTDM-GCCのobjdumpで逆アセンブルし、
先頭の以下の関数のアドレスを
I sent placeholder.bin and then leak.bin via "Send file" with puts and have the server accept another input.
To prepare for the next step, I disassembled libc.so.6 via objdump in TDM-GCC,
and put the addresses of following functions to
abort__libc_init_first__libc_start_maingnu_get_libc_release
結果は複数出たが、使いたいputs、str_bin_sh、systemの値は共通しており、特定ができたといえる。
この情報を利用し、ROPにより以下を行うデータを生成するプログラムgen.plを作成した。
pop rdi; retというgadgetを用い、RDIをstr_bin_shに設定する。retというgadgetを用い、スタックのアラインメントを調整する。systemに制御を移す。
There were several results, but the values of puts, str_bin_sh, and system to use were the same, so this can be considered as identified.
Using this information, I created a program gen.pl to generate a data to do following things via ROP.
str_bin_sh via a gadget pop rdi; ret.ret.system.
もう一度placeholder.binを「ファイル送信」した後、生成したデータを「ファイル送信」することで、シェルを起動できた。
シェルでlsコマンドを実行することでファイルflag.txtが存在することがわかり、
cat flag.txtコマンドを実行することでflagが得られた。
I sent placeholder.bin again via "Send file", and then sent the generated data via "Send file" to launch the shell.
Using a command ls in the shell revealed that there is a file flag.txt.
I obtained the flag by executing a command cat flag.txt.