Ret2Libc

TCPサーバの接続情報、サーバのプログラム(ELFファイル) ret2libc、そのソースコード ret2libc.c、 ELFファイル ld-2.31.so および libc-2.31.so が与えられた。

ret2libc.c を読むと、gets関数で入力を読み込む処理がある関数learnがあった。
そこで、TDM-GCCobjdump による ret2libc の逆アセンブル結果を用いて、 以下のデータを用いた ROP (Return-Oriented Programming) により、puts関数のメモリ上のアドレスを出力させ、learn関数をもう一度呼ばせることにした。
gets関数が読み込んだデータの書き込み先は-0x20(%rbp)であり、%rbpは関数の呼び出し後1回pushした時の%rspなので、 リターンアドレスは読み込んだデータの書き込み先の先頭から0x28バイト後である。

以下が実際にサーバに送信するデータである。

Information to connect to a TCP server, the server program (a ELF file) ret2libc, its source code ret2libc.c, and ELF files ld-2.31.so and libc-2.31.so were given.

Reading ret2libc.c, I found a function learn that reads some input via the function gets.
Seeing this, I decided to perform ROP (Return-Oriented Programming) using following sequence of data
to have it output the address of the function puts on the memory and call the function learn again using the result of disassembling of ret2libc via objdump in TDM-GCC.
The function gets here will write what it read from -0x20(%rbp) and %rbp is %rsp after one push from the beginning of the function,
so the return address is 0x28 bytes after the head of data written by the function gets.

Here is the actual data to send to the server:

payload_leak.bin

この payload_leak.binTera Termで「ファイル送信」し、 サーバの応答をWiresharkで見ることで、puts関数のメモリ上のアドレスがわかる。

さらに、readelf -s コマンドを libc-2.31.so に適用し、 puts関数とsystem関数のファイル中の位置を調べると、以下のようになった。

We can obtain the address of the function puts in the memory by sending this file payload_leak.bin via "Send file" in Tera Term and observing the response from the server via Wireshark.

Also, I applied readelf -s command to the file libc-2.31.so to obtain the place in the file of the functions puts and system. Here is the result:

430: 00000000000765f0 472 FUNC WEAK DEFAULT 14 puts@@GLIBC_2.2.5 1430: 0000000000048e50 45 FUNC WEAK DEFAULT 14 system@@GLIBC_2.2.5

また、libc-2.31.so から文字列 /bin/sh をバイナリエディタで検索すると、 0x18A152 バイト目 (0-origin) に見つかった。

これらに基づき、求めたputs関数のメモリ上のアドレスを引数とし、 system("/bin/sh"); を実行させるためのデータを生成するプログラム payload_gen.pl を作成した。

Moreover, I searched for a string /bin/sh from the file libc-2.31.so via a binary editor, finding at the 0x18A152-nd byte. (the first byte is 0th)

Based on these, I created this program payload_gen.pl that takes the address of the function puts in the memory as an argument and generates data to have it execute system("/bin/sh");.

payload_gen.pl

生成したデータをTera Termで「ファイル送信」することでシェルを起動でき、 ls コマンドを実行すると flag.txt があることがわかった。

cat flag.txt コマンドを実行すると、flagが得られた。

I succeeded to launch the shell by sending generated data via "Send file" in Tera Term. I found an entry flag.txt by executing ls command.

I obtained the flag by executing cat flag.txt command.

flag{th3_wh0l3_us3l3r4nd_1s_my_pl4ygr0und}

PBjar CTF