Index
0x10サイズのheap chunkを2つ確保し、1つ目に gets で入力する。直後に malloc_usable_size(buf_2) == 0x100 ならシェルが起動するので、1つ目から2つ目のchunk headerへ溢れさせる。
通常のchunk size改ざんだと整合性チェックに引っかかるが、sizeに IS_MMAPPED bitを立てると malloc_usable_size 側の扱いが変わる。buf_2 のsize fieldを 0x113 にすればusable sizeが0x100相当になり、条件を満たせる。
Shamir Secret Sharingの問題。法は 2^521-1、thresholdは3で、フラグ整数が2次多項式の定数項になっている。出力にはちょうど3つのshareが与えられる。
3点があれば2次多項式は一意に決まる。有限体上でLagrange補間を行い、f(0) を評価して定数項を取り出す。得た整数をbytesへ戻すとフラグになる。
Flaskはユーザごとのsecretをセッションに紐づけ、/render/<lang> でテンプレート内に表示する。/report ではadminセッションを作り、adminのsecretとしてFLAGを持った状態で指定URLへアクセスする。
前段Nginxは .css や .js で終わるパスを長期間キャッシュし、セッション差分を考慮しない。botに /render/en.css を踏ませるとadminのFLAG入りレスポンスがキャッシュされ、その後同じURLを自分で読むとキャッシュからFLAGが返る。
暗号化は「鍵xor」とPBOXを32回繰り返す構造だが、PBOXもxorもGF(2)上では線形またはアフィンな変換として扱える。つまり全体は A^32 * plaintext xor constant という形になる。
まず全ゼロ平文を暗号化してconstantを得る。目標暗号文からconstantをxorで消し、A^32 の逆変換をGF(2)上で適用すれば元のchallenge bytesが戻る。
添付にはQEMU起動用のkernel/initramfsと、鍵が42であることを示す補助スクリプトが含まれている。initramfs.cpio を展開すると /flag.txt があり、実行時には権限で読みにくいが、アーカイブ内の内容は確認できる。
flag.txt の各バイトを42でxorすると平文が出る。
Cの _Decimal64 で 0.1dd と入力値を数値比較しつつ、raw bytesは違うことを要求している。decimal floating pointでは同じ数値でも指数と係数の表現が複数ある。
ヒントの 0.1dd は 31A0000000000001 だが、0.10dd に対応する 318000000000000A も数値としては等しい。raw表現は異なるため、これを入力すると両方の条件を満たせる。