概要
2018年9月8,9日にかけて開催された、CyberRebeatCTF2018のWriteUp 兼 感想文です。僕の所属しているチーム「生活習慣崩壊ズ(SeikatsuKowareru)」は10時間程度で5チーム目に全完し、同率一位となりました。僕は6問通しましたが、1問解けたのに通せなかったものや3問のなぞなぞ枠を鑑みて実質4完かなぁという気がします。
ということで、僕が解けた6+1問について書いていきます。
Monero
- genre : Trivia
- difficulty : 10
- point : 116pts
- solved : 127
通貨名は定かではなかったが、日本で、自身のウェブサイト上にこのソフトを設置した何人かのユーザが逮捕されている。とあったのでまぁcoinhiveだろうなと思った。あっていた。
Tweet
- genre : Recon
- difficulty : 10
- point : 113pts
- solved : 130
Let's check our official twitter account!とあるので、公式アカウントを見た。あった。
CRCTF{CyberRebeatCTF_has_started!}
— CyberRebeat (@CyberRebeat) September 8, 2018
ここまでは出先だったので、スマホで解いた。
ここでエカスドクィナにPPCを全て解かれてしまい、PPC担当だった僕は意気消沈していた。そこで見るからに作業ゲーっぽいCrosswordをやることにした。
Crossword
- genre : Trivia
- difficulty : 100
- point : 203pts
- solved : 71
ググり力が試される問題だと思った。ひたすらググってペイントで頑張った。よくよく見るとCyberRevertと誤字してしまっている。つらい(Iに入る”E”をエスパーできたのが個人的に嬉しいポイント)
追記:RE:LIFEと書いていますが、これもRe:LieFの誤記です。作品名を間違えるのは本当に失礼ですね、申し訳ないです…
Alpha
- genre : Stegano
- difficulty : 100
- point : 218pts
- solved : 65
画像でAlphaと言ったらまぁアルファ値だろうと思い、C#で画像を読み込む方法を調べる。
分かったので実装し、初めの方を回すと大体アルファが253だなぁという感想を持った。そこで場合分けしてピクセルを文字1つとしてテキストに出力し、いい感じで見てあげると文字が見えた。
ここで漁師もこの問題を解いていたらしく、フラグのテキストファイルを開いた瞬間に「解けたよw」って言われた。おもしろかった。(彼はGimpかなにかを使ったらしく、それのほうがスマートだなぁと思った)
Last 5 boxes
- genre : Stegano
- difficulty : 200
- point : 414pts
- solved : 14
MP4の知識はあったので、まぁ最後のBoxを見たらヒントが書いてあるのかなぁと思って見た。そうすると怪しいのが5個本当にあったので、1つ目を見た。PNGのシグネチャが見えたので、ファイルを繋げる系かなぁと思った。シグネチャがズレていることから考えるに、おそらくBoxにはオフセットがあるだろうな、と思った
大体同じ24byteのオフセットかな、と思ってオフセットを除いたファイルを5個作り、それをつなげて祈りながら拡張子を変えたらflagが出た。
Opening Movie
- genre : Misc
- difficulty : 100
- point : 377pts
- solved : 21
開始すぐに目を通したときは、sourceにwasmが見えたのでpwnかぁと思ってアセンブラ担当のぞへに投げようかと思っていた。しかし、よく見てみるとdllが落ちてきている。どうやらC#等をブラウザ上で実行できるライブラリのようだ。
ILSpyに入れていろいろ見ていると、300回以上のときにFlagを描画する機能がついた関数を見つけた(BuildRenderTree())。これはframeを生成し、そのsrcに変数txtを指定する、というソースのようだ。txtは文字列をmd5でハッシュ化したものなので、同様にハッシュ化してあげてそこにアクセスすれば終了。
Signature
- genre : Crypto
- difficulty : 200
- point : 419pts
- solved : 13
ユーザー名Kanaとしてログインさせる問題。guestのログイン枠が与えられている。
始めはソースを見逃していた。それで10分位溶かしてしまった。単純にsaltつきのmd5とログイン情報を一致させているようで、どこにもWeb的な脆弱性を見つけることはできなかった。(Cryptoだしそれはそう)
Cookieのlogged_inが0以外であれば受け付けるようなので、そこを弄ってハッシュを合わせるという検討はついたが、それ以上は何もわからなかった。
Cryptoしそうなところといえばmd5の脆弱性ということで、漁師が伸張攻撃なるものを見つけてきた(天才)。kを未知変数(この場合はSalt)、mを既知としたときに、md5(k+m),|k|(kの長さ)が分かっている場合、任意のaに対してmd5(k+m+b+a)が分かるbがあるという。
この後の文章で謎の英字一文字が出てきた場合は、上の伸張攻撃の説明に出てくるものだと思って欲しい。
kの長さは分かっていないが、今回はSaltがFlagと一緒という制約もあり、高々50以下なので余裕で探索ができる。
なので、bの部分をlogged_inの後部につけ、aは&id=Kanaにするのかなぁと思った。
logged_in=0となる非ログイン状態でもHashが与えられていることに気が付き、mをlogged_in=0として、logged_in=0{b}&id=Kanaとすればうまくいきそう、と思った、しかしなぜか上手く行かなかった。なぜ上手く行かなかったかはわからない…。
途方にくれているうちに、えかすどがlogged_in=1&id=guestをmにすればいいのでは?と提案してきた。後から&id=KanaとするとidはKanaになる上、guestログインでのHashは与えられているので行けると思った。しかし、HashはCookieからそのまま取っているわけではなく、"logged_in={$parse["logged_in"]}&id={$parse["id"]}"と整形した後の文字列から取っていた。そのため、愚直にlogged_in=1&id=guest&id=Kanaを送るだけでは上手くいかない。
少し工夫をして、logged_inの値を1&id=guestとするといい感じで行きそうだと感じる。なので1&id=guestをURLエンコードし、送信cookieはlogged_in=1%26id%3dguestとした。
しかしどうにも上手くいかないのでいろいろ考えてみたところ、Cookieを受け取るところとparse_strの部分で二回URLエンコードに対するデコードが掛かっているよう。なので、エンコードされた%に対して更にエンコードをした。それによって、ついに通すことができた。
伸張攻撃を行うのに使ったツールはHashPumpというツール。以下のソースはHashPumpでハッシュとbを生成するシェルスクリプト、それを鯖に投げてログインを確認するC#プログラムに分かれている。C#で参照されているdata-signature.txtはシェルスクリプトのアウトプット。ファイルはソースコードの下に添付した。
data-signature.txt - Pastebin.com
感想
ラストの問題を通して全完したので喜びはとても大きかったです。
チーム全員のバランスがよく、分散して問題が解けていたのでやっていて楽しかったです。全く自分がわからない分野(Cryptoやrev)をチームメイトが通しているのを見ると「天才だなぁ」という気持ちになりました。また、最後の問題は総力戦みたいな感じがあって、チーム戦特有の「相手の天才考察の上に考察を構築する気持ちよさ」みたいなものがあり、ゾクゾクしました。
今回はILやMP4と言った自分の知識範囲のものが偶然複数出てくれたので個人で満足の行く成績が残せましたが、PPCのTCPコネクションで苦戦したりなどと基礎部分ができていないという印象が残りました。体系的に過去問を解くなどの勉強をしていきたいです。
チームメイトのWriteUpは以下↓