先日(二週間前)に開催されたTokyo Westerns/MMA CTFにSSR_CTF_BU(ymduu/yosupotの二人)で出ていました。結果は33位でした。

以下解いた問題のwriteup
 

Global Page

webが何もわからないため非常に苦戦した。 page=hogeは自由度が低い(/と.が消される)が、Accept-languagesという欄は自由度が高い。 色々検索したら出てきたphp://filter~みたいなのを実行させたら通った

judgement

フラグを入力して合っているかをチェックしてくれるサービスが与えられる。 入力したフラグをエコーする部分にFSBがある。
起動時にファイルからフラグを読み込んでいるため、スタックの上にフラグ文字列へのアドレスが乗っている。
ので、%28$sでそのフラグを読める。
flag:TWCTF{R3:l1f3_1n_4_pwn_w0rld_fr0m_z3r0}
おたく~

Make a Palindrome!

全探索(next_permutation)

Twin Primes

RSA暗号。
なのだが、二つ用意されているn(n1,n2)が、p*qと(p+2)*(q+2)であるため、p*qとp+qがわかり、pとqを求めることができる。
p,qが分かれば秘密鍵dも計算できるので、cを暗号文として、ans=c^d mod nを計算すれば復号できる。
flag:TWCTF{3102628d7059fa267365f8c37a0e56cf7e0797ef}

Reverse Box

文字列をコマンドライン引数で与えると暗号化して表示してくれるバイナリが与えられる。
バイナリを読むと、randだのtimeだの言ってるサブルーチンでスタックに乱数表を作り、乱数表の先頭から入力文字のasciiコード分だけポインタを進めた場所の乱数を持ってくる、という感じのシーザー暗号的なコードであることがわかる。
が、コードを読まなくても、単一替字式暗号っぽいなあ、ということが分かればバイナリを一切読まずに解ける。
乱数は下1バイトしか使っていないため、乱数表の種類は高々256通りしかないので、1秒に一回暗号化するシェルスクリプトを書けば、与えられた暗号を得られる乱数は簡単に引き当てられる。
フラグが"TWCTF{"で始まっていることを考えると、 TWCTF ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_ を暗号化することを繰り返すシェルスクリプトを書いて、先頭が"95eeaf95ef"になる出力だけ取り出せば替字表が手に入る。
替字表があればdecryptできる。(得た替字表に'-'が入っていなかったため、-だけ復号できなくて困ったが、エスパーで通してしまった)
flag:TWCTF{5UBS717U710N_C1PH3R_W17H_R4ND0M123D_5-B0X}

greeting

greeting tomoriセクションにあるnao関数が特徴的な問題。
セキュキャンCTFにもnao関数がある問題があったらしいですね(僕はその問題を見つけることができなかった)
バイナリを起動すると名前を入れろと言われて、入れるとNice to meet youとか言われる。
脆弱性はNice to meet you部分にjudgement同様FSBがあるが、スタックの上にフラグのアドレスが乗っているということはなく、一回のFSBに使える文字列の長さが64byteであるため、一回のFSBで1ワードしかoverwriteできず、FSBの後にはほぼ何もなく終了してしまう(=GOT overwriteでsystemにすり替えられる関数が無い)。
FSBの後はcanaryのチェックに失敗した場合の__stack_chk_failくらいしかGOT overwriteできそうなものが無いのでEIPを取るのに困る。
fini_arrayを書き換えるとmain関数終了時に書き換えた場所に一回だけ飛ばせるので、それでEIPを取る。 ここで、main関数のstack canaryを積んだ後の部分(-①)にジャンプすると、canaryのチェックを必ず失敗させることができる(もともとcanaryをスタックに積んでいないので、それはそう)ので、そうして、次のFSBで__stack chk_failのGOTを書き換えて①にすれば何度でもFSBができるようになる。
最後にprintfのGOTを書き換えてsystemにすれば、次にprintfが呼ばれる時にこちらが入力した文字列をsystemに渡すことができる。今回はpltにsystemがあるのでそれを使えばOK
方針は一日目の夜には立っていたのだが、DoS攻撃に対する対策の為,出力が131072文字に制限されていたり(この情報は解いた後で出た)、三回目(printfのGOT書き換え)のペイロードが長いとgetnlineでセグフォになったり(意味不明)、つらいバグを踏み続けて時間が無限に溶けた。
手元で動くがサーバーで動かない場合のデバッグのテクが欲しい flag:TWCTF{51mpl3_FSB_r3wr173_4nyw4r3}
コードは以下。コード内でアドレス計算を一切行わないため、echo とかでも解ける(多分)

Super Express

keyは文字列ではなくpairの配列。(s_0, t_0), (s_1, t_1), ..., (s_n, t_n)として c_i+1 = s_i * c_i + t+i という漸化式で暗号化されている。
ただし mod 251 整理すると S * c_0 + T という形になるので、TMCTF{からS, Tの候補を絞れば良い

ESPer

RSAを実行するときに好きな変数の値を乱数で置き換えられる。
まず、乱数を使わなくても2と3をencryptすることでnは得られる decryptは普通にd乗を行うのではなく、mod pとmod qでそれぞれ計算して中国の余剰定理から値を生成していることに注目する。
つまりc^d mod pとc^d mod qを順に計算する ここで、c=1にしてm2を乱数にするとm - 1がpの倍数になるので、2個取得してgcdを得れば大体pが得られる。

Backpacker's cipher - easy mode

asciiなので入力の各文字は7bit目は必ず0であることに注目する。
これにより候補を絞ると、パスワードがかなり絞れる。
確か12文字ということと、更にそのうち何文字かが確定したはず。 この候補を列挙し復元して眺めると、TMCTF, Windowsとかの単語が入っていそうなことがわかる
こんな単語を何個か適当に選んで絞るとすぐに一意になる

rps-ng

初期テーブルは高々6^9通り。 これを全部持って、逐一ありえないものを絞っていく。すると40勝程度ならすぐに達成できる。

whiteout

適当に入力してOEISに突っ込むと[l, r]についてそれぞれ約数の総和を求めてそれのmaxを求めている事がわかる。 あまり大きな素因数を持ちそうになかったので、素因数を1~100の間の素数だけに限定して全探索したら解けた。

Lights out!

Lights Out本家はmod2の行列演算で解ける事が知られているので、今回もそのように考える。 上2行のボタンを押すか決めたら残りは全部一意なので、要するに辺数は2*n。 また、正しいかは下2行が全部白くなるかを見れば良い。要するに条件数は2*n。 後はこれを吐き出せば良い。

glance

見えないgifが与えられたらコマ毎に切り出して繋ぐ。 切り出すのにはgiam、繋ぐのは最強画像処理ライブラリDxLibを使った。