この大会は2023/7/28 19:00(JST)~2023/7/30 19:00(JST)に開催されました。
今回もチームで参戦。結果は2447点で970チーム中29位でした。
自分で解けた問題をWriteupとして書いておきます。
RULES (MISC, WARMUP)
ルールのページを見るとフラグのサンプルが書いてあった。
TFCCTF{Th15_3d1t10n_15_rus7y!}
DOWN BAD (FORENSICS, WARMUP)
IHDRチャンクのCRCがおかしい。画像の高さが間違っていると推測できるので、CRCが合うよう高さを変更する。
#!/usr/bin/env python3 import struct import binascii with open('down_bad.png', 'rb') as f: data = f.read() head = data[:12] tail = data[29:] for h in range(1168, 2049): height = struct.pack('>I', h) ihdr = data[12:20] + height + data[24:29] crc = struct.pack('!I', binascii.crc32(ihdr)) if crc == data[29:33]: out = head + ihdr + tail with open('down.png', 'wb') as f: f.write(out) break
下の方にフラグが現れた。
TFCCTF{28ae25c96850245ffdd70a880158f9f3}
MAYDAY! (CRYPTO, WARMUP)
NATO phonetic alphabetのようだ。https://en.wikipedia.org/wiki/NATO_phonetic_alphabetを参考に復号する。
WH4T-AR3-YOU-S1NKING-4B0U7
TFCCTF{WH4T-AR3-YOU-S1NKING-4B0U7}
DIZZY (CRYPTO, WARMUP)
文字と位置のペアがスペース区切りで書いてある。該当する位置に文字を書いていく。
111111111122222222223333333333 0123456789012345678901234567890123456789 TFCCTF{th15_ch4ll3ng3_m4k3s_m3_d1zzy_;d}
TFCCTF{th15_ch4ll3ng3_m4k3s_m3_d1zzy_;d}
ALIEN MUSIC (CRYPTO, EASY)
音階のアルファベット表記のような暗号。
>>> hex(ord('T'))[2:] '54' >>> hex(ord('F'))[2:] '46' >>> hex(ord('C'))[2:] '43' >>> hex(ord('{'))[2:] '7b' >>> hex(ord('}'))[2:] '7d'
以上から推測しながら、対応づける。
A -> 0 A# -> 1 B -> 2 C -> 3 C# -> 4 D -> 5 D# -> 6 E -> 7 F -> 8 F# -> 9 1 -> a 2 -> b 3 -> c 4 -> d 5 -> e 6 -> f
#!/usr/bin/env python3 enc = 'DC# C#D# C#C C#C DC# C#D# E2 C#5 CA EC# CC DE CA EB EC# D#F EF# D6 D#4 CC EC EC CC# D#E CC E4' enc = enc.replace('1', 'a') enc = enc.replace('2', 'b') enc = enc.replace('3', 'c') enc = enc.replace('4', 'd') enc = enc.replace('5', 'e') enc = enc.replace('6', 'f') enc = enc.replace('A#', '1') enc = enc.replace('A', '0') enc = enc.replace('B', '2') enc = enc.replace('C#', '4') enc = enc.replace('C', '3') enc = enc.replace('D#', '6') enc = enc.replace('D', '5') enc = enc.replace('E', '7') enc = enc.replace('F#', '9') enc = enc.replace('F', '8') enc = enc.split(' ') flag = '' for c in enc: flag += chr(int(c, 16)) print(flag)
TFCCTF{N0t3W0rthy_m3ss4g3}
RABID (CRYPTO, EASY)
base64文字列に余計な文字が含まれている。CyberChefでbase64結果を確認しながら、文字を削っていく。
VEZDQ1RGe13kwdV9yNGIxZF9kMGc/IT8hPyE/IT8hPi8+Pz4/PjEyMzkwamNhcHNrZGowOTFyYW5kb21sZXR0ZXJzYW5kbnVtYmVyc3JlZWVlMmozfQ== TFCCTF{]äÁÕ}Èшő}Áœü„ü„ü„ü„ü„ø¼øüøüøÄÈÌäÁ©…ÁÍ‘¨ÀäÅÉ…¹‘½µ±•ÑÑ•ÉÍ…¹‘¹Õµ‰•ÉÍÉ•••”ɨÍô
VEZDQ1RGe3kwdV9yNGIxZF9kMGc/IT8hPyE/IT8hPi8+Pz4/PjEyMzkwamNhcHNrZGowOTFyYW5kb21sZXR0ZXJzYW5kbnVtYmVyc3JlZWVlMmozfQ== TFCCTF{y0u_r4b1d_d0g?!?!?!?!?!>/>?>?>12390jcapskdj091randomlettersandnumbersreeee2j3}
TFCCTF{y0u_r4b1d_d0g?!?!?!?!?!>/>?>?>12390jcapskdj091randomlettersandnumbersreeee2j3}
CYPHEREHPYC (CRYPTO, MEDIUM)
サーバの処理概要は以下の通り。
・KEY: ある文字列の2回繰り返し ・initial_cipher: 16進数文字列→hexデコード ・cipher: initial_cipherをパディングし、AES-ECB暗号化したもの ・cipherの16進数表記を表示 ・cipher: cipherをパディングし、AES-ECB暗号化したもの ・cipherの16進数表記を表示 ・cipher: cipherをパディングし、AES-ECB暗号化したもの ・result: 16進数文字列→hexデコード ・cipherとresultが一致する場合、フラグを表示
KEYは固定なので、2回アクセスすると、1回目のresultがわかる。
$ nc challs.tfcctf.com 31797 Initial HEX: 10101010101010101010101010101010 45163e33272d0b15cb72f8a9ad51d58445163e33272d0b15cb72f8a9ad51d584 68afa11f3c8c1d4632e8b7faebfeb45668afa11f3c8c1d4632e8b7faebfeb45645163e33272d0b15cb72f8a9ad51d584 Result HEX: $ nc challs.tfcctf.com 31797 Initial HEX: 45163e33272d0b15cb72f8a9ad51d58445163e33272d0b15cb72f8a9ad51d584 68afa11f3c8c1d4632e8b7faebfeb45668afa11f3c8c1d4632e8b7faebfeb45645163e33272d0b15cb72f8a9ad51d584 60b9b8d9446bb248e86bcedd1292537d60b9b8d9446bb248e86bcedd1292537d68afa11f3c8c1d4632e8b7faebfeb45645163e33272d0b15cb72f8a9ad51d584 Result HEX: $ nc challs.tfcctf.com 31797 Initial HEX: 10101010101010101010101010101010 45163e33272d0b15cb72f8a9ad51d58445163e33272d0b15cb72f8a9ad51d584 68afa11f3c8c1d4632e8b7faebfeb45668afa11f3c8c1d4632e8b7faebfeb45645163e33272d0b15cb72f8a9ad51d584 Result HEX: 60b9b8d9446bb248e86bcedd1292537d60b9b8d9446bb248e86bcedd1292537d68afa11f3c8c1d4632e8b7faebfeb45645163e33272d0b15cb72f8a9ad51d584 TFCCTF{3v3ryth1ng_1s_r3v3rs3d_1n_th3_3nd}
TFCCTF{3v3ryth1ng_1s_r3v3rs3d_1n_th3_3nd}
AES CTF TOOL V1 (CRYPTO, MEDIUM)
$ nc challs.tfcctf.com 30796 1. Encrypt Data q. Quit > 1 Data (HEX): 11 85002691171df16280981249612d09379390287d25ca1975aa8b6173044513373dfa81168619115150b32e5b49f9e230051f1a65a2a879b02dfbd3aad9d4a5fcda9b6f6504f626c40d2a8c1d8b3628cf 1. Encrypt Data q. Quit > 1 Data (HEX): 1111 35f699049a7a32cc6d0c66ad5605c299386f6df4ad17887a32e2b210c55e645f90e9f19d88bdf08bb7475432ff4989de683a26922e3934b6cc7b24541d6118258ff392c88c920355af4950f3bead013d 1. Encrypt Data q. Quit > 1 Data (HEX): 111111 ea42625c60d0f17023354279abb9282fa0351c3e8aec2bf3d26b2ef9d123a43310a458a22431862ae3030d47d6092ab4e976927b64abc93e8f5625a1181837de445509ce391ab51535737ba8af2bbda7 1. Encrypt Data q. Quit > 1 Data (HEX): 11111111 8413ba6c4088575f07217d22e5cd8c167b10d44f4774f821159f758ee5fc7e026bcdd7a7746faa51be74cffb93caa01062b649117b0378cfdd6036e56733c0cc557527ab44e966690f52a262a2ccf79d 1. Encrypt Data q. Quit > 1 Data (HEX): 1111111111 6bb8d79dbf7979038c32443e24849949f49448acb6c51566653658264c3e02be864b7e975f22ba73d84a3a17343015e84b3a8dc43072898f64e5f8f5e760457aea672c9b8da2d0fe9161abed835d6fa1 1. Encrypt Data q. Quit > 1 Data (HEX): 111111111111 636c8da4d1573a3d9c83b62f6454a08cbe7b5bd8d3b9397530d687aa2d40548df9df1a4f0788881227a2a38a49306daf8513662e21dfcde24b5054fc8f90cd91f72893a09af0ef372551d63b9007cad8 1. Encrypt Data q. Quit > 1 Data (HEX): 11111111111111 a2b27fbfa9408da5a6fd4fd874709622779e3c1a623027cd2b76d99678c3b9c7a96f30dae0f6bdc64c42b74977a3d418c8f490decb20d864d630f7fb881cb4805c0279a39d48020848cb9d5a52e85d79 1. Encrypt Data q. Quit > 1 Data (HEX): 1111111111111111 cf632b307e2d852a6040a2c265372133cca1d9224b47912af1d7f2f75fc49485c20247c148f1f7c964e01ee336eaec25f5a425c7756c8fa1a4561388044cd93f66c5a5ea6b1f69404865edf7f15dda50 1. Encrypt Data q. Quit > 1 Data (HEX): 111111111111111111 cf632b307e2d852a6040a2c265372133ff329119ddc70f9ac08b523d63f11ce1ab72b36d501dd59af587e39c484189a574d4264c7ce2461034d43000c662232773bb45d526085f617aa9d95c712f576d 1. Encrypt Data q. Quit > 1 Data (HEX): 11111111111111111111 cf632b307e2d852a6040a2c265372133b8cc6915d04275246d8bf3bfe1ef51f5adf7a00091e4b90b5f0450994f448b3f80069efc633d7ba28a927e7781c5251f4e947a0c6d59c5755756b9b2b094a66b 1. Encrypt Data q. Quit > 1 Data (HEX): 1111111111111111111111 cf632b307e2d852a6040a2c2653721335366a5b55cd91d13629a76f239c1d3a6633922a69e40adb04a96d1e53a9777c29762a90ee0b00dbe89d56ad69c6cb4465f893157b0ad77a901acb5c464368fcb 1. Encrypt Data q. Quit > 1 Data (HEX): 111111111111111111111111 cf632b307e2d852a6040a2c265372133a4675c1c5799f1be38b8122bfe241b2c61cf61c2b7274f2769ca8dea85fdcdc21aba12746c4a4f10ef7a9461c270bfd8ce5d534393c97d909bce95c1629887a2 1. Encrypt Data q. Quit > 1 Data (HEX): 11111111111111111111111111 cf632b307e2d852a6040a2c2653721337c8ad10490cd369b96c2f62717a5fb9f86a82256f37a76296317b2dccd3052d5db22efa93b66c946e05269f98a9d4ce0ad4b3e83e2b2fd12d30152cb6fd498da 1. Encrypt Data q. Quit > 1 Data (HEX): 1111111111111111111111111111 cf632b307e2d852a6040a2c265372133d1372126a091c2c0f5f0b1348763dbe86fbcd6e210e63ccb2e95c295661add06c37bc3b16702927aaf759a25f13029b0b9b7e0e49e503bb5668582f4ff34d66c 1. Encrypt Data q. Quit > 1 Data (HEX): 111111111111111111111111111111 cf632b307e2d852a6040a2c265372133c0ca5cd5307d24a0b6d9a037a03cbe9ff37864afafc70a669f8f67a49face404859714360d0cb79a56f7870760074b8a94493b17ad11210cd1e6b4ecca18551a 1. Encrypt Data q. Quit > 1 Data (HEX): 11111111111111111111111111111111 cf632b307e2d852a6040a2c2653721339d6399eaf717efa28b086755a0745ba588040d348a6cf7e92acfacbe3733745f3e88ec44488bb611ee84857d435cf555f31b9bbd820d397eaa38af12a61e3652 1. Encrypt Data q. Quit > 1 Data (HEX): 1111111111111111111111111111111111 cf632b307e2d852a6040a2c265372133b5a11da5774b87b51f418d6f59bdf1a79390287d25ca1975aa8b6173044513373dfa81168619115150b32e5b49f9e230051f1a65a2a879b02dfbd3aad9d4a5fcda9b6f6504f626c40d2a8c1d8b3628cf 1. Encrypt Data q. Quit > 1 Data (HEX): 1111111111111111111111111111111111111111111111111111111111111111 cf632b307e2d852a6040a2c26537213395dec1915bf16e17255083e484eba6b19d6399eaf717efa28b086755a0745ba588040d348a6cf7e92acfacbe3733745f3e88ec44488bb611ee84857d435cf555f31b9bbd820d397eaa38af12a61e3652 1. Encrypt Data q. Quit Data (HEX): 111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 cf632b307e2d852a6040a2c26537213395dec1915bf16e17255083e484eba6b195dec1915bf16e17255083e484eba6b19d6399eaf717efa28b086755a0745ba588040d348a6cf7e92acfacbe3733745f3e88ec44488bb611ee84857d435cf555f31b9bbd820d397eaa38af12a61e3652 1. Encrypt Data q. Quit
おそらくAES暗号のCBCモードで、先頭8バイトに固定文字列が入っている。
0123456789abcdef SSSSSSSSXXXXXXXX XXXXXXXXXFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF PPPPPPPPPPPPPPPP
フラグの長さは55であると思われる。
ECBモードより面倒だが、1バイトずつはみ出させ、ブルートフォースでフラグを求めることができる。1回目に(1)のように指定し、5ブロック目の暗号を取得する。次に(2)のように?をブルートフォースし、5ブロック目の暗号が同じになるものを探す。これを繰り返す。
(1)フラグはみ出し 0123456789abcdef SSSSSSSSXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFPP (2)ブルートフォース 0123456789abcdef SSSSSSSSXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXX? FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFP
#!/usr/bin/env python3 import socket def recvuntil(s, tail): data = b'' while True: if tail in data: return data.decode() data += s.recv(1) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('challs.tfcctf.com', 31706)) flag = '' for i in range(55): payload = (b'X' * (71 - i)).hex() data = recvuntil(s, b'> ') print(data + '1') s.sendall(b'1\n') data = recvuntil(s, b': ') print(data + payload) s.sendall(payload.encode() + b'\n') data = recvuntil(s, b'\n').rstrip() print(data) block5 = data[32*4:32*5] for code in range(32, 127): payload = ((b'X' * (71 - i)) + flag.encode() + bytes([code])).hex() data = recvuntil(s, b'> ') print(data + '1') s.sendall(b'1\n') data = recvuntil(s, b': ') print(data + payload) s.sendall(payload.encode() + b'\n') data = recvuntil(s, b'\n').rstrip() print(data) if data[32*4:32*5] == block5: flag += chr(code) break print(flag)
実行結果は以下の通り。
: 1. Encrypt Data q. Quit > 1 Data (HEX): 58585858585858585858585858585858585446434354467b67753335355f746834745f7734735f333435792e2e2e576834542d41626f55745f5468335f30746833725f306e333f7c 5e117e6df84abfd4ec4278a6eeb4dcc2d5878b3b645e5938b898eccb5f3a5cadb124b89e4c5319882f4a8700ce908abed25369139323e530cb38b75c9b56aefb5883af3bb74e2574c007d465db396dfd468060dc4e9e1f11458e58597f2171be99c593829911de9ec9294bc51352766b9779759ce5b40dfae8c92ceab954f6d861d27d66c74e11825b01afc8f5faf8a8 1. Encrypt Data q. Quit > 1 Data (HEX): 58585858585858585858585858585858585446434354467b67753335355f746834745f7734735f333435792e2e2e576834542d41626f55745f5468335f30746833725f306e333f7d 5e117e6df84abfd4ec4278a6eeb4dcc2d5878b3b645e5938b898eccb5f3a5cadb124b89e4c5319882f4a8700ce908abed25369139323e530cb38b75c9b56aefbe6cd366f4d67e30bfc9b6487ce10f25d468060dc4e9e1f11458e58597f2171be99c593829911de9ec9294bc51352766b9779759ce5b40dfae8c92ceab954f6d861d27d66c74e11825b01afc8f5faf8a8 TFCCTF{gu355_th4t_w4s_345y...Wh4T-AboUt_Th3_0th3r_0n3?}
TFCCTF{gu355_th4t_w4s_345y...Wh4T-AboUt_Th3_0th3r_0n3?}
AES CTF TOOL V2 (CRYPTO, MEDIUM)
$ nc challs.tfcctf.com 30853 Flag is: fd083c910e4322d97054a742d6e6cdbc7aeed3cab5b04f539bca7a64bf8a4db76eaeb5a579429bbe848fd57fb9136e1f54ef4630c6c7a0fe4b7a7497247daa15 1. Encrypt Data 2. Decrypt Data q. Quit > 1 Data (HEX): 12 fd083c910e4322d97054a742d6e6cdbc26af21a95f580cf077aa6149935652e1 1. Encrypt Data 2. Decrypt Data q. Quit > 2 Data (HEX): fd083c910e4322d97054a742d6e6cdbc26af21a95f580cf077aa6149935652e1 1. Encrypt Data 2. Decrypt Data q. Quit > 2 Data (HEX): fd083c910e4322d97054a742d6e6cdbc7aeed3cab5b04f539bca7a64bf8a4db76eaeb5a579429bbe848fd57fb9136e1f54ef4630c6c7a0fe4b7a7497247daa15 1. Encrypt Data 2. Decrypt Data q. Quit > 2 Data (HEX): fd083c910e4322d97054a742d6e6cdbc7aeed3cab5b04f539bca7a64bf8a4db76eaeb5a579429bbe848fd57fb9136e1f54ef4630c6c7a0fe4b7a7497247daa14 Padding is incorrect. 1. Encrypt Data 2. Decrypt Data q. Quit
paddinのチェック結果だけがわかる。AES CBC Padding Oracle Attackで復号する。
#!/usr/bin/env python3 import socket from Crypto.Util.strxor import strxor from Crypto.Util.Padding import unpad def recvuntil(s, tail): data = b'' while True: if tail in data: return data.decode() data += s.recv(1) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('challs.tfcctf.com', 31485)) data = recvuntil(s, b'\n').rstrip() print(data) enc_flag = bytes.fromhex(data.split(' ')[-1]) blocks = [enc_flag[i:i+16] for i in range(0, len(enc_flag), 16)] flag = b'' for i in range(1, len(blocks)): xor_block = b'' for j in range(16): for code in range(256): print('[+] flag: ', flag) if j != 0: print('[+] %d - %d - %d: %s' % (i, j, code, strxor(xor_block, blocks[i - 1][-j:]))) try_pre_block = b'\x00' * (16 - j - 1) + bytes([code]) + strxor(xor_block, bytes([j + 1]) * j) try_cipher = (try_pre_block + blocks[i]).hex() data = recvuntil(s, b'> ') print(data + '2') s.sendall(b'2\n') data = recvuntil(s, b': ') print(data + try_cipher) s.sendall(try_cipher.encode() + b'\n') data = recvuntil(s, b'\n').rstrip() print(data) if 'Padding is incorrect' not in data: xor_code = (j + 1) ^ code xor_block = bytes([xor_code]) + xor_block break flag += strxor(blocks[i - 1], xor_block) flag = unpad(flag, 16).decode() print('[*] flag:', flag)
実行結果は以下の通り。
: : [+] flag: b'TFCCTF{W3ll..._th15_0n3_w4s_4ls0' [+] 3 - 15 - 199: b'easy!}\t\t\t\t\t\t\t\t\t' 1. Encrypt Data 2. Decrypt Data q. Quit > 2 Data (HEX): c787562125d6f9763a4fa2cc757bdbba5da5d91b41d51a8e85a6e2ebaf36565d Padding is incorrect. [+] flag: b'TFCCTF{W3ll..._th15_0n3_w4s_4ls0' [+] 3 - 15 - 200: b'easy!}\t\t\t\t\t\t\t\t\t' 1. Encrypt Data 2. Decrypt Data q. Quit > 2 Data (HEX): c887562125d6f9763a4fa2cc757bdbba5da5d91b41d51a8e85a6e2ebaf36565d [*] flag: TFCCTF{W3ll..._th15_0n3_w4s_4ls0_easy!}
TFCCTF{W3ll..._th15_0n3_w4s_4ls0_easy!}