この大会は2020/2/22 21:30(JST)~2020/2/25 3:30(JST)に開催されました。
今回もチームで参戦。結果は 360点で282チーム中81位でした。
自分で解けた問題をWriteupとして書いておきます。
Welcome!!! (miscellaneous 10)
Telegramのbotと会話する。
/helpを確認すると、/movieなるものがある。
/movieを試すと、以下の一覧が表示された。
Pulp Fiction Casablanca Terminator Final Destination Batman Begins Once Upon A Time In Hollywood Tomb Raider Se7en Aquaman Ratatouille Ender's Game Casino Royale Oblivion Oceans 11 Little Women Aladdin Finding Nemo
各行の先頭の文字をつなげると、フラグになりそう。
PCTFBOTSARECOOLAF
p_ctf{bots_are_cool_af}
Up can be Down (Forensics 100)
$ exiftool mrRobot.jpg ExifTool Version Number : 10.10 File Name : mrRobot.jpg Directory : . File Size : 857 kB File Modification Date/Time : 2020:02:22 21:59:50+09:00 File Access Date/Time : 2020:02:22 22:01:10+09:00 File Inode Change Date/Time : 2020:02:22 21:59:50+09:00 File Permissions : rwxrwxrwx File Type : JPEG File Type Extension : jpg MIME Type : image/jpeg JFIF Version : 1.01 Exif Byte Order : Big-endian (Motorola, MM) X Resolution : 28 Y Resolution : 28 Resolution Unit : cm Artist : 8f068b017cd807fd3b8c684dea2f8156 Y Cb Cr Positioning : Centered XMP Toolkit : Image::ExifTool 11.70 Format : U29tZSBTSEEgbWF5YmUhISEh Comment : c82358dfb202ce9cfddc34e13d403fa3 Image Width : 2560 Image Height : 1920 Encoding Process : Baseline DCT, Huffman coding Bits Per Sample : 8 Color Components : 3 Y Cb Cr Sub Sampling : YCbCr4:4:4 (1 1) Image Size : 2560x1920 Megapixels : 4.9
Format の値をBase64デコードしてみる。
$ echo U29tZSBTSEEgbWF5YmUhISEh | base64 -d Some SHA maybe!!!!
Comment の値を CrackStation でクラックすると、c82358dfb202ce9cfddc34e13d403fa3 は sha256の部分一致でaviumが見つかった。
$ echo -n avium | sha256sum c82358dfb202ce9cfddc34e13d403fa38f068b017cd807fd3b8c684dea2f8156 -
aviumのsha256の後半はArtistの値と同じ。どうやらaviumがパスフレーズになりそうだ。
steghideでこれをパスフレーズにして隠蔽ファイルを取り出す。
$ steghide extract -sf mrRobot.jpg Enter passphrase: wrote extracted data to "flag.txt". $ cat flag.txt Congrats! This was way too wasy :P This is the key:
p_ctf{s0rry_6ut_1_@m_n0t_@_r060t}
ASCII Sentence (Crypto 100)
10進数のASCIIコードが並んでいるとみて、デコードする。
Y3t1cnRfYXNsa29fZV9mb2FfZWVlX25nZHlwdHlfZWh3a3RpX29ifQ==
Base64文字列になるので、さらにデコードする。
c{urt_aslko_e_foa_eee_ngdypty_ehwkti_ob}
転置式暗号の何かの暗号と推測できる。フラグはp_ctfから始まるはずなので、そのインデックスを見てみる。
111111111122222222223333333333 0123456789012345678901234567890123456789 c{urt_aslko_e_foa_eee_ngdypty_ehwkti_ob} p 26 _ ? c 0(40) t 27 f 14(54)
27飛びで次の文字にすれば復号できそう。つまりスキュタレー暗号になっていると推測できる。
enc = '8951116499911082102898878115975057102908657109985070102908786108885053110907210811910072108102908710451975182112885057105102816161' code = '' dec = '' for i in range(len(enc)): code += enc[i] if int(code) >= 32 and int(code) < 127: dec += chr(int(code)) code = '' print dec dec = dec.decode('base64') print dec index = dec.index('p') flag = '' while True: if len(flag) == len(dec): break flag += dec[index] index += 27 if index > len(dec) - 1: index -= len(dec) print flag
p_ctf{you_are_the_weakest_link_good_bye}
AskTheOracle (Crypto 150)
$ nc ctf.pragyan.org 8500 Enter in format '<Ciphertext>|<Initialisation Vector>' aaa|aaa Cipher not in base64 IV not in base64 VGhpcyBpcyBhbiBJVjQ1Ng== name 'cipher' is not defined Padding Error! $ echo VGhpcyBpcyBhbiBJVjQ1Ng== | base64 -d This is an IV456
これが暗号化した時のIVと推測できる。
いろいろ試したところ、パディングエラーになるときに以下のメッセージが出ているようだ。
'Not happening padding error!'
これを利用してCBC Padding Oracleで復号する。
import socket from base64 import b64encode, b64decode def recvuntil(s, tail): data = b'' while True: if tail in data: return data.decode() data += s.recv(1) def str_xor(s1, s2): return ''.join(chr(ord(a) ^ ord(b)) for a, b in zip(s1, s2)) def unpad(s): return s[:-ord(s[-1])] def is_valid(ct): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('ctf.pragyan.org', 8500)) data = recvuntil(s, '\n').rstrip() #print data print ct s.sendall(ct + '\n') data = recvuntil(s, '\n').rstrip() #print data valid_flag = recvuntil(s, '\n').rstrip() #print valid_flag if valid_flag == 'Not happening padding error!': data = recvuntil(s, '\n').rstrip() #print data data = recvuntil(s, '\n').rstrip() #print data return False else: return True enc = 'TIe8CkeWpqPFBmFcIqZG0JoGqBIWZ9dHbDqqfdx2hPlqHvwH/+tbAXDSyzyrn1Wf' enc = b64decode(enc) enc_blocks = [] enc_blocks.append(b64decode('VGhpcyBpcyBhbiBJVjQ1Ng==')) for i in range(0, len(enc), 16): enc_blocks.append(enc[i:i+16]) xor_blocks = [] for i in range(len(enc_blocks)-1, 0, -1): xor_block = '' for j in range(16): for code in range(256): print '%d - %d - %d: %s' % (i, j, code, xor_block.encode('hex')) print '****', str_xor(xor_block, enc_blocks[i-1][-j:]), '****' try_pre_block = '\x00' * (16 - j - 1) + chr(code) + str_xor(xor_block, chr(j+1)*j) try_cipher = b64encode(enc_blocks[i]) + '|' + b64encode(try_pre_block) if is_valid(try_cipher): xor_code = (j+1) ^ code xor_block = chr(xor_code) + xor_block break xor_blocks.append(xor_block) xor_blocks = xor_blocks[::-1] flag = '' for i in range(len(xor_blocks)): flag += str_xor(enc_blocks[i], xor_blocks[i]) flag = unpad(flag) print flag
pctf{b@d_p@nd@s_@r3_3v3rywh3r3_c@tch}