この大会は2020/12/18 18:00(JST)~2020/12/20 4:00(JST)に開催されました。
今回もチームで参戦。結果は1056点で169チーム中15位でした。
自分で解けた問題をWriteupとして書いておきます。
Homer The Simp - 0x1 (Misc)
青い鳥のあるプラットフォームということからSNSの種類はTwitter。HomerTheSimpを検索すると、内容的に以下のURLに掲載していることが合う。
https://twitter.com/homerthesimp56/
そこからツイートをたどっていく。
https://twitter.com/Marge010556/status/1327162071113461761
ここでフラグが書いてあった。
shellmates{w3_c4ught_h1m_s1mp!ng_l4ds}
It's Complicated My Pal (Forensics)
ICMPのデータ部にzipの断片が見えた。集めて、zipにする。
from scapy.all import * packets = rdpcap('capture.pcap') data = '' for p in packets: if p.haslayer(ICMP): if p[IP].src == '192.168.1.200': data += p[Raw].load with open('flag.zip', 'wb') as f: f.write(data)
パスワードがかかっているので、クラックする。
$ fcrackzip -u -D -p dict/rockyou.txt flag.zip PASSWORD FOUND!!!!: pw == craccer $ unzip -P craccer flag.zip Archive: flag.zip inflating: flag.jpg
解凍し、展開されたflag.jpgにフラグが書いてあった。
shellmates{icmp_p@yl04d_4in't_us3l3ss_4ft3r_4ll_r1gHt?}
Sequences and Bases (Cryptography)
逆算していくためにまず素因数分解する。
$ python -m primefac 5654655333396589573009251270272824452868045532409847035578809519921971758405056586087615745288 5654655333396589573009251270272824452868045532409847035578809519921971758405056586087615745288: 2 2 2 3 157 179 4339 1112581 94333140093961 349904234337911801671 53693611291973 979906911043329098468466567737
p * q = 5654655333396589573009251270272824452868045532409847035578809519921971758405056586087615745288 = 2**3 * 3 * 157 * 179 * 4339 * 1112581 * 94333140093961 * 349904234337911801671 * 53693611291973 * 979906911043329098468466567737
SequencesOf0は2進数にしたときの0の連続する数、SequencesOf1は2進数にしたときの1の連続する数。素因数分解の結果から、p, qの組み合わせの総当たりで復号する。
from Crypto.Util.number import * def base_n(p, n): s = '' while True: s += str(p%n) p /= n if p == 0: break return s[::-1] def seq_to_str(seq0, seq1): bin_s = '' for i in range(len(seq0)): bin_s += '0' * seq0[i] bin_s += '1' * seq1[i] s = '' for i in range(0, len(bin_s), 8): s += chr(int(bin_s[i:i+8], 2)) return s with open('ciphertext', 'rb') as f: n = bytes_to_long(f.read()) print '[+] n =', n ps = [] for p0 in [1, 2, 4, 8]: for p1 in [1, 3]: for p2 in [1, 157]: for p3 in [1, 179]: for p4 in [1, 4339]: for p5 in [1, 1112581]: for p6 in [1, 53693611291973]: for p7 in [1, 94333140093961]: for p8 in [1, 349904234337911801671]: for p9 in [1, 979906911043329098468466567737]: p = p0 * p1 * p2 * p3 * p4 * p5 * p6 * p7 * p8 * p9 ps.append(p) found = False for i in range(len(ps)): p = ps[i] q = n / p for maximum0 in range(1, 8): for maximum1 in range(1, 8): SequencesOf0 = map(int, list(base_n(p, maximum0 + 1))) SequencesOf1 = map(int, list(base_n(q, maximum1 + 1))) if len(SequencesOf0) == len(SequencesOf1): flag = seq_to_str(SequencesOf0, SequencesOf1) if flag.startswith('shellmates{'): found = True print '[+] p =', p print '[+] q =', q print '[+] Seq0 =', SequencesOf0 print '[+] Seq1 =', SequencesOf1 print '[*] flag =', flag break if found: break if found: break
実行結果は以下の通り。
[+] n = 5654655333396589573009251270272824452868045532409847035578809519921971758405056586087615745288 [+] p = 157764541996625996565130847469449869788076056 [+] q = 35842371561016047939149570405318318265423962928523 [+] Seq0 = [1, 2, 1, 1, 4, 2, 1, 1, 1, 3, 1, 3, 1, 1, 1, 4, 1, 1, 3, 2, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 3, 1, 1, 4, 1, 1, 1, 2, 1, 1, 1, 2, 1, 3, 1, 3, 1, 3, 1, 1, 2, 2, 1, 4, 1, 3, 2, 1, 1] [+] Seq1 = [3, 2, 2, 1, 2, 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 1, 3, 1, 2, 1, 1, 3, 2, 4, 2, 1, 1, 1, 3, 1, 1, 3, 2, 3, 1, 1, 5, 2, 1, 1, 5, 3, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 1, 5, 2, 2, 2, 2, 2, 1, 2, 3, 5, 1] [*] flag = shellmates{Just_a_sm4ll_fl4g}
shellmates{Just_a_sm4ll_fl4g}
AES ECB (Cryptography)
$ nc chall.bsidesalgiers.com 5002 Oo o.OOoOoo .oOOOo. o.OOoOoo .oOOOo. o.oOOOo. o O O o o O .O o o o O o o O. o o O O oOooOoOo ooOO `OOoo. ooOO o oOooOO. o O O `O O o o `O O o o o o O O o o O O O. .O O `o .o o .O O. O ooOooOoO `oooO' ooOooOoO `OoooO' `OooOO' You send me a string, I send you: BASE64(AES_ECB(input + flag, SECRET_KEY)) Your goal is to get the flag back => 1 The result : bO6QSoVwyjjWUG6k+BWtuEakMEZ4tmq3CN79M/WWRtQkvMas8omC3lCFp05k+PmIhk/kDBDAQlARAPYwfelmG8qFmIF4UaBUW31UrrYeCEE= => 11 The result : YQOWV/Ck03gqZ9GpGfQWCFu0c6EbXGKB73Cjjz6YVoqjfwBtAz+frVOmsIku8d1QRg8LiQuopFFWmjRR/+h0gVO2PVIL5fbVps07b7c14b4= => 111 The result : HDua1M3GoJEE3+GHESPKBIgSathq9vnuqLws9RmXq5iXL8RBiJ4hCqDQspct4Nr4pk10jLDxUtRlu5Th13yqOYbztZW5RDVriYyjedMC9A0= => 1111 The result : alRbRFxyqBAJyis5kVA2aNLt7gZB4sCGq48xFSkzxLLfQzotKbNSGrTZbum7mo7QmI2SfRQ2pww36QqATVR2n/d9Qj00iEIIAGnNK4R8yNM= => 11111 The result : ZTPr63sE/EEv1aA5+HDYsFAqsnqQDUtnXr2W0TxnPO6mc1PKf4atVde6h4X+8QhGw74qemTRG43rcZP1PCX4oiDt6cuqbN9P5u7IHKiI/+I= => 111111 The result : Erm5SNHRRzK2ig4DCgbb7Ny6X82C8TiPHjLyrn1gxKnVAbRTqbG5gs+MTjiAnJpmWBmzAB88xvH7FtSFLOjyZlvbji4jtkbBD88+PvFOltg= => 1111111 The result : fT8tuk9DPASDCX1x9hO9Yjx8qXDLCNybL5npIqCWJ9xL3DdIRbfZGAAY+oiuDNFXLeor0PdWywH96l3h6WhP5UyPPywYd6ePISF1QnhTkF4= => 11111111 The result : aoqRjR3wRoYC9eN29aJKippnOv8N3V/L4HVS+oQkK97WaHeNQx2NxMt387+vGm0idgRuHOfVYzmKGeNtoTY+U2IKijHXQdfPbA3dEIWltMI= => 111111111 The result : PPYYsyy218H0QdowYatDszAG8a1S238ZQMx+Mo+373t+5oO6NIhKiIxLEEPnnNzqfuxEL0W1RDgt0skTwaycnyOzzA1TmYmA9KLzRp5L3AQ= => 1111111111 The result : xFBgEYax4pLQ1HlOMikHCV5srrgr3mOxP3xazzG46OZyJ5TNPLS3n21GSJkjeVl12UYXNWfoGYd/RN9grCFsPpLG01VnOcrVF9Um5VTFNU0= => 11111111111 The result : dIWj2IZzEG3LYVJdlu+zzpJdM5TqvxMxe8z5Gfe3L0yqTUU+Tj4ie9s4xYQnG79JdQqAi5gaMGX9KUMMvNSqLQf9aBwfsLYq7bnsx4C2A0Y= => 111111111111 The result : 0Uq6FplPYDzb5wC+TuJbT+00bZfMm6Yk1iSO47lAx9CxTurGxLYo0Vk0xnKaxUmPn3YMIeRjWvFSVaJ9//TgegXA4YXI/xS0WvzgOWyA23HGDotT/zOS8nueZVlsUDdb
入力が111111111111のときに、base64デコードした文字列の長さが80バイトから96バイトになる。平文は「[input][flag]」という形式。
0123456789abcdef 1111111111111FFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF PPPPPPPPPPPPPPPP
ブロック暗号であることを利用してパディング文字数を調整しながら、先頭からフラグを探り当てる。
0123456789abcdef 111111111111111? 1111111111111111 1111111111111111 1111111111111111 1111111111111111 111111111111111F FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFPPPPPPPPPPPPPP
import socket def recvuntil(s, tail): data = '' while True: if tail in data: return data data += s.recv(1) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('chall.bsidesalgiers.com', 5002)) data = recvuntil(s, 'back\n').rstrip() print data flag = '' for i in range(67): for code in range(32, 127): print '[+]', flag if i < 16: inp = '1' * (15 - i) + flag + chr(code) + '1' * (79 - i) else: inp = flag[-15:] + chr(code) + '1' * (79 - i) data = recvuntil(s, '=>') print data + inp s.sendall(inp + '\n') data = recvuntil(s, '\n').rstrip() print data enc = data.split(' : ')[1].decode('base64') enc0 = enc[16*0:16*1] enc5 = enc[16*5:16*6] if enc0 == enc5: flag += chr(code) break print '[*] flag =', flag
実行結果は以下の通り。
Oo o.OOoOoo .oOOOo. o.OOoOoo .oOOOo. o.oOOOo. o O O o o O .O o o o O o o O. o o O O oOooOoOo ooOO `OOoo. ooOO o oOooOO. o O O `O O o o `O O o o o o O O o o O O O. .O O `o .o o .O O. O ooOooOoO `oooO' ooOooOoO `OoooO' `OooOO' You send me a string, I send you: BASE64(AES_ECB(input + flag, SECRET_KEY)) Your goal is to get the flag back [+] =>111111111111111 1111111111111111111111111111111111111111111111111111111111111111111111111111111 The result : Nm+4gsxsV6Q998Qy3e9OvbG9uRREt2s7AA+yzhxd1YGxvbkURLdrOwAPss4cXdWBsb25FES3azsAD7LOHF3VgbG9uRREt2s7AA+yzhxd1YGsHbqwnv0JDhtSAGsnZ7QcROo7IkzOY996Cfc5VFm/M/wzAnwvm7oV0FNQFTYyJpmDHwi26sCgpFaIEGwbEVOHnqPj7nBgZTiLseoqUTwJQHQIdX7XTw8ro9xwZj1C1mc= [+] =>111111111111111!1111111111111111111111111111111111111111111111111111111111111111111111111111111 The result : foz2dPzoyMr52E4xuCi6xLG9uRREt2s7AA+yzhxd1YGxvbkURLdrOwAPss4cXdWBsb25FES3azsAD7LOHF3VgbG9uRREt2s7AA+yzhxd1YGsHbqwnv0JDhtSAGsnZ7QcROo7IkzOY996Cfc5VFm/M/wzAnwvm7oV0FNQFTYyJpmDHwi26sCgpFaIEGwbEVOHnqPj7nBgZTiLseoqUTwJQHQIdX7XTw8ro9xwZj1C1mc= [+] =>111111111111111"1111111111111111111111111111111111111111111111111111111111111111111111111111111 The result : RgxCvaueFr+4DjJmdH6Lz7G9uRREt2s7AA+yzhxd1YGxvbkURLdrOwAPss4cXdWBsb25FES3azsAD7LOHF3VgbG9uRREt2s7AA+yzhxd1YGsHbqwnv0JDhtSAGsnZ7QcROo7IkzOY996Cfc5VFm/M/wzAnwvm7oV0FNQFTYyJpmDHwi26sCgpFaIEGwbEVOHnqPj7nBgZTiLseoqUTwJQHQIdX7XTw8ro9xwZj1C1mc= [+] =>111111111111111#1111111111111111111111111111111111111111111111111111111111111111111111111111111 The result : 3VWrwS5t/jieejg4JpNdR7G9uRREt2s7AA+yzhxd1YGxvbkURLdrOwAPss4cXdWBsb25FES3azsAD7LOHF3VgbG9uRREt2s7AA+yzhxd1YGsHbqwnv0JDhtSAGsnZ7QcROo7IkzOY996Cfc5VFm/M/wzAnwvm7oV0FNQFTYyJpmDHwi26sCgpFaIEGwbEVOHnqPj7nBgZTiLseoqUTwJQHQIdX7XTw8ro9xwZj1C1mc= [+] =>111111111111111$1111111111111111111111111111111111111111111111111111111111111111111111111111111 The result : TfXHLzwMUD3BMevZ8mmfMrG9uRREt2s7AA+yzhxd1YGxvbkURLdrOwAPss4cXdWBsb25FES3azsAD7LOHF3VgbG9uRREt2s7AA+yzhxd1YGsHbqwnv0JDhtSAGsnZ7QcROo7IkzOY996Cfc5VFm/M/wzAnwvm7oV0FNQFTYyJpmDHwi26sCgpFaIEGwbEVOHnqPj7nBgZTiLseoqUTwJQHQIdX7XTw8ro9xwZj1C1mc= [+] =>111111111111111%1111111111111111111111111111111111111111111111111111111111111111111111111111111 The result : jxmJzfxd9K6cveeLNO8OMLG9uRREt2s7AA+yzhxd1YGxvbkURLdrOwAPss4cXdWBsb25FES3azsAD7LOHF3VgbG9uRREt2s7AA+yzhxd1YGsHbqwnv0JDhtSAGsnZ7QcROo7IkzOY996Cfc5VFm/M/wzAnwvm7oV0FNQFTYyJpmDHwi26sCgpFaIEGwbEVOHnqPj7nBgZTiLseoqUTwJQHQIdX7XTw8ro9xwZj1C1mc= : : : [+] shellmates{I_though_AES_w4s_m1l1tary_gr4de_encryp7ion_1n_al1_m0des =>on_1n_al1_m0des|1111111111111 The result : 24hlQghiXP72+3R3b0COPcssf4ZxVVWb22QjqFvUHflKpunAOjAiiCYyYgsHwkZc7RWQxn0dUSE4RmsC4zHJMNelvw6iWs7poZWBqSqqqtJUkr6moH0+OlaGl6av3jYzaxLF7pKy9Of5p+mCeycoiQ== [+] shellmates{I_though_AES_w4s_m1l1tary_gr4de_encryp7ion_1n_al1_m0des =>on_1n_al1_m0des}1111111111111 The result : VJK+pqB9PjpWhpemr942M8ssf4ZxVVWb22QjqFvUHflKpunAOjAiiCYyYgsHwkZc7RWQxn0dUSE4RmsC4zHJMNelvw6iWs7poZWBqSqqqtJUkr6moH0+OlaGl6av3jYzaxLF7pKy9Of5p+mCeycoiQ== [*] flag = shellmates{I_though_AES_w4s_m1l1tary_gr4de_encryp7ion_1n_al1_m0des}
shellmates{I_though_AES_w4s_m1l1tary_gr4de_encryp7ion_1n_al1_m0des}