TCPサーバの接続情報と、ファイル Dockerfile および tROPic-thunder が与えられた。
tROPic-thunder を逆コンパイルすると、以下の main 関数が出てきた。
Information for connection to a TCP server, and files Dockerfile and tROPic-thunder were given.
I decompiled the file tROPic-thunder using main.
この関数は、関数 setup_seccomp() を呼び出した後、fgets 関数でデータを読み込んでいる。
setup_seccomp() 関数は、以下の内容であった。
This function calls a function setup_seccomp(), and then reads data using the function fgets.
This is the function setup_seccomp().
このページ
Referring this page,
seccomp_rule_add(3) - Linux manual page
を参照すると、seccomp_rule_add の第3引数がシステムコールを、第2引数がそのシステムコールが使われた時のアクションを表すことがわかる。
このページ
We can know that the 3rd argument of seccomp_rule_add specifies a system call, and that the 2nd one specifies an action to take when the system call is used.
From this page,
Linux System Call Table for x86 64 · Ryan A. Chapman
より、システムコール 0x3b (59) は sys_execve、0x142 (322) は stub_execveat であることがわかる。
さらに、このページ
We can know that a system call 0x3b (59) corresponds to sys_execve and that 0x142 (322) corresponds to stub_execveat.
Also, this page
libseccomp/seccomp.h.in at main · seccomp/libseccomp · GitHub
より、ここで指定されているアクション 0 は SCMP_ACT_KILL すなわち使用したスレッドが強制終了されることを表していることがわかる。
よって、execve を使わずにflagを得る方法を考えないといけなそうである。
まず、他の問題より、サーバプログラムのカレントディレクトリにファイル flag.txt があると予想した。
さらに、逆アセンブル結果およびバイナリエディタを用いて、ファイル tROPic-thunder から以下のgadgetを見つけた。
Tells us that the action 0, used here, corresponds to SCMP_ACT_KILL, which means that threads that called the system calls are terminated.
This suggests that we should come up with a way to obtain the flag without using execve.
Firstly, considering other challenges, I guessed that there should be a file flag.txt in the working directory of the server program.
Then, using the disassembled code and a binary editor, I found these gadgets from the file tROPic-thunder.
| アドレス address | バイナリ binary data | 処理内容 what to do |
|---|---|---|
| 0x45ed9a | 5e c3 | pop %rsi; ret |
| 0x45b667 | 5f c3 | pop %rdi; ret |
| 0x45b056 | 5a c3 | pop %rdx; ret |
| 0x45899c | 58 c3 | pop %rax; ret |
| 0x403472 | 48 89 50 18 48 83 c4 08 c3 | mov %rdx,0x18(%rax); add $0x8,%rsp; ret |
| 0x401ca7 | 48 83 c4 08 c3 | add $0x8,%rsp; ret |
| 0x40968c | 48 89 c7 ff d2 | mov %rax,%rdi; callq *%rdx |
| 0x484105 | 0f 05 c3 | syscall; ret |
また、.plt セクションの最初と最後は、以下のようになっていた。
Also, this is the first and last part of the section .plt.
ここで参照されている 0x6d6018 から 0x6d60d0 までの領域は書き込みが可能で、かつそれぞれの8バイトのうち最上位の1バイトには 0x00 が格納されていると予想した。
さらに、main 関数の逆アセンブル結果は、以下のようになっていた。
I guessed that the region from 0x6d6018 to 0x6d60d0, referred from here, can be written, and that the highest bytes of each 8 bytes are 0x00.
Moreover, this is the disassembled code of the function main.
fgets が読み込んだデータを書き込み始める位置は %rbp - 0x70 であり、リターンアドレスは %rbp + 8 にあるので、最初に実行させるアドレスはデータの 0x78 バイト目から書き込めばいいことがわかる。
見つけたgadgetを用い、ファイル file.txt の内容を標準出力に書き出す以下の処理を行うことにした。
The address for fgets to store data read is %rbp - 0x70 and one of the return address is %rbp + 8, so the first address to be executed should be written from the 0x78-th byte of the data.
Using the gadgets, I decided to perform these operations to output the contents of the file file.txt to the standard output.
以下が、これを実現するため実際に送る内容である。
This is what should actually be sent to achieve this.
I assembled this with
このデータを
I obtained the flag by sending this data using "Send File" on