CyberRebeat CTF Write-up 兼感想文

 概要

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!とあるので、公式アカウントを見た。あった。

ここまでは出先だったので、スマホで解いた。

ここでエカスドクィナにPPCを全て解かれてしまい、PPC担当だった僕は意気消沈していた。そこで見るからに作業ゲーっぽいCrosswordをやることにした。

Crossword

  • genre : Trivia
  • difficulty : 100
  • point : 203pts
  • solved : 71

f:id:keymoon:20180909011447p:plain

ググり力が試される問題だと思った。ひたすらググってペイントで頑張った。よくよく見るとCyberRevertと誤字してしまっている。つらい(Iに入る”E”をエスパーできたのが個人的に嬉しいポイント)

 追記:RE:LIFEと書いていますが、これもRe:LieFの誤記です。作品名を間違えるのは本当に失礼ですね、申し訳ないです…

Alpha

  • genre : Stegano
  • difficulty : 100
  • point : 218pts
  • solved : 65

画像でAlphaと言ったらまぁアルファ値だろうと思い、C#で画像を読み込む方法を調べる。

分かったので実装し、初めの方を回すと大体アルファが253だなぁという感想を持った。そこで場合分けしてピクセルを文字1つとしてテキストに出力し、いい感じで見てあげると文字が見えた。

gist.github.com

f:id:keymoon:20180909013652p:plain

ここで漁師もこの問題を解いていたらしく、フラグのテキストファイルを開いた瞬間に「解けたよw」って言われた。おもしろかった。(彼はGimpかなにかを使ったらしく、それのほうがスマートだなぁと思った)

f:id:keymoon:20180909013835p:plain

Last 5 boxes

  • genre : Stegano
  • difficulty : 200
  • point : 414pts
  • solved : 14

MP4の知識はあったので、まぁ最後のBoxを見たらヒントが書いてあるのかなぁと思って見た。そうすると怪しいのが5個本当にあったので、1つ目を見た。PNGシグネチャが見えたので、ファイルを繋げる系かなぁと思った。シグネチャがズレていることから考えるに、おそらくBoxにはオフセットがあるだろうな、と思った

大体同じ24byteのオフセットかな、と思ってオフセットを除いたファイルを5個作り、それをつなげて祈りながら拡張子を変えたらflagが出た。

f:id:keymoon:20180909014505p:plain

f:id:keymoon:20180909014631p:plainf:id:keymoon:20180909014826p:plain

Opening Movie

  • genre : Misc
  • difficulty : 100
  • point : 377pts
  • solved : 21

開始すぐに目を通したときは、sourceにwasmが見えたのでpwnかぁと思ってアセンブラ担当のぞへに投げようかと思っていた。しかし、よく見てみるとdllが落ちてきている。どうやらC#等をブラウザ上で実行できるライブラリのようだ。

ILSpyに入れていろいろ見ていると、300回以上のときにFlagを描画する機能がついた関数を見つけた(BuildRenderTree())。これはframeを生成し、そのsrcに変数txtを指定する、というソースのようだ。txtは文字列をmd5でハッシュ化したものなので、同様にハッシュ化してあげてそこにアクセスすれば終了。

f:id:keymoon:20180909015327p:plain

f:id:keymoon:20180909015719p:plain

Signature

  • genre : Crypto
  • difficulty : 200
  • point : 419pts
  • solved : 13

ユーザー名Kanaとしてログインさせる問題。guestのログイン枠が与えられている。

始めはソースを見逃していた。それで10分位溶かしてしまった。単純にsaltつきのmd5とログイン情報を一致させているようで、どこにもWeb的な脆弱性を見つけることはできなかった。(Cryptoだしそれはそう)

gist.github.com

 

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はシェルスクリプトのアウトプット。ファイルはソースコードの下に添付した。

gist.github.com

data-signature.txt - Pastebin.com

感想

ラストの問題を通して全完したので喜びはとても大きかったです。

チーム全員のバランスがよく、分散して問題が解けていたのでやっていて楽しかったです。全く自分がわからない分野(Cryptoやrev)をチームメイトが通しているのを見ると「天才だなぁ」という気持ちになりました。また、最後の問題は総力戦みたいな感じがあって、チーム戦特有の「相手の天才考察の上に考察を構築する気持ちよさ」みたいなものがあり、ゾクゾクしました。

