この大会は2018/3/17 13:30(JST)~2018/3/18 1:30(JST)に開催されました。
今回もチームで参戦。結果は1616点で134チーム中3位でした。
自分で解けた問題をWriteupとして書いておきます。
RSA-2 (Crypto 200)
2組の平文の差と暗号文がわかっているので、Franklin-Reiter Related Message Attackで復号する。
# solve.sage from hashlib import sha256 def related_message_attack(c1, c2, diff, e, n): PRx.<x> = PolynomialRing(Zmod(n)) g1 = x^e - c1 g2 = (x+diff)^e - c2 def gcd(g1, g2): while g2: g1, g2 = g2, g1 % g2 return g1.monic() return -gcd(g1, g2)[0] n = 114725527397185618184017233206819193913174443780510744606142335459665478168081417742295326326458510125306461590118257162988125409459000413629137879229803717947627133370343339582895822944017711093729671794212087753322731071609302218014807365556283824229308384059742494244873283137838666434755861643308137132991 e = 12289 c1 = 87410813732157727701928184577314318681587457726095432638836338681211650253979034474596959990411435773763619929643745595561018045828590610328140736165000754846648327232298646701600080979346670157972588491030528441191645554122003288005262778737855011793921980764813901447954145380508985385929190951189001811183 c2 = 13405530225102142120310029551994876557837309021095393214835868463875586021351445304878372433515568058695315045246405214821866800311993984428311760617739453096525618753380012567374424357402936368910846206438489444245873338816383688500972351617863313954864557810634214028546221991063291427532826592675208605764 pad1 = int('qwerty'.encode('hex'), 16) pad2 = int('asdfgh'.encode('hex'), 16) diff = pad1 - pad2 m = (related_message_attack(c2, c1, diff, e, n) - pad2) >> (8 * 6) flag = ('%x' % m).decode('hex') print flag
b00t2root{M4ny_pa7hs_up_th3_m0unt4in_4ll_l3ading_t0_th3_s4me_plac3}
hlea (Crypto 200)
Hash Length Extention Attackの問題。
hash(SALT + 'a') = 既知ハッシュ hash(SALT + 'a' + '???' + 'administrator')
HashPumpを使って、'???'とハッシュ値を取得、提示することができれば、フラグが得られる。
import socket import re import subprocess def encHex(s): enc = '' xcode = '' for i in range(len(s)): if s[i] == '\\' and len(xcode) == 0: xcode += s[i] elif s[i] == 'x' and len(xcode) == 1: xcode += s[i] elif len(xcode) == 2: xcode += s[i] elif len(xcode) == 3: xcode += s[i] enc += xcode[2:] xcode = '' else: enc += '%02x' % ord(s[i]) return enc cmd_format = 'hashpump -s %s -d a -k %d -a administrator' s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('18.188.130.86', 1223)) for j in range(2): data = s.recv(1024) print data choice = '1' print choice s.sendall(choice + '\n') data = s.recv(1024) print data username = 'a' print username s.sendall(username + '\n') data = s.recv(1024) print data pattern = 'Here\'s your token\:(.+)' m = re.search(pattern, data, re.DOTALL) h = m.group(1).replace('\n', '').split(':')[1] data = s.recv(1024) print data for i in range(1, 32): print 'SALT Length: %d' % i s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('18.188.130.86', 1223)) for j in range(2): data = s.recv(1024) print data choice = '2' print choice s.sendall(choice + '\n') data = s.recv(1024) print data cmd = cmd_format % (h, i) print cmd ret = subprocess.check_output(cmd.split(' ')) print ret try_ans = ret.split('\n') token = encHex(try_ans[1]) token += ':' + try_ans[0] print token s.sendall(token + '\n') data = s.recv(1024) print data if 'Invalid Token' not in data: data = s.recv(1024) print data break
実行結果は以下の通り。
: SALT Length: 15 What do you want to do? [1] Register [2] Login Enter your choice: 2 Enter your token: hashpump -s d346d2179993563cfc0cc81ff7d31f627ca9cce5645ea5b8d0b6588d975f0396 -d a -k 15 -a administrator 30dea6e09040845ef0474fe8b15490f2afc5e36a4e14a808c065e9b054b996d2 a\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80administrator 6180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008061646d696e6973747261746f72:30dea6e09040845ef0474fe8b15490f2afc5e36a4e14a808c065e9b054b996d2 Welcome a��administrator! Here's the flag: b00t2root{51mpl3_h45h_l3ng7h_3x73n510n_4774ck} Closing connection.
b00t2root{51mpl3_h45h_l3ng7h_3x73n510n_4774ck}
unZipitCat (Forensics 150)
ZIPの既知平文攻撃。
$ zipinfo ZIPIT.zip Archive: ZIPIT.zip 1201088 bytes 5 files -rw-r--r-- 3.0 unx 47 TX stor 16-Mar-18 17:00 gg -rw-rw-r-- 3.0 unx 1023704 BX defN 13-Mar-18 23:04 catgif.gif -rw-rw-r-- 3.0 unx 186442 BX defN 13-Mar-18 23:05 minion.gif -rw-rw-r-- 3.0 unx 10342 BX defN 13-Mar-18 23:06 TaPz.gif -rw-r--r-- 3.0 unx 5 TX stor 16-Mar-18 17:01 flag 5 files, 1220540 bytes uncompressed, 1200218 bytes compressed: 1.7% $ ls -l am.gif -rwxrwxrwx 1 root root 1023704 3月 17 18:26 am.gif $ zip am.zip ./am.gif adding: am.gif (deflated 1%) $ ./pkcrack-1.2.2/src/pkcrack -C ZIPIT.zip -c catgif.gif -p am.gif -P am.zip -d decrypted.zip : Stage 2 completed. Starting zipdecrypt on Sat Mar 17 18:59:11 2018 Decrypting gg (373132b4e5a73cb6227ad66b)... OK! Decrypting catgif.gif (f9fac3f69bc4ecbde55f609c)... OK! Decrypting minion.gif (275d6236c096e1f8116f749c)... OK! Decrypting TaPz.gif (a7c27d9a7f06f41ad7e5849c)... OK! Decrypting flag (e65781eb8c4ddbbbbc1ce26b)... OK! Finished on Sat Mar 17 18:59:11 2018 $ unzip decrypted.zip Archive: decrypted.zip extracting: gg inflating: catgif.gif inflating: minion.gif inflating: TaPz.gif replace flag? [y]es, [n]o, [A]ll, [N]one, [r]ename: y extracting: flag $ cat gg b00t2root{1t_only_requ1r3s_a_k3y_noth1ng_els3}
b00t2root{1t_only_requ1r3s_a_k3y_noth1ng_els3}
Thousand Milliard (Misc 120)
SEEDを元に最初のランダムな値を求め、そこから四則演算や今の値を答えていく。
import socket import re import random 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(('18.188.130.86', 1000)) for i in range(8): data = recvuntil(s, '\n') print data if i == 2: pattern = 'SEED: (.+)\n' m = re.search(pattern, data) SEED = int(m.group(1)) random.seed(SEED) now = random.randint(0, 1000000000000) for i in range(600): print 'Round %d' % (i+1) data = recvuntil(s, '\n') print data first = data.split(' ')[0] op = data.split(' ')[2] num = data.split(' ')[4] num_sub = data.split(' ')[1] ans = '' if first == 'What': ans = str(now) elif first == 'Subtract': ans = str(now - int(num_sub)) elif op == 'added': ans = str(now + int(num)) elif op == 'multiplied': ans = str(now * int(num)) elif op == 'divided': ans = str(now / int(num)) print ans s.sendall(ans + '\n') now = int(ans) data = s.recv(1024) print data data = s.recv(1024) print data data = s.recv(1024) print data
実行結果は以下の通り。
: Round 600 Subtract 4960 from your number 739060326684744025972495958689 You did it Here is your reward b00t2root{h0pe_y0u_g0t_this_3asily}
b00t2root{h0pe_y0u_g0t_this_3asily}