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