この大会は2019/12/1 21:00(JST)~2019/12/26 21:00(JST)に開催されました。
今回もチームで参戦。結果は428点で948チーム中136位でした。
自分で解けた問題をWriteupとして書いておきます。
Santaty flag (misc)
Discordに入って#advent-2019チャネルを見ると、トピックにフラグが書いてあった。
General CTF Discussion - bridged with #advent on OverTheWire.org IRC -- Santaty Flag: AOTW{Testing123}
AOTW{Testing123}
7110 (keylogger, programming)
ガラケーキーパッドのログがついているので、復元する問題。101はDelete、102は左、103は右に移動する。時間が1000開いている場合は次の文字入力になっていると判断すると、入力文字を復元することができる。
KEY_ZERO = ' 0' KEY_ONE = '.,\'?!"1-()@/:' KEY_TWO = 'abc2' KEY_THREE = 'def3' KEY_FOUR = 'ghi4' KEY_FIVE = 'jkl5' KEY_SIX = 'mno6' KEY_SEVEN = 'pqrs7' KEY_EIGHT = 'tuv8' KEY_NINE = 'wxyz9' KEY_STAR = '@/:_;+&%*[]{}' def get_chr(key, count): if key == '0': return KEY_ZERO[(count-1)%len(KEY_ZERO)] elif key == '1': return KEY_ONE[(count-1)%len(KEY_ONE)] elif key == '2': return KEY_TWO[(count-1)%len(KEY_TWO)] elif key == '3': return KEY_THREE[(count-1)%len(KEY_THREE)] elif key == '4': return KEY_FOUR[(count-1)%len(KEY_FOUR)] elif key == '5': return KEY_FIVE[(count-1)%len(KEY_FIVE)] elif key == '6': return KEY_SIX[(count-1)%len(KEY_SIX)] elif key == '7': return KEY_SEVEN[(count-1)%len(KEY_SEVEN)] elif key == '8': return KEY_EIGHT[(count-1)%len(KEY_EIGHT)] elif key == '9': return KEY_NINE[(count-1)%len(KEY_NINE)] elif key == '10': return KEY_STAR[(count-1)%len(KEY_STAR)] with open('sms4.csv', 'r') as f: lines = f.readlines()[6:-17] pre_time = 0 msg = [''] * 1024 cur_key = '11' cur_count = 1 index = 0 for line in lines: csv = line.rstrip() cur_time = int(csv.split(',')[0]) key = csv.split(',')[1] if int(key) <= 10: if cur_key == '11': cur_key = key cur_count = 1 elif key != cur_key: if int(cur_key) <= 10: char = get_chr(cur_key, cur_count) msg.insert(index, char) index += 1 elif cur_key == '101': del msg[index] elif cur_key == '102': index -= 0 elif cur_key == '103': index += 2 cur_key = key cur_count = 1 elif cur_time - pre_time > 1000: char = get_chr(cur_key, cur_count) msg.insert(index, char) index += 1 cur_key = key cur_count = 1 else: cur_count += 1 else: if int(cur_key) <= 10: char = get_chr(cur_key, cur_count) msg.insert(index, char) else: if cur_key == '101': del msg[index] index -= 1 elif cur_key == '102': index -= 1 elif cur_key == '103': index += 1 cur_count = 1 cur_key = key pre_time = cur_time char = get_chr(cur_key, cur_count) msg.insert(index, char) msg = ''.join(msg) print msg
実行結果は以下の通り。
alright pal heres ye flag good luck entering it with those hooves lol its aotw{l3ts_dr1nk_s0m3_eggn0g_y0u_cr4zy_d33r}
AOTW{l3ts_dr1nk_s0m3_eggn0g_y0u_cr4zy_d33r}
Sudo Sudoku (misc, sudoku)
Sudokuのルールなど条件を指定して、z3で解く。フラグは左上から時計回りに外周の数字を並べて、フラグの形式にしたもの。
from z3 import * #### Rules of Sudoku #### def betweenOneToNine(val, s): for i in range(n): for j in range(n): s.add(1 <= val[i][j], val[i][j] <= n) def distinctRow(val, s): for i in range(n): tmpList = [] for j in range(n): tmpList.append(val[i][j]) s.add(Distinct(tmpList)) def distinctColumn(val, s): for i in range(n): tmpList = [] for j in range(n): tmpList.append(val[j][i]) s.add(Distinct(tmpList)) def distinctBlock(val, s): for k in range(3): for l in range(3): tmpList = [] for i in range(3): for j in range(3): tmpList.append(val[3*k+i][3*l+j]) s.add(Distinct(tmpList)) #### Set known numbers #### def setNum(val,s,x,y,num): s.add(val[x-1][y-1] == num) def condition1(val, s): setNum(val, s, 1, 9, 1) setNum(val, s, 2, 2, 1) setNum(val, s, 2, 3, 2) setNum(val, s, 3, 7, 2) setNum(val, s, 4, 9, 2) setNum(val, s, 5, 2, 2) setNum(val, s, 7, 7, 1) setNum(val, s, 8, 1, 1) setNum(val, s, 8, 6, 2) setNum(val, s, 9, 4, 1) #### Add other conditions #### def condition2(val, s): s.add(val[1][8] + val[1][7] + val[2][0] + val[7][3] + val[7][3] == 23) s.add(val[0][4] + val[3][6] + val[8][4] + val[6][7] + val[1][2] + val[0][4] == 19) s.add(val[8][1] + val[8][2] + val[5][1] + val[4][8] == 15) s.add(val[8][6] + val[7][7] + val[2][1] + val[3][8] == 26) s.add(val[8][5] + val[0][4] + val[8][2] + val[1][7] + val[2][2] == 20) s.add(val[8][6] + val[3][8] + val[1][5] + val[0][7] + val[0][2] + val[2][3] == 27) s.add(val[2][6] + val[7][8] + val[8][6] + val[1][1] + val[7][7] + val[6][2] == 31) s.add(val[3][2] + val[8][7] + val[0][3] + val[8][5] == 27) s.add(val[5][4] + val[1][7] + val[5][7] + val[8][6] + val[5][0] == 33) s.add(val[0][1] + val[0][7] + val[3][6] + val[4][3] == 21) s.add(val[2][0] + val[8][3] + val[2][1] + val[8][0] + val[0][3] == 20) s.add(val[5][7] + val[2][0] + val[5][5] + val[3][2] + val[1][5] == 25) #### n * n values #### n = 9 val = [[Int("val[%d,%d]" % (i,j)) for j in range(n)] for i in range(n)] s = Solver() #### add conditions #### betweenOneToNine(val, s) distinctRow(val, s) distinctColumn(val, s) distinctBlock(val, s) condition1(val, s) condition2(val, s) #### solve #### r = s.check() if r == sat: m = s.model() for i in range(n): for j in range(n): print('%d' % m[val[i][j]].as_long()), print else: print(r) #### print flag #### flag = '' i = 0 j = 0 while j < n - 1: flag += str(m[val[i][j]].as_long()) j += 1 while i < n - 1: flag += str(m[val[i][j]].as_long()) i += 1 while j > 0: flag += str(m[val[i][j]].as_long()) j -= 1 while i > 0: flag += str(m[val[i][j]].as_long()) i -= 1 flag = 'AOTW{%s}' % flag print flag
実行結果は以下の通り。
8 6 4 7 2 9 5 3 1 9 1 2 4 5 3 7 6 8 3 7 5 6 1 8 2 4 9 6 4 9 8 7 5 3 1 2 7 2 1 9 3 6 8 5 4 5 3 8 2 4 1 6 9 7 4 8 6 5 9 7 1 2 3 1 9 7 3 6 2 4 8 5 2 5 3 1 8 4 9 7 6 AOTW{86472953189247356794813521457639}
AOTW{86472953189247356794813521457639}
Easter Egg 2 (fun)
問題が増えるとき(?)に出現するっぽい画像(以下のURL)にアクセスする。
https://advent2019.overthewire.org/static/img/transparent-santa-gif-flying.gif
レスポンスヘッダに以下が設定されている。
X-EasterEgg2: ==QftRHdz8VZydmZuNzXhJ3MxcGMltnSHJkT
base64文字列が反転されているので、反転してデコードする。
$ echo ==QftRHdz8VZydmZuNzXhJ3MxcGMltnSHJkT | rev | base64 -d NBGJ{e0g13ra_3nfgre_3ttm}
さらにROT13のデコードをする。
$ echo ==QftRHdz8VZydmZuNzXhJ3MxcGMltnSHJkT | rev | base64 -d | tr '[A-Za-z]' '[N-ZA-Mn-za-m]' AOTW{r0t13en_3aster_3ggz}
AOTW{r0t13en_3aster_3ggz}
Santa's Signature (crypto)
$ nc 3.93.128.89 1219 Dear Santa, Last christmas you gave me your public key, to confirm it really is you please sign three different messages with your private key. Here is the public key you gave me: -----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAu1jb39GZlWh9XPpOHmaa ZEYrbNqa6KMf4E211NYklZytuRBQy71zOI8V9O7i12C4hjhoAzj8JnXkpFur7w3z PLimVB/B+KfQq3fo5YqWzVhi06LuuCvyGwkWSO3K2sMyH3ISKlPKlyVzhr/9qeHR 2gbFXK6so8rHXpZGgSJk5TimuY4yb+TNjpfi4srQIyepVPCjECs4n+Ii941c+7KW 2wScAUk7MuMExuKuNvvKeTZdhQeq/ZCd0otascBXk9GmsBx0eVBzG8/94Hm+9egl eQu1DqLn/HZovaAcyIbqjunuB/KoM76DISjhmcaRyipafEJm+u9/jPHAG+8dLUuc Wr+04D9iAFBEt5XBA2u3WaaL4/eP7hR5mR9QOxH8YilpttfQJY/78AXo+GJtECTF LJ7zRyP1Jq89qdySJVumxwZmKP3sE7mojTb2030TDF/27v+vMVVtczyAQdybDHzj 8ainHn2SP3yTTOnjNTuGWvIcs3Qa4bv78ezTmLofpsZLoRbcx5FV2YXuiao8ezD/ WBuIOlDZhqRiods3LN8x7gNQo8zDmwY0Z54oac2dPgIUr1AvnDbEGdqyCyJRIrnW kLFMXdy2GJLSFMk+rswORKEtojCmqQIydW7+5M4J4FhVNyVtNuPcLfUjF+e5+V5E +piEcAsCnQ1k9QHGZAuVxX8CAwEAAQ== -----END PUBLIC KEY----- Message 1 you signed (hex encoded):12 Signature 1:1 Looks like you aren't Santa after all!
RSA署名で暗号と平文の組を3パターン答えればよいだけ。
import socket from Crypto.PublicKey import RSA def recvuntil(s, tail): data = '' while True: if tail in data: return data data += s.recv(1) sc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sc.connect(('3.93.128.89', 1219)) data = recvuntil(sc, 'END PUBLIC KEY-----\n').rstrip() print data pub_pem = '\n'.join(data.split('\n')[6:]) pub_key = RSA.importKey(pub_pem) n = pub_key.n e = pub_key.e for i in range(1, 4): m = hex(pow(i, e, n))[2:].rstrip('L') s = i data = recvuntil(sc, '(hex encoded):') print data + str(m) sc.sendall(str(m) + '\n') data = recvuntil(sc, ':') print data + str(s) sc.sendall(str(s) + '\n') data = recvuntil(sc, '\n').rstrip() print data data = recvuntil(sc, '\n').rstrip() print data
実行結果は以下の通り。
Dear Santa, Last christmas you gave me your public key, to confirm it really is you please sign three different messages with your private key. Here is the public key you gave me: -----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAu1jb39GZlWh9XPpOHmaa ZEYrbNqa6KMf4E211NYklZytuRBQy71zOI8V9O7i12C4hjhoAzj8JnXkpFur7w3z PLimVB/B+KfQq3fo5YqWzVhi06LuuCvyGwkWSO3K2sMyH3ISKlPKlyVzhr/9qeHR 2gbFXK6so8rHXpZGgSJk5TimuY4yb+TNjpfi4srQIyepVPCjECs4n+Ii941c+7KW 2wScAUk7MuMExuKuNvvKeTZdhQeq/ZCd0otascBXk9GmsBx0eVBzG8/94Hm+9egl eQu1DqLn/HZovaAcyIbqjunuB/KoM76DISjhmcaRyipafEJm+u9/jPHAG+8dLUuc Wr+04D9iAFBEt5XBA2u3WaaL4/eP7hR5mR9QOxH8YilpttfQJY/78AXo+GJtECTF LJ7zRyP1Jq89qdySJVumxwZmKP3sE7mojTb2030TDF/27v+vMVVtczyAQdybDHzj 8ainHn2SP3yTTOnjNTuGWvIcs3Qa4bv78ezTmLofpsZLoRbcx5FV2YXuiao8ezD/ WBuIOlDZhqRiods3LN8x7gNQo8zDmwY0Z54oac2dPgIUr1AvnDbEGdqyCyJRIrnW kLFMXdy2GJLSFMk+rswORKEtojCmqQIydW7+5M4J4FhVNyVtNuPcLfUjF+e5+V5E +piEcAsCnQ1k9QHGZAuVxX8CAwEAAQ== -----END PUBLIC KEY----- Message 1 you signed (hex encoded):1 Signature 1:1 Message 2 you signed (hex encoded):5bf10144e9e96f26774f5750df1083d68ee461e4e4932291b0a511c5f2f8860db89470008ed3971b92d91a8b6ec8bc122f1ca5f3beb7533b014604f633da5b83ebed3d8f092f0636b50e62a492a407c35357b30815b78c55a5dcf40ce5b94cf8b6aebc67a596e56ea171f938e27671a4dae3d2dc9ae3f79624579123a166e5745c24799f490e5d8e2d00709445366c9278ed65aff3930daa5aeeab58ea566b636e7f72973ab9ed7b0af698fb3dc9ea5c2d4ebc330a7ef06fa457ff27f6f697fb047b8046f2e801b97e7d753ef8c07089082ff1e1f8bea9ff1c8023f054f0640f109c5aa055e96743cb09d07651334c483ebdebe8482e7a723ee308d6f7398fa792461badea070b2cf2c850ad20dd236f7ed6832702c27896c408ff34716215e0d9e9907e0b9ce9fb08f8c0b81619255eff9d046ca1d665b355e948e3e6cf5a377ac3e09f73c008a07975e20ed164458deee1cd019d6a9eb64e1472fa40388fec77c16ed57147cbc193477923eb5d6ac352d65e0934f815c5915608855959b5e28b425f9b1fbd42348c6128efe1307c9bc1fd8df8b2ac6911f3905be0d6bbdc11c8a7b50c800879f4665a7cd241230805173e9a88b90d95246fd7d1056c7bcdb66f6f096321c07a978720ba8a38114331e2539fd54fe484c093becdcbe38f16120f356b330de703835efc5421e39124ccb4d289e94cfc9fb5f0d846b8cd94a577 Signature 2:2 Message 3 you signed (hex encoded):4ae2bad4c417894d61336509fd5bbed5d698d2dd666dd4b3e022f022a99ca96963b22a582227634b328b7a209ebaaa8dfc026193f542706cce3b517df79314c0cfd2932d8a342361e902717145c66965d289b3dc175a26546a7860bb0f6c7894ae741a6c8793c796d267f67680c8a19375cfbad66346327def10a499ee9b70ba1eb8a74c52ddd70dae2e7f3bbedaa1f24d497d7382dbca8ba2f091f054bcfd6edb69f1ba0f43195c23edf288bf0694980d38f3df75c5eaafc2e3ca21a92b8d896b2e20e9ddc7e64817dbc6c92b856cd3184468093e2cab9bb004ffcd376e8bd08261673e9a9fd70e003f255cf76628d446cc343ae8d2b5f2396266e8845087e31e046039363b90aba5cb63dbb84eac5bdd0016e72ed3e32c06b1fe82f317f5bfe629a989b8b3df614f501305055a4806fdbc1a37dedbd1cba85205f1391be9bcfdfd9d4947568ed3d0f9cfb09443f8bc757addb2da4d9e6e6f0fd152d3c82c0771a379236d94aabe9ad9309b2486dd5927c2a5fcc4ace15217cae3bd7842e6eaaf3b82869c0caf5c2415ab5f66488607d21ca520a5818b262274997d44dfd27dbc7e9ce27445f57f8dcb8164fec46842e19eb686682446f1ed2c36218794e9447133ff0e883e91e874f9597704d6776aa686cd328080343014423963ae23ba4884d9df62f5694a3aeb1c7ccef01465ebef2db366fd70fb6a7cd260cef9c46797 Signature 3:3 Hello Santa, here is your flag: AOTW{RSA_3dg3_c4s3s_ftw}
AOTW{RSA_3dg3_c4s3s_ftw}
Survey (misc)
アンケートに答えたら、フラグが表示された。
AOTW{Surv3y5_5h0w_7h4t_5urv3ys_n3v3r_l13}