CODEGATE 2012 YUT CHALLENGE 予選に参加してみた。
久しぶりのCTFでした!超楽しかった!!
Bin100
Net100、200、300、400
Misc100、300
のWriteupを残しておきます。
Binary 100
やったー!Windowsバイナリだー!(
実行すると、何やら強制終了する。
このとき、"sxe42.tmp"というファイルが出来てる。
これも実行ファイル。
.NET製なので、Reflector等で逆コンパイルしてやると、コードが出てきます。
自分はVB.NET派なので、VB.NETのコードで見てやると、こんな感じ。
長いので抜粋。
Friend Class Program Private Shared Sub Main(ByVal args As String()) '... synthesizer.Speak("What is greater than god, more evil than the devil?") '... End Sub Private Shared Sub recognizer_SpeechRecognized(ByVal sender As Object, ByVal e As SpeechRecognizedEventArgs) '... If (e.get_Result.get_Text = "Yes") Then Program.str_cypher = (Program.str_cypher & "QA1f1/EqAOZktIz1RrwMPunDlqwww==") Program.DoHibernation End If '... End Sub Private Shared Sub DoHibernation() Dim now As DateTime = DateTime.Now If (now.Hour = 8) Then Program.str_input = (Program.str_input & "!") If (Program.str_input.Length = now.Hour) Then Dim crypt As New WATCrypt(Program.str_input) Console.WriteLine(crypt.Decrypt(Program.str_cypher)) End If Else Console.WriteLine("This isn't the time yet.") End If End Sub ' Fields Private Shared current As RecognitionState = RecognitionState.None Private Const RecognizerId As String = "SR_MS_en-US_TELE_11.0" Private Shared str_cypher As String = "BM3aZTvv5iQAhK95EFLuz4pta" Private Shared str_input As String End Class Friend Class WATCrypt '... Public Function Decrypt(ByVal p_data As String) As String '... End Class
Speakで、"What is greater than god, more evil than the devil?" と聞かれてるので、
ぐぐってみる。すると、答えは "Nothing!" だと分かる。
よって、鍵 "Nothing!" を使ってDecryptすればよい。
プログラムが動いてくれないので、適当に移植して、Decryptした。
Answer: Nuno! Congratulations on your wedding!
Network 100
パケットファイル。データを見ると、PKが見つかり、ZIPと分かる。
が、ところどころ壊れてるので、03 04とか 01 02とか PK とかで検索しながら、修復する。
正常なZIPになったところで、解凍作業。
パスワードがかかっているが、問題文をよく読んでいれば、すぐ分かる。
The password of disclosure document is very weakness and based on Time, can be found easily.
パスワードは時間らしいので、とりあえず数字でブルートフォース。すぐにヒット。
pass: 19841128
そしてこれは同時に、以下のCryptoのKeyになっている。
Msg = "ThisIsNotARealEncryption!SeemToEncoding" Key = 0x20120224 (if date format is 2012/02/24 00:01:01) Cryto = C(M) = Msg * Key = 0xa92fd3a82cb4eb2ad323d795322c34f2d809f78
zipの中には、keyが入っているので、このkeyをDecryptする。
irb(main):002:0> v / 0x19841128 => 620138491573466333567436341452945961 irb(main):003:0> v % 0x19841128 => 0 irb(main):004:0> ans = v / 0x19841128 => 620138491573466333567436341452945961 irb(main):012:0> ans.to_s(16) => "776f30306f735230634b696e473a29" irb(main):013:0> ans_h = ans.to_s(16) => "776f30306f735230634b696e473a29" irb(main):014:0> ansarr = "77 6f 30 30 6f 73 52 30 63 4b 69 6e 47 3a 29".split(" ") => ["77", "6f", "30", "30", "6f", "73", "52", "30", "63", "4b", "69", "6e", "47", "3a", "29"] irb(main):018:0> kotae = "" => "" irb(main):019:0> ansarr.each{ |val| irb(main):020:1* kotae = kotae + val.hex.chr irb(main):021:1> } => ["77", "6f", "30", "30", "6f", "73", "52", "30", "63", "4b", "69", "6e", "47", "3a", "29"] irb(main):022:0> kotae => "wo00osR0cKinG:)"
Network 200
めっちゃ大量のパケット。NetworkMinerを使って開く。
ついでにWiresharkでも開く。
DoS攻撃らしいので、有名どころのSYN Floodとか探してみる。すぐ見つかる。
TOP4 Targetを見つけろとのことなので、NetworkMinerで、受信パケット数でHostをソートする。
(このソートにめっちゃ時間がかかった・・・。)
ソートが終わったら、一番上のIPから順番にチェックしていく。
Wiresharkのフィルタで、"ip.dst ==
攻撃とおぼしきデータを、順番に見つけていく。
攻撃っぽいデータは、大体みればわかる。
結果はこんな感じ。
TOP1 Singapore n 111.221.70.11 Send 0 Recv 52620 UNKNOWN SYN Flood TOP2 United Kingdom o 109.123.118.42 Send 5325 Recv 2960 WINDOWS F5 Attack TOP3 United States n 199.7.48.190 Send 304 Recv 311 UNKNOWN BIG DATA TOP4 United States e 66.150.14.48 Send 50 Recv 99 LINUX MALFORMED PACKET? Answer: none_111.221.70.11_109.123.118.42_199.7.48.190_66.150.14.48
SYN Flood攻撃の参考ページ
Network 300
これ結構大変だった!
UDPパケットなので、データを解析していく。
とりあえず、受信データ量から、データが転送された側は、どちらかすぐ分かる。
最後の方のデータに、"test2.swf"という文字列が見えるので、Flashファイルだろうと予想がつく。
だらだら見てると、データの先頭0x34バイトはあまり変化がないことにも気づく。
その上で最初のパケットを見ると、"7z"から始まっているので、7zファイルだと分かる。
後は、データヘッダを削りながらデータグラムを結合して1つのファイルにする。
(ここでやたら時間を食った気がする・・・。)
うまい方法が思い浮かばなかったので、
1. Wireshark で plain text としてパケットを保存。
2. 余分な情報をカット(Ruby)
3. バイナリデータに変換(Ruby)
4. 手動で最初の方のヘッダをいくらか削除
5. 残りのヘッダを削除(Ruby)
ヘッダの削除でやたらと手間取ってしまった。力量不足を痛感する。。。
後は、できあがった7zファイルを解凍する。
test2.swf が出てくるので、再生してみる。
The answer is ipv6.dst !!
と言われる。はて、このパケットはipv4なんだけど。
と思ってデータヘッダをよく見ると、送信元と送信先のipv6が書かれてる。
fe 80 00 00 00 00 00 00 00 00 00 00 c0 a8 88 88 fe 80 00 00 00 00 00 00 00 00 00 00 c0 a8 88 02
後は、いろんな形で試すだけ。なんだけど。
Answer : strupr(md5(Hint in the leaked data | Hacked internal system address)) ('|'is just a character)
これ、"|"の左右にスペースが入ってる。ハッシュ化するときにもスペースがいるのかどうか分からなくて、
メールで聞いてみた。そしたら、"No."と言われた。スペースは要らないらしい。
"Hint in the leaked data"は、ipv6.dstなのか、dstのipv6アドレスなのか分からない。両方試す。
問題は、internal system address。ipv4なのかipv6なのか分からないけど、まあipv6なんだろう。
(といいつつ、ipv4もしっかり試したけど。)
fe80::c0a8:8802|192.168.136.136 fe80::c0a8:8888|192.168.136.136 FE80::C0A8:8802|192.168.136.136 FE80::C0A8:8888|192.168.136.136 ipv6.dst|fe80::c0a8:8802 ipv6.dst|fe80::c0a8:8888 ←BINGO answer: 6642E5A831032D2CF852C66024D9C1F1
追記
murachue氏に、「Decode as→network→IPv6でスッキリ」と教えてもらいました。
これはスッキリ・・・!
Network 400
なんか大量にSQLインジェクションを行ってるパケットを渡される。うわ、これ全部読むの?w
と思いながらも、とりあえずとりかかる。
なんとかインジェクションリストを取りだせないかなー、あわよくば成功したかどうかも知りたい。
パケットを眺めてると、どうやらインジェクションしたSQLが正常に実行されると、
だけが返るみたい。
そこで、こんな風にして抜き出した。
strings 80924D4296FCBE81EA5F09CF60542AE7 | grep -i -E "(php\?name=|<br>)" > injections
更に、%20とか%28とか諸々をsedで置換して、見やすくする。
後はひたすら解析。
schema count: 2 schema1: information_schema schema2: cdgate [cdgate] table count: 1 table1: member [cdgate.member] column count: 6 column1: name column2: id column3: email column4: sex column5: level column6: passwd
この辺で手動解析するのがめんどくさくなった。
なので、適当にツールを作成して、解析を自動化。
残りは英字ばかりだったので、さほど苦労せずに自動化できた。
そして解析データ。
mail : monitor@cdgate.xxx id : 08b5411f848a2581a41672a759c87380 level : 2 name : monitor passwd : *1763CA06A6BF4E96A671D674E855043A9C7886B2 sex : f mail : apple@cdgate.xxx id : apple level : 3 name : apple passwd : *C5404E97FF933A91C48743E0C4063B2774F052DD sex : m mail : music@cdgate.xxx id : music level : 6 name : music passwd : *DBA29A581E9689455787B273C91D77F03D7FAD5B sex : m mail : computer@cdgate.xxx id : computer level : 2 name : computer passwd : *8E4ADF66627261AC0DE1733F55C7A0B72EC113FB sex : f mail : com@cdgate.xxx id : com level : 3 name : com passwd : *FDDA9468184E298A054803261A4753FF4657E889 sex : f mail : lyco@cdgate.xxx id : lynco level : 4 name : *EEFD19E63FA33259154630DE24A2B17772FAC630 passwd : *0ECBFBFE8116C7612A537E558FB7BE1293576B78 sex : f mail : mouse@cdgate.xxx id : mouse level : 4 name : *87A5750BB01F1E52060CF8EC90FB1344B1D413AA passwd : *6FF638106693EF27772523B0D5C9BFAF4DD292F1 sex : m mail : root@cdgate.xxx id : root level : 6 name : root passwd : *300102BEB9E4DABEB8BD60BB9BB6686A6272C787 sex : f mail : desktop@cdgate.xxx id : desktop level : 1 name : desktop passwd : *DDD9B83818DB7B634C88AD49396F54BD0DE31677 sex : f mail : www@cdgate.xxx id : 4eae35f1b35977a00ebd8086c259d4c9 level : 8 name : www passwd : *3E8563E916A490A13918AF7385B8FF865C221039 sex : f mail : notebook@cdgate.xxx id : notebook level : 8 name : fb5d1b4a2312e239652b13a24ed9a74f passwd : *18DF7FA3EE218ACB28E69AF1D643091052A95887 sex : m
大量にある。levelって権限かなーと思うんだけど、高い方がいいのか低い方がいいのか分からない。
とりあえず全部試すことにする。
パスワードはdecodeしないといけないけど、DBに入ってるこれはハッシュ値。
先日、後輩のid:hi_igu (通称いぐにゃん)に教えてもらったOnlineHashCrack.comが早速活躍。
levelが一番低い、desktop のパスワードがデコードできたので、試したら、通った。OK。
cdgate|member|etagcd answer: AB6FCA7FFC88710CFBC37D5DF9A25F3F
Misc 100
ROT13か転置かなーと思いながら、統計取って転置してみたけど、だめぽ。でも、どう見ても転置だよなあ。
と、ファイルをいろいろ漁ってると、keyboard layoutみたいなファイルを発見。
ググりながら調べてみると、キーボードのレイアウトを編集するファイルっぽい。名前まんまだな。
a -> d とか e -> j とか、そんなノリ。でも、よく分からない数字が入ってるのもある。
これはどうやら、下の方に書いてあるらしい。あった。なるほど。デコード。終わり。
cipher = "Az hrb eix mcc gyam mcxgixec rokaxioaqh hrb mrqpck gyam lbamgarx oatygqh Erxtoigbqigarx Gidc hrbg gasc gr koaxd erzzcc zro i jyaqc Kr hrb ocqh rx Ockubqq ro Yrg man? Gyc ixmjco am dccqihrbgm" p cipher dec = cipher for i in 0 .. dec.length c = dec[i,1].downcase dec[i,1] = "m" if c == "s" dec[i,1] = "k" if c == "d" dec[i,1] = "z" if c == "f" dec[i,1] = "t" if c == "g" dec[i,1] = "f" if c == "z" dec[i,1] = "p" if c == "v" dec[i,1] = "l" if c == "q" dec[i,1] = "j" if c == "w" dec[i,1] = "c" if c == "e" dec[i,1] = "h" if c == "y" dec[i,1] = "g" if c == "t" dec[i,1] = "r" if c == "o" dec[i,1] = "b" if c == "u" dec[i,1] = "v" if c == "p" dec[i,1] = "q" if c == "l" dec[i,1] = "w" if c == "j" dec[i,1] = "d" if c == "k" dec[i,1] = "x" if c == "n" dec[i,1] = "s" if c == "m" dec[i,1] = "a" if c == "i" dec[i,1] = "i" if c == "a" dec[i,1] = "y" if c == "h" dec[i,1] = "n" if c == "x" dec[i,1] = "e" if c == "c" dec[i,1] = "u" if c == "b" dec[i,1] = "o" if c == "r" end p dec exit()
Misc 300 (4つ目のヤツ)
HTMLソースを見てると、最下部に変なコードが。あ、ホワイトスペースか。
と思いきや、ホワイトスペースのインタプリタ落としてきて試そうとしても、うまくいかない。
素直に、jsファイルを見てみる。あ、これまた最下部にpackされたコードがある。
適当にunpackしてみた。なんかevalしてる。中身見てみよう。こんな感じ。
if(new Date().getTime()>1330268400000){ var dummya = '1'; var dummyb = '1'; var dummyv = '1'; var dummyc = '1'; var dummys = '1'; var dummyae = '1'; var dummyasefa = '1'; var dummeya = '1'; var dummya = '1'; var dum3mya = '1'; var dumm54ya = '1'; var dumm3ya = '1'; var dum1mya = '1'; var p = 'YTK4YPT1YK48PTK48TK34PTYK6TDKT5P2KT73TKPY4TBTK3TT4YKT4ETK4YTP7K4T6KT30TKYP7T2KYT33TKP7TY6KTYP33TKPY7PT2YT'; p = p.replace(/T/g,'').replace(/P/g,'').replace(/Y/g,'').replace(/K/g,'%'); var authkey = unescape(p); }
なるほど、getTimeの条件を潰してauthkeyをalertで表示してみよう。出た。終わり。
answer: AHH4mRsK4NGF0r3v3r
Misc 100(5つ目のヤツ)
RDCVGF_YGBNJU_TGBNM_YGBNJU_TGBNM_TGBNM_YGBNJU_TGBNM
せっかくなので、友人に教えて、一緒に悩んでみた。分からん。
友人は先に寝てしまったので、一人で考えてみる。うーんうーん。
文字を回転させてみたり、ペイントで塗りつぶしたり、ROTしてみたり。
なんか、1フレーズが1つの文字に対応してそうな気はする。
何かの英単語だろうか。うーん。分からん。
英語だから、かな打ちじゃないだろうし・・・と思い、キーボードに目をやる。ん?ひらめく。分かる。終わり。
(答えは書かないので、考えてみてください。)
問題の感想
- Network がパケットぺろぺろちゅっちゅな問題ばかりで面白かった。
- Misc の5つ目は凄く好き。
- Forensics 100 難しすぎじゃね?(非常に悔しい。)
- Volnerab 100 も解けなかった。うーん、ブラインドインジェクションしか思い浮かばず。
- Binary にもっと時間割いてもよかったかも。せっかくWindowsバイナリだったのに。。
- Network が 400 まで解けたのは嬉しい。
CODEGATE自体の感想
- 質問メールの対応がすっごくあっさりしてた。(No.だけ。。署名も挨拶とかも一切なし。そんなもんなのかな。)
- sutegoma2 相変わらず凄いなあ、と思いながら、オフライン参加しちゃえばよかったなーという思いも。
- とはいえ、一人で参加してないと、今回ほど頑張れなかった気がする。
- 問題があまりひねくれてなくて、純粋なハッキング大会という印象。
- 参加して、問題をいろいろ考えながら解くだけで、かなりスキルアップしたことを実感できる。
- sutegoma2 が、一時はランキングから消えてたけど、後から上位に食いこんでいくところを見ていると、自分も頑張ろうと思える。
- 来年もぜひ参加したい。それぐらい楽しい。
自分は Aquarium として一人チームで参加してました。
個人的には、結構満足な感じ。苦手分野も凄くはっきりしたので、勉強していかなきゃ。