今回はILやMP4と言った自分の知識範囲のものが偶然複数出てくれたので個人で満足の行く成績が残せましたが、PPCTCPコネクションで苦戦したりなどと基礎部分ができていないという印象が残りました。体系的に過去問を解くなどの勉強をしていきたいです。

チームメイトのWriteUpは以下↓

kobaryo222912.hatenablog.com

ecasd-qina.hatenablog.com

CyberRebeatCTFの参戦記とwriteup

SuperCon2018参加記~本選篇~

はじめに

SuperConってなに?とかは以前の記事で説明しました。

keymoon.hatenablog.com

結果

落ちました。

感想

予選篇とか書いてるけど本選なかったらクソザコですよね、まあ通ると信じてこうしましたが

SuperCon2018参加記~予選篇~ - 雑記

しょぼすぎる。ひゃ

通った人はおめでとうございます!落ちた人の分まで本選で戦ってきてください。

えーなんか、Twitterは割と荒れてましたね。(去年優勝のWA_TLEさんも落ちてたり、前回二位のチームメイトを擁する僕たちも落ちてたり。)

僕はそんなに文句を言うつもりはないので、適当に燃えてたところを纏めてみたいと思います。

審査が遅延した!地震はどうせ言い訳だろ!

 

こういうことなので普通に地震のせいでしょう。

10ミリ秒単位での改善は本質的なのか?

これは思わないでもないですが、細かい枝刈りをさせるのが出題者の意図だったのではないか、要するにこれが本質だったのでは?と感じます。

ジャッジが不透明!

テストケースもそのうち公開される気がします。(そのときに明らかに早い/遅い等があったら別ですが。)

境界外参照が発生しうるコードが通っている。

単純に非本質的なところで落としたくはないという意図だった気がします。知らんけど

サイレントお祈り

予選落ちメールは同時に送ってほしかったです(一日経っても送られてきていない気がする)

なんでこんなまとめしたの?

精神を安定させたいからです

さいごに

来年は真面目に取り組むぞい

 

SuperCon2018参加記~予選篇~

はじめに

 SuperCon2018の予選に出ました。僕は提出コードにほぼ手を加えてないので実質マスコットですが、キーボードが打てるマスコット*1としての仕事はしたのでここに記します。

ところで

予選篇とか書いてるけど本選なかったらクソザコですよね、まあ通ると信じてこうしましたが

6/20 更新しました

keymoon.hatenablog.com

SuperConってなんやねん

 高校生がチームで参加できるプログラミングコンテストです。予選、本選ともに長期間*2で一問を解きます。スコアで競う場合もありますが、今回の予選は特定の解を出すための実行時間で競います。

 チームは2,3人で、本選出場者は関東・関西でそれぞれ10チームずつです。

 本戦だとスーパーコンピューターを使って問題を解きますが、予選は普通のパソコンで解ける程度の問題です。

問題概要(PDF)

 予選に関係する1級認定問題のみ説明します。*3

 端的にいうと、

格子上で(0,0)を始点とする閉路のうち、交差しない(同じ点は1度しか通らない)かつ特定の点を通らないような閉路の総数を求めなさい

という問題です。*4(分からなかったらPDFを見るなりすると雰囲気が掴めます)

僕がしたこと(概要)

ひたすらテストした 以上。*5

詳細

C++が書けないので、C#でexeを実行してランダムにテストケースを実行させ、ベンチマークを取ったり愚直解と比較したりするテストを書きました。ログはJsonで吐き出して解析しやすくしました*6

愚直解ですが「絶対に間違いでないと保証されている解」が欲しいとのことで最低限の枝刈りを*7行ったDFS*8で解を出しました

最高320万くらいで、6分くらいで終わります(平均3分程度。遅い)

失敗一覧

人の失敗って見てて面白いですよね。教訓にしてください

  • めんどくさがり性のせいでtesterを書くのが1日遅れた*9
  • コンパイルオプションの-Oを-oとしていてコンパイルオプションがかかっていなくて、遅い奴で動かしていた*10
  • パフォーマンスを比較する時に別実行ファイルを比較しているつもりでいたら同じ実行ファイルを比較していた*11
  • Seedからの復元性がなかった*12
  • そもそもこれを書いてる時にまだ提出が済んでいない。

経過

5/30

SuperCon、組めたら組もうね~ってKMCodeと話した

5/31

部でいろいろ聞いて回ったけど確定した1チームしか観測できなかった

~~(僕は)虚無~~

6/10

SuperConに出るっぽい流れになったので取り組むことに。

いきなり1000msが来て、その少し後に600msのソースが降ってくる。

僕がテスターを作る感じになったけど、サボる(クズ)

6/11

テスター今日中にできる?って5時くらいに聞かれる。焦って適当に書いた

6/12

一晩寝かせて400ケースくらい調べたけどWAが出なかった。

いろいろと改善が降ってきて試したが、漏れ/被りがちらほら出て怖かったのでやめた(1/1500くらい)。

オーバーフローに気がつく。ソースコードへの唯一の貢献!

テストケースをいっぱい錬成して試すことに。テストケースはハッシュ値から再生成ができるようにする

6/13

解析したデータをスプレッドシートとかに起こした

最適化オプションの指定漏れに気がつく。死

指定し直して適当に解析したら400ms程度を出す。このまま提出用のコードを書いて後はテストするだけ

あれ?????テストケースの再生成できなくない?????→テストケース5000個くらいが無に帰す

引数自体を愚直に保存すればいいのに。って思ってそうする

チーム名を適当に考えるも何も思いつかない*13

ここらへんで英字8字縛りに気がつく→何も思い浮かばずに死

6/14

パソコンの自動スリープをオフにして持ち運び中もテストケースを錬成できるようにした。ThinkPadのぬくもりを感じて「これが彼女か…」ってなった。*14

昼休み(12:20頃)に提出準備*15。その頃にテストケースが4000個くらい生成できたので並行してテストする。

WAが0だったので満を持して提出。

テスターを公開すればコンテスト後に情報が迅速に集まる可能性があるな~って思ってテスターを改修。

あとテストケースが10000個くらいあると嬉しいかもしれないと思ったのでマイニングを継続

6/15

334のがしたけどテスターの改修が終わった ガバガバだけど動く

みんなの報告を全裸待機 それだけ*16

感想

つかれた。僕がポンコツで相方さんに迷惑がかかるので割と申し訳のなさみりてぃが高い。

なんかね、本選に行けたらいいねって感じです。*17*18

ということで

なんか最後の方にも書いたけどテスターを公開します。情報が欲しいです*19

一応コマンドラインでヘルプとかは完結するようにしましたが、readmeを読むと使い方がより詳細に書いてます。

ダウンロードリンクは以下です*20

ダウンロード

*1:SuperCon、マスコットとしてついていくとは言ったけどキーボードが打てるマスコットとしての作業程度はする()

*2:予選は15日くらい、長い。

*3:肩慣らしみたいなのがついてますが、それはどうでもいいです

*4:自己回避ループ (Self-Avoiding Loop、略して SAL) と呼ぶらしい

*5:というとちょっと嘘で、一箇所オーバーフローを見つけた えへへ

*6:区切りのカンマを忘れて死んだりとかした

*7:マンハッタン距離が残りターン数より少なければ切る,スタート地点の近傍が埋まったら切る

*8:いつもBFSなのでなにげに書くのは初めて

*9:謝罪しか無いです。懺悔of懺悔

*10:バカすぎる

*11:差が出ないしWAがも出ないしで喜んでいたら死んだ

*12:後述しますが、クソ致命的だった

*13:候補案:Tourist抗酸化物質国務長官,スーパー皆伝68

*14:電車で発熱するPCが入ったケースを抱いて壁にもたれていた時に、PCケースとお布団の類似性を見出した。

*15:準備室のパソコンがポンコツでむっちゃ固まった。

*16:Keidarooさんが提出できるかが割とヒヤヒヤでした

*17:正直どんくらいのタイムなのか、高速化の方針があってるかとかが無茶苦茶不安でマジで不安です

*18:というか恣意的に落とすコーナーケースとかをあまり検討しなかったので結構怖い

*19:解析したら是非、というかTwitterでつぶやいてくれ~~~~

*20:ソースは本選で使えそうな気がするので一応非公開です。たった100行くらいだけど。