Index
Function(guess, "...")(1337) で、こちらが制御できるのは関数の引数リスト側。
なので SECRET を当てるのではなく、引数部分で処理を発生させてFLAGを抜く。
{x=console.log(process.env.FLAG)}
引数部分の波括弧は分割代入であり、1337にはxプロパティが存在しないためデフォルト引数にしたconsole.log部が実行される。
子プロセスの bash -i は env={"FLAG": "🦙"} で起動されるが、親の Python プロセスは本物の FLAG を保持したまま。
したがって bash から親 PID を辿って /proc/$PPID/environ を読めば回収できる。
cat /proc/$PPID/environ
100 回異なる文字列を入れて、毎回 int(s) == 100 を満たせばよい。
Python の int() は 100 以外にも +100, 00100, 1_00, 0_0_100 のような表記を普通に受理する。
なので + と _ と先頭ゼロを組み合わせて、長さ 10 以下の別表記を 100 個作れば通る。
7文字の鍵で flag を繰り返し XOR している。
flag の先頭は Alpaca{ と分かっていて、これはちょうど 7 文字なので、暗号文の先頭 7 バイトと XOR すると鍵が復元できる。
あとはその鍵を繰り返して暗号文全体を XOR すれば flag が得られる。
buf[64] の直後に volatile int *target が置かれていて、gets(cache.buf) がそのままオーバーフローする。
その後に *cache.target = 1; が実行されるので、target を不正ポインタに壊せばアクセス違反になる。
このバイナリは SetUnhandledExceptionFilter(handler) を使っていて、例外時に handler() から win() が呼ばれる。
したがってb"A" * 72 を送って target を壊すだけでよい。