School CTF Spring 2015 writeup
School CTF Spring 2015に参加しました。
14問解いて3050ptの6位(Non-School Teamsでの順位)でした(`・ω・´)
学生向けということもあり、さくさく解ける難易度でした(*´ω`*)
Affine Cipher(crypto:200pt)
出題当初は説明がよくわからない感じだったが、途中でアフィン暗号らしい問題に変更された。
対応表を作って終了。
alphabet = "abcdefghijklmnopqrstuvwxyz_" dictionary = {} alphabet.each_char{|c| dictionary[alphabet[(alphabet.index(c) * 4 + 15) % alphabet.length]] = c } puts "ifpmluglesecdlqp_rclfrseljpkq".chars.map{|c| dictionary[c]}.join # => "flag_is_every_haxor_love_math"
FLAG:every_haxor_love_math
Super Digest 4(crypto:400pt)
class Hasher @@sd4_iv = 0 @@sd4_block_size = 4 @@sd4_alphabet = "abcdefghijklmnopqrstuvwxyz" def sd4(line) special_value = @@sd4_iv if line.size % @@sd4_block_size != 0 line+="x"*(@@sd4_block_size - line.size % @@sd4_block_size) end (0...line.size).step(@@sd4_block_size) do |i| current_block = line[i..i+@@sd4_block_size-1].bytes special_value = sd4_round(special_value, current_block) end return special_value end def sd4_round(special_value, current_block) sum = current_block.inject(0){ |res, elem| res+=elem } sum += special_value return sum end end
文字数が4の倍数になるように末尾に"x"をパディングした後、各文字のASCIIコードを合計したものをハッシュ値としている。
1ステージのみで時間制限もなく、solver書くのもめんどくさかったので手計算で解いた。
FLAG:sometimes_i_think_that_super_digest_is_not_so_super
Hidden file(forensics:200pt)
zipファイルの中には"F", "L", "A", "G", "I", "S"と1文字ずつ描かれた画像ファイルとThumbs.dbが入っている。
I deleted my pass, so dont try to hack me, dudes :d
とあり、ファイルシステム上は削除されていてもThumbs.dbの中に残っているような気がしたので、Thumbs.dbを覗けるツールを探してきて覗いたところ、
zipに入っていなかった画像ファイルのサムネイルがいっぱいでてきた。
FLAG:XP_WAS_SO_SWEET_FOR_HACKERS
Agreement by default(joy:100pt)
joyって何……?
"Where does a wise man hide a leaf? In the forest."
というヒントと共に謎のインストーラが渡される。
文字化けが激しいという以外は普通のインストーラと変わらないが、使用許諾の同意の後にインストールキーの入力を求められた。
インストールキーをクラックする案件? と思ったが、ヒントでピンときて使用許諾をよく見たところ、文中にフラグが紛れ込んでいるのを発見。
FLAG:NoB0dy_Re@Ds_Agr33m3nt
Weird selfie(joy:100pt)
おっさんの写真が渡され、写真を撮った人物を答える問題。
こいつ誰やねん……とGoogle画像検索にかけたところ、Kevin Mitnick氏の情報が出てきた。
すごい人らしい(小並感)
FLAG:kevin_mitnick
Old school hacking(joy:200pt)
.NETで作られたマインスイーパ。
ILSpyで見たところ、フラグ生成処理(文字列定数をくっつけるだけだが……)があった。
FLAG:Game_Maker_Not_For_Serious_Programmers
Tricky authorization(networks:200pt)
pcapファイル内にあったやりとりを再現したらフラグが返ってきた。
$ nc sibears.ru 11811 >>> R U redi keeds? > Aye Eye pactain CORRECT! >>> I cant here U! > cleen ur eARs 0ld f4rt! CORRECT! >>> Oooo00oO0h! Wh0 livs in a pain-appl undr the see? > 5PuNGE bUb pnts^2! FLAG: p1ain_tex7_is_sti11_p1ain_ev3n_if_its_tricky
FLAG:p1ain_tex7_is_sti11_p1ain_ev3n_if_its_tricky
School incident(reverse:150pt)
LOL, look at these stupid admins, bros! They set easy-breasy root password and store md5 of the password in /etc/shadow:
root@school:#cat /etc/shadow root:f505f1e49e98cea82c9c4265262444f6:14425:0:99999:7::: teacher:*:14425:0:99999:7::: adm:*:14425:0:99999:7::: ...
MD5をクラックしてくれるサービスに投げる。
FLAG:i_am_admin
Strange program(reverse:300pt)
今回解いた問題の中で一番の問題児。
We have found the strange file named mascal.pas in one of directories on our server. Probably it is a source code of some program, but we can't understand its algorithm. Can you tell us its output?
Сценарii Добре_декодер_прапор; Змiннi: прапор1, прапор2, прапор3, прапор4 : рядок; результат_прапор : рядок; позицiя : цiле число; Функцiя перевертати_рядок(гарний_рядок : рядок) : рядок; Змiннi: часовий_рядок : рядок; i, рядок_довжина : цiле число; ц : ієрогліф; Почати часовий_рядок := гарний_рядок; рядок_довжина := Довжина(часовий_рядок) + 1; Заради i := 1 до рядок_довжина дiлити 2 зробити Почати ц := часовий_рядок[i]; часовий_рядок[i] := часовий_рядок[рядок_довжина - i]; часовий_рядок[рядок_довжина - i] := ц; Кiнец; перевертати_рядок := часовий_рядок; Кiнец; Почати прапор1 := 'АРОКАРП'; прапор2 := 'ФАРГОНИЛЕЦ'; прапор3 := 'ЗА-ХОП-ХЛОПЯ'; прапор4 := 'ЖРУЖЕОБЛОМОВ'; позицiя := Положення('-',прапор3); В той час як позицiя <> 0 зробити Почати Видаляти(прапор3, позицiя, 1); позицiя := Положення('-',прапор3); Кiнец; прапор1[4] := 'П'; позицiя := Положення('ОБЛОМ',прапор4); Видаляти(прапор4, позицiя - 1, Довжина('ОВ') + 1 + Довжина('ОБЛОМ')); Вписувати('БА',прапор4,Довжина(прапор4)+1); прапор4[1] := 'Д'; позицiя := Положення('ХОПХЛОП',прапор3); Видаляти(прапор3, позицiя + 3, 4); Вписувати('ЛЕНН',прапор3,Довжина(прапор3)); прапор2 := перевертати_рядок(прапор2); Видаляти(прапор2, 3, Довжина(прапор2)-2); результат_прапор := прапор3 + '_' + перевертати_рядок(прапор1) + '_' + прапор2 + '_' + прапор4; Написати_лiнiя(результат_прапор); Kiнец;
適当な単語を選んでGoogle翻訳にかけてみたところ、どうもPascalのソースの変数名・関数名・予約語をウクライナ語にしたものっぽい。なんだそりゃ……。
とりあえずPascalに直してみた。
Program good_flag_decoder; var flag1, flag2, flag3, flag4 : string; result_flag : string; policies : integer; function reverse_string(good_string : string) : string; var temp_string : string; i, string_length : integer; ts : char; begin temp_string := good_string; string_length := length(temp_string) + 1; for i := 1 to string_length div 2 do begin ts := temp_string[i]; temp_string[i] := temp_string[string_length - i]; temp_string[string_length - i] := ts; end; reverse_string := temp_string; end; begin flag1 := 'АРОКАРП'; flag2 := 'ФАРГОНИЛЕЦ'; flag3 := 'ЗА-ХОП-ХЛОПЯ'; flag4 := 'ЖРУЖЕОБЛОМОВ'; policies := pos('-',flag3); while policies <> 0 do begin delete(flag3, policies, 1); policies := pos('-',flag3); end; flag1[4] := 'П'; policies := pos('ОБЛОМ',flag4); delete(flag4, policies - 1, length('ОВ') + 1 + length('ОБЛОМ')); insert('BA',flag4,length(flag4)+1); flag4[1] := 'Д'; policies := pos('ХОПХЛОП',flag3); delete(flag3, policies + 3, 4); insert('ЛЕНН',flag3,length(flag3)); flag2 := reverse_string(flag2); delete(flag2, 3, length(flag2)-2); result_flag := flag3 + '_' + reverse_string(flag1) + '_' + flag2 + '_' + flag4; writeln(result_flag); end.
ideoneで実行してみたが、文字列変数にマルチバイト文字が入っているのがお気に召さないらしく、実行時エラーになってしまった。
仕方がないのでRubyで書き直し、フラグを出した。
class String def delete(start, count) self[0...start] + self[start + count...self.length] end end flag1="АРОКАРП" flag2="ФАРГОНИЛЕЦ" flag3="ЗА-ХОП-ХЛОПЯ" flag4="ЖРУЖЕОБЛОМОВ" flag3 = flag3.gsub(/-/, "") flag1[3] = "П" policies = flag4.index('ОБЛОМ') flag4 = flag4.delete(policies - 1, 8) flag4 += "БА" flag4[0]="Д" policies = flag3.index("ХОПХЛОП") flag3 = flag3.delete(policies + 3, 4) flag3 = flag3.insert(flag3.length - 1, "ЛЕНН") flag2 = flag2.reverse flag2 = flag2.delete(2, flag2.length - 2) result_flag = flag3 + "_" + flag1.reverse + "_" + flag2 + "_" + flag4 puts result_flag # => "ЗАХОПЛЕННЯ_ПРАПОРА_ЦЕ_ДРУЖБА"
ウクライナ語で"Capture the Flag is friendship"という意味らしい。
てか断りなくフラグに非ASCII文字が入ってるのはどうなの……w
FLAG:ЗАХОПЛЕННЯ_ПРАПОРА_ЦЕ_ДРУЖБА
Run the image?(stego:400pt)
JPEGファイルの後ろにexeファイルがくっついていた。
分離して実行したらフラグが表示される。
FLAG:aw3s0me_flag
Shop of goodness(web:100pt)
「フラグが買えるネットショップ」の模様。
画面が1つ進むと、URLパラメータのst
の値も1つ増える。
「銀河カードの番号」なるものの入力を求められるが……
SQLインジェクションの脆弱性はなく、何を入れてもエラー画面に。
しかし、st
を5にすると購入完了画面が出せる。
FLAG:GoOgle_iS_yOur_FrieNd
Stored pass(web:100pt)
パスワードフィールドに最初からフラグが入っているので、Webコンソールで
document.getElementsByName("password")[0].value // => saving_passwords_is_bad_idea
で終了。
FLAG:saving_passwords_is_bad_idea
Junior pentesting(web:300pt)
user : admin'-- pass : hoge
でsubmitするとフラグが出る。
FLAG:dont_drop_my_tables
Unusual redirection(web:300pt)
flagページにアクセスしようとすると302でoopsページに飛ばされるが、302のレスポンス内にフラグが入っている。
FLAG:old_link_is_cool_link