参加して2問解いたのでwriteup
nimrev
Nim言語で書かれたプログラムのリバースエンジニアリング。
Nimの内部処理はわからないが、関数名から推測しつつcall
を追っていくと、NimMainModule
がメイン処理であることがわかる。
さらに細かいことを考えずcall
を追っていくと、
- 標準入力から読み込む
- 配列を作成して値を設定
- 配列をmapする
- 配列をjoinする
- eqStringsの結果で分岐して”Correct!”か”Wrong!”のどちらかを出力
という流れと推測できる。
Nim公式のリファレンスを参照してmap処理時のプロシージャの引数位置を確認、コードから該当する箇所を探すとNOT
してるだけとわかるので、2.の配列に設定された値のNOT
を取ってフラグを取得。
Flag: CakeCTF{s0m3t1m3s_n0t_C}
zundamon
実行ファイルとpcapを渡される。pcapには複数のIPの通信があるので、まずはこの実行ファイルの通信先を確認する必要がある。
sink
関数を覗くと通信回りの初期処理をやっており、ここで通信先が164.70.70.9:6379
であることがわかる。pcapから該当する内容を確認するとこんな感じ。
$17
の後にMACアドレスと思われる17バイト、$3
の後に3バイトのデータを送ってることがわかる。MACアドレスは最初からずっと同じで、3バイトのデータは変化している。
3バイトのデータを送信することで何らかの情報を外部創出しているものと思われるので、ここを解析して何が送られているのか見ていく。
$17
と$3
の送信をしている関数はexfiltrate
(そのまんまだ…)で、$3
の送信データになっているバッファを確認すると、3バイトのうち先の2バイトはexfiltrate
の第3引数、後ろ1バイトはexfiltrate
の第2引数で指定されている。
これらの出元をたどると、read
で繰り返し読み込んだデータの書き込み先であることがわかる。書き込み先の先頭はrsp
で、そこから18バイト先からがexfiltrate
での送信データになる。
ではread
で読み込んでいるものは何か。read
の第1引数fdを追いかけると、source
関数の返り値であることがわかるので、source
関数を読み解くと、/dev/input/event1
(キーボード)を開いていることがわかる。その後のioctl
の意味がわからなかったので誰かわかる人教えてほしい。
/dev/input/event1
から得られるデータはinput_event
構造体となる。
struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};
struct timeval
は128bit(16byte)のため、exfiltrate
に渡されるデータは、code
とvalue
(の先頭1バイト)になることがわかった。code
の値はinput-event-code.h
にキーボードのキーとの対応が定義されている。value
はキーの状態を表し、0がup、1がdown、2がholdとなる。ちなみに、各キーを押したときのcode
の値はevtest
コマンドで確認できる。
pcapから3バイトのデータ部分を抜き出すとキーボードの入力履歴情報となる。使用されていたのが日本語レイアウトのキーボードであること、NumLockがOffのときのキーパッド1はEndであることに注意すると、以下の文字列が抽出できる。
CakeCTF{b3_c4r3fuL_0f_m4l1c10us_k3yL0gg3r}
I hope nobody is seeing my screen...
Flag: CakeCTF{b3_c4r3fuL_0f_m4l1c10us_k3yL0gg3r}