この大会は2018/7/21 18:00(JST)~2018/7/23 6:00(JST)に開催されました。
今回もチームで参戦。結果は875点で637チーム中28位でした。
自分で解けた問題をWriteupとして書いておきます。
Welcome to CTFZone!
問題にフラグが書いてある。
ctfzone{2018}
Federation Workflow System (CRYPTO)
$ nc crypto-04.v7frkwrfyhsjtbpfcppnu.ctfz.one 7331 list</msg> lorem.txt,flag.txt,admin.txt,password.txt</msg> $ nc crypto-04.v7frkwrfyhsjtbpfcppnu.ctfz.one 7331 login</msg> 8150411504</msg> $ nc crypto-04.v7frkwrfyhsjtbpfcppnu.ctfz.one 7331 file lorem.txt</msg> N5VO/+EIu1GtkPR8HsxkQ8w/18vV42h0xVeBBL4R9QVTcJhPE9ZrqX23saQBdnKcwHp6fVMag+a+k57SMyVcsmRRmGJwWClSCSOUHh+FHyIiup5mHFUHpn1PsFV53GbesDRKE6NjBGpxKdf0iO7S/9GFJcqa5d4vR65QLG0Nw4YEigM2EgZB9F6s/Rrz9z/0sG6lDLEErtVAjungqmnmcYVfLcZ7TpV8GRXlJppwhwrJKwWSTowJ+68DomDZx3jEAxCmrE547TbL5ZVIpfynSNcVYL1mHI1PgWuM1/Rpojoofae4qviTFaDGtOEOOy+TwMuMR8LuVy2nXuKpPFUiOu9td2WKcQA+vf1zMKJPrbVQfBN1CFbZMX5Bgt6UVLuGAoSQn/t9pYMwQ2ourJV20GzmAOObhyQxe/12dBNaYmHTn4/zDJB35GOE7VKAYESVd5rGEZ25miUMLWQkUr+dYiCE3ylKFjkgGk8PGTDdCgdnytqK34gy8x5Lult3rUwQduHlriOa8UQ0awlVIeB7js5JtfgZ2jfSfSJAnw9xTN1yrnJnPaZr5Ofx+bmiwjS4vuHD/rr6DD1Rk2bp0aVSEji80QQbUjfvZitMqtN6IIYmtrWLnzwWOmFLNsugIojhY3OaXb5TdiJcPg58PI7cBfIJT6uYK3VlwQzdFQQAyZXzPclnq5FLE9FgNzeMIOtDHZbCh8SEFeGn3o80YPScJmWVc9WgysLDvaPHFsXxzEI=</msg> $ nc crypto-04.v7frkwrfyhsjtbpfcppnu.ctfz.one 7331 file flag.txt</msg> a0DGKiriDPsP6ILG+SxK2jhUPjEBcHHSJV7gpqcjiQA=</msg> $ nc crypto-04.v7frkwrfyhsjtbpfcppnu.ctfz.one 7331 file admin.txt</msg> wwXYDdGHxF4hjoO5/jOu62I1bZzDof2NwmkGrXCN8tZISxU9L1JJrvbTswK7LVd8XZvfDrRfF715j8DPDFFdDw==</msg> $ nc crypto-04.v7frkwrfyhsjtbpfcppnu.ctfz.one 7331 file password.txt</msg> 26yRuctJGSszUouMVgPy2OyKuRFpaHaYlEvvxpZXO31Cz9KAgtd7whefNgExU2wX</msg> $ nc crypto-04.v7frkwrfyhsjtbpfcppnu.ctfz.one 7331 file ../top_secret/server.log</msg> +s9BHx3ZJ63gULLTNFtpwZyaziwmAjPXHs1ob6x28qVk4PHps81ItKmQ48h1xWJn</msg> $ nc crypto-04.v7frkwrfyhsjtbpfcppnu.ctfz.one 7331 file ../top_secret/real.flag</msg> aU+tYnYcQZ+kVti6l+aCEXfvGsdC4jgVpP1nL065BkXaM6MkmQ7MapG2uwT4+obq</msg> $ nc crypto-04.v7frkwrfyhsjtb file ../top_secret/aes.key</msg> /XXk19YZgWPHK+QCzuyXuDclnD1kINNGDFWrcUNDBcBsm2rInegIuMXvFpJpSjdG</msg> $ nc crypto-04.v7frkwrfyhsjtb file totp.secret</msg> tPT1pw0IliLk+Rg/dlUHoNf/z5M3bfY+uFelVQLzJbo=</msg>
各メニューの機能は以下の通り。
■list 以下を表示 ・lorem.txt ・flag.txt ・admin.txt ・password.txt ■login 時刻(エポック秒数)を表示 ■file ・content: 指定ファイル読み込み ・\x00が含まれている場合はそこまではファイル名とする。 ・response: "<ファイル名>: <ファイルの内容>" ・encrypted_response: responseのAES暗号(ECB) ■admin ・check_totpでOKである場合にフラグが表示される。
../totp.secretの内容を復号する。あとはAES-ECBで1文字ずつはみ出させ、ブルートフォースで復号する。さらにサーバ時刻を取得し、その情報を復号データを使って、admin tokenを算出して提示すればフラグが得られる。
import hmac import socket from hashlib import sha1 from struct import pack, unpack from base64 import b64decode import string totp_key = '../totp.secret' block_size = 16 buff_size = 1024 def get_enc(file): host = 'crypto-04.v7frkwrfyhsjtbpfcppnu.ctfz.one' port = 7331 snd_format = 'file %s</msg>' s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, port)) snd_data = snd_format % file s.sendall(snd_data) data = s.recv(buff_size) print data return data.replace('</msg>', '') def get_time(): host = 'crypto-04.v7frkwrfyhsjtbpfcppnu.ctfz.one' port = 7331 snd_format = 'login</msg>' s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, port)) snd_data = snd_format s.sendall(snd_data) data = s.recv(buff_size) print data return data.replace('</msg>', '') def snd_admin_tk(pin): host = 'crypto-04.v7frkwrfyhsjtbpfcppnu.ctfz.one' port = 7331 snd_format = 'admin %s</msg>' s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, port)) snd_data = snd_format % pin s.sendall(snd_data) data = s.recv(buff_size) print data return data.replace('</msg>', '') key = '' for i in range(48): file = totp_key + '\x00' * (i + 1) data = get_enc(file) correct_data = b64decode(data)[64:80] for c in string.hexdigits: try_file = totp_key + '\x00' * 2 + c + key print try_file pad = block_size - len(try_file) % block_size try_file = try_file + (pad * chr(pad)) try_enc = get_enc(try_file) if b64decode(try_enc)[16:32] == correct_data: key = c + key break print key tm = int(get_time()) counter = pack('>Q', tm // 30) print counter.encode('hex') totp_hmac = hmac.new(key.encode('UTF-8'), counter, sha1).digest() offset = ord(totp_hmac[19]) & 15 totp_pin = str((unpack('>I', totp_hmac[offset:offset + 4])[0] & 0x7fffffff) % 1000000) token = totp_pin.zfill(6) print token msg = snd_admin_tk(token) print msg
ctfzone{A74D92B6E05F4457375AC152286C6F51}