Index

3/8 guess.js

Function(guess, "...")(1337) で、こちらが制御できるのは関数の引数リスト側。

なので SECRET を当てるのではなく、引数部分で処理を発生させてFLAGを抜く。

{x=console.log(process.env.FLAG)}

引数部分の波括弧は分割代入であり、1337にはxプロパティが存在しないためデフォルト引数にしたconsole.log部が実行される。

3/9 FLAG OVER

子プロセスの bash -ienv={"FLAG": "🦙"} で起動されるが、親の Python プロセスは本物の FLAG を保持したまま。 したがって bash から親 PID を辿って /proc/$PPID/environ を読めば回収できる。

cat /proc/$PPID/environ

3/10 100

100 回異なる文字列を入れて、毎回 int(s) == 100 を満たせばよい。

Python の int()100 以外にも +100, 00100, 1_00, 0_0_100 のような表記を普通に受理する。 なので +_ と先頭ゼロを組み合わせて、長さ 10 以下の別表記を 100 個作れば通る。

3/11 Find XOR key

7文字の鍵で flag を繰り返し XOR している。

flag の先頭は Alpaca{ と分かっていて、これはちょうど 7 文字なので、暗号文の先頭 7 バイトと XOR すると鍵が復元できる。 あとはその鍵を繰り返して暗号文全体を XOR すれば flag が得られる。

3/12 kappa overflow

buf[64] の直後に volatile int *target が置かれていて、gets(cache.buf) がそのままオーバーフローする。 その後に *cache.target = 1; が実行されるので、target を不正ポインタに壊せばアクセス違反になる。

このバイナリは SetUnhandledExceptionFilter(handler) を使っていて、例外時に handler() から win() が呼ばれる。

したがってb"A" * 72 を送って target を壊すだけでよい。