TCPサーバの接続情報と、ファイル Dockerfile
および money-printer
が与えられた。
file
コマンドを使うと、ファイル money-printer
は64bitのELFファイルらしいことわかった。
main
関数が得られたが、役立ちそうな処理は見当たらなかった。
Information for connecting to a TCP server, and files Dockerfile
and money-printer
were given.
Using file
command, I found that the file money-printer
should be a 64-bit ELF file.
I decompiled the file using main
, but I found nothing look useful from here.
ファイル money-printer
を
fgets
で読み込んだ内容を printf
の第一引数に渡し、その後 puts
および exit
を呼び出している以下の部分が見つかった。
I disassembled the file money-printer
using objdump from
Then, I found this part that passes what is read via fgets
to the 1st argument of printf
, and calls functions puts
and exit
.
main
関数の冒頭は、以下のようになっていた。
Also this is the first part of the function main
.
%rsp
は %rbp - 0xc0
、fgets
で文字列を読み込む位置は %rbp - 0x70
であり、その差は 80 バイトである。
レジスタに置かれる引数6個と合わせて、読み込まれる文字列の前には8バイトの引数が16個あるとみなせる。
さらに、逆アセンブル結果の以下の部分は、読み込んだ数値がある値以下かをチェックしているようである。
The value of %rsp
is %rbp - 0xc0
, and where to read a string using fgets
is %rbp - 0x70
. Their difference is 80 bytes.
Therefore, adding 6 arguments on the registers, it can be seen as there are 16 8-byte arguments before the string to be read.
Also, this part of the disassembled program looked like checking if the number read is not greater than some value.
指定のサーバに
I tried connecting to the server with
-1
を入力すると、以下のメッセージが出力された。
Entering -1
, this message appeared.
そこで、以下の文字列を入力してみた。
Then, I entered this string.
すると、以下のメッセージが出力され、入力した文字列の最初が printf
関数で16番目のデータとして用いられるらしいことがわかった。
As a result, this message appeared. This is suggesting that the first part of the string entered is used as the 16th data in the function printf
.
これを利用して、まずはいくつかの標準ライブラリ関数のアドレスを調べることにした。
.plt
セクションの逆アセンブル結果より、printf
関数のアドレスが 0x601030
に、fopen
関数のアドレスが 0x601048
に格納されることがわかる。
これらのアドレスを利用した以下のデータを Tera Term の「ファイル送信」で送信し、通信内容を
Using this, I firstly obtained the addresses of some standard library functions.
According to the disassembled code of the .plt
section, the address of the function printf
will be stored at 0x601030
and one of the function fopen
will be stored at 0x601048
.
I sent this data, using these addresses, via "Send File" on Tera Term, and watched the communication using
その結果、(例えば) printf
関数のアドレスは 0x7f2aa39ace40
、fopen
関数のアドレスは 0x7f2aa39c6de0
であった。
これらのアドレスを
これにより printf
関数と system
関数のアドレスの差が求まるので、以下の手順によりシェルを起動することができる。
printf
のアドレスを取得しつつ、繰り返し入力できるように exit
として実行する関数のアドレスを main
関数のアドレスにする。printf
として実行する関数のアドレスを system
関数のアドレスにする。/bin/sh
を入力し、system("/bin/sh");
を実行させる。
これを行う以下のプログラムを作成した。
printf
のアドレス全部を書き換えようとすると入力文字数制限に引っかかったので、下位3バイトだけを書き換えるようにした。
As a result, I found that (for example) the address of the function printf
is 0x7f2aa39ace40
and one of the function fopen
is 0x7f2aa39c6de0
.
I queried
We can use this to calculate the difference between the address of the functions printf
and system
, so the shell can be launched by these steps.
printf
, and at the same time set the address to be executed as exit
to the address of the function main
to have it accept inputs repeatedly.printf
to the address of the function system
./bin/sh
to have it execute system("/bin/sh");
.
I wrote this program to perform these steps.
I failed to have it rewrite the whole address for printf
due to the length limit for inputs, so I had it rewrite only the lower 3 bytes.
このプログラムを実行すると、シェルを起動できた。
シェルで ls -al
コマンドを実行すると、ファイル flag.txt
があることがわかった。
コマンド cat flag.txt
を実行すると、flagが得られた。
I succeeded to launch the shell by running this program.
Executing a command ls -al
on the shell revealed that a file flag.txt
exists.
I obtained the flag by executing a command cat flag.txt
.