この大会は2016/11/17 16:00(JST)~2016/11/18 23:00(JST)に開催されました。
今回もチームで参戦。結果は1500点で680チーム中78位でした。
自分で解けた問題をWriteupとして書いておきます。
Reverse 100_2 (Reverse 100)
pycファイルが与えられているので、Easy Python Decompilerでデコンパイルする。
# Embedded file name: task.py import marshal src = 'YwAAAAADAAAAGAAAAEMAAABz7wAAAGQBAGoAAGcAAGQCAGQDAGQEAGQFAGQGAGQHAGQIAGQJAGQKAGQLAGQMAGQNAGQOAGQPAGQMAGcPAERdHAB9AAB0AQB0AgB8AACDAQBkEAAXgwEAXgIAcToAgwEAfQEAdAMAZBEAgwEAfQIAfAIAfAEAawIAcuYAZAEAagAAZwAAZBIAZBMAZBQAZBUAZBYAZBcAZBgAZBkAZBoAZBsAZBwAZB0AZB4AZAsAZBwAZB8AZAMAZB0AZAgAZB4AZCAAZCEAZxYARF0VAH0AAHwAAGoEAGQiAIMBAF4CAHHGAIMBAEdIbgUAZCMAR0hkAABTKCQAAABOdAAAAAB0AQAAAF50AQAAADR0AQAAAEt0AQAAAGl0AQAAAC50AQAAAC90AQAAAE50AQAAAGp0AQAAAFB0AQAAAG90AQAAAD90AQAAAGx0AQAAADJ0AQAAAFRpAwAAAHMJAAAAWW91IHBhc3M6dAEAAABzdAEAAAB5dAEAAABudAEAAAB0dAEAAAA6dAEAAAB7dAEAAAB3dAEAAABxdAEAAABFdAEAAAA2dAEAAABmdAEAAABYdAEAAAB1dAEAAABhdAEAAAAxdAEAAAB9dAUAAABST1QxM3MFAAAATm8gOigoBQAAAHQEAAAAam9pbnQDAAAAY2hydAMAAABvcmR0CQAAAHJhd19pbnB1dHQGAAAAZGVjb2RlKAMAAAB0AQAAAGV0AwAAAHRtcHQGAAAAcGFzc3dkKAAAAAAoAAAAAHMHAAAAdGFzay5weVIcAAAAAgAAAHMKAAAAAAFfAQwBDAFvAQ=='.decode('base64') code = marshal.loads(src) exec code
pycのヘッダを付けてauth.pycを作成する。
#!/usr/bin/env python code = 'YwAAAAADAAAAGAAAAEMAAABz7wAAAGQBAGoAAGcAAGQCAGQDAGQEAGQFAGQGAGQHAGQIAGQJAGQKAGQLAGQMAGQNAGQOAGQPAGQMAGcPAERdHAB9AAB0AQB0AgB8AACDAQBkEAAXgwEAXgIAcToAgwEAfQEAdAMAZBEAgwEAfQIAfAIAfAEAawIAcuYAZAEAagAAZwAAZBIAZBMAZBQAZBUAZBYAZBcAZBgAZBkAZBoAZBsAZBwAZB0AZB4AZAsAZBwAZB8AZAMAZB0AZAgAZB4AZCAAZCEAZxYARF0VAH0AAHwAAGoEAGQiAIMBAF4CAHHGAIMBAEdIbgUAZCMAR0hkAABTKCQAAABOdAAAAAB0AQAAAF50AQAAADR0AQAAAEt0AQAAAGl0AQAAAC50AQAAAC90AQAAAE50AQAAAGp0AQAAAFB0AQAAAG90AQAAAD90AQAAAGx0AQAAADJ0AQAAAFRpAwAAAHMJAAAAWW91IHBhc3M6dAEAAABzdAEAAAB5dAEAAABudAEAAAB0dAEAAAA6dAEAAAB7dAEAAAB3dAEAAABxdAEAAABFdAEAAAA2dAEAAABmdAEAAABYdAEAAAB1dAEAAABhdAEAAAAxdAEAAAB9dAUAAABST1QxM3MFAAAATm8gOigoBQAAAHQEAAAAam9pbnQDAAAAY2hydAMAAABvcmR0CQAAAHJhd19pbnB1dHQGAAAAZGVjb2RlKAMAAAB0AQAAAGV0AwAAAHRtcHQGAAAAcGFzc3dkKAAAAAAoAAAAAHMHAAAAdGFzay5weVIcAAAAAgAAAHMKAAAAAAFfAQwBDAFvAQ==' PYC_HEADER = '\x03\xf3\x0d\x0a\x14\x0c\xf4\x57' data = code.decode('base64') data = PYC_HEADER + data with open('auth.pyc', 'wb') as f: f.write(data)
auth.pycをEasy Python Decompilerでデコンパイルする。
# Embedded file name: task.py tmp = ''.join([ chr(ord(e) + 3) for e in ['^', '4', 'K', 'i', '.', '/', 'N', 'j', 'P', 'o', '?', 'l', '2', 'T', '?'] ]) passwd = raw_input('You pass:') if passwd == tmp: print ''.join([ e.decode('ROT13') for e in ['s', 'y', 'n', 't', ':', '{', 'w', 'q', 'E', '6', 'f', 'X', 'u', 'o', 'f', 'a', '4', 'X', 'N', 'u', '1', '}'] ]) else: print 'No :('
tmpを表示させ、その値を入力すると、フラグが表示された。
>python auth.py You pass:a7Nl12QmSrBo5WB flag:{jdR6sKhbsn4KAh1}
jdR6sKhbsn4KAh1
Reverse 200_1 (Reverse 200)
pyファイルが与えられている、Reverse 100_2 と似たような問題。pycのヘッダを付けてauth.pycを作成する。
#!/usr/bin/env python code = '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' PYC_HEADER = '\x03\xf3\x0d\x0a\x14\x0c\xf4\x57' data = code.decode('base64') data = PYC_HEADER + data with open('auth.pyc', 'wb') as f: f.write(data)
auth.pycをEasy Python Decompilerでデコンパイルする。
# Embedded file name: task1.py passwd = raw_input('You pass:') if ''.join([ chr(ord(e[0]) ^ ord(e[1])) for e in zip('PQ1OJiRWAitBJg5QP2A='.decode('base64'), passwd) ]) == ''.join((e.decode('ROT13') for e in ['t', 'P', 'a', 'B', 'J', 'i', 'b', 'E', 'n', 'W', 't', '6', 'M', 'N'])): print ''.join([ [ chr(ord(e) + 30) for e in ''.join([ e.decode('ROT13') for e in ['K', 'm', 'L', 'g', 'K', 'G', 'A', 'C', 'A', 'E', 'k', 'U', 'F', 'I', 'E', 'W', 'S', 'H', 'k', 'p', 'D', 'm', 'x', 'x', 'D', '0', '4', 'J', 'E', 'F', 'q', 'V'] ]).decode('base64')[::-1] ][i] + [ chr(ord(e) + 30) for e in ''.join([ e.decode('ROT13') for e in ['K', 'm', 'L', 'g', 'K', 'G', 'A', 'C', 'A', 'E', 'k', 'U', 'F', 'I', 'E', 'W', 'S', 'H', 'k', 'p', 'D', 'm', 'x', 'x', 'D', '0', '4', 'J', 'E', 'F', 'q', 'V'] ]).decode('base64')[::-1] ][i + 4] + [ chr(ord(e) + 30) for e in ''.join([ e.decode('ROT13') for e in ['K', 'm', 'L', 'g', 'K', 'G', 'A', 'C', 'A', 'E', 'k', 'U', 'F', 'I', 'E', 'W', 'S', 'H', 'k', 'p', 'D', 'm', 'x', 'x', 'D', '0', '4', 'J', 'E', 'F', 'q', 'V'] ]).decode('base64')[::-1] ][i + 4 + 4] + [ chr(ord(e) + 30) for e in ''.join([ e.decode('ROT13') for e in ['K', 'm', 'L', 'g', 'K', 'G', 'A', 'C', 'A', 'E', 'k', 'U', 'F', 'I', 'E', 'W', 'S', 'H', 'k', 'p', 'D', 'm', 'x', 'x', 'D', '0', '4', 'J', 'E', 'F', 'q', 'V'] ]).decode('base64')[::-1] ][i + 4 + 4 + 4] + [ chr(ord(e) + 30) for e in ''.join([ e.decode('ROT13') for e in ['K', 'm', 'L', 'g', 'K', 'G', 'A', 'C', 'A', 'E', 'k', 'U', 'F', 'I', 'E', 'W', 'S', 'H', 'k', 'p', 'D', 'm', 'x', 'x', 'D', '0', '4', 'J', 'E', 'F', 'q', 'V'] ]).decode('base64')[::-1] ][i + 4 + 4 + 4 + 4] + [ chr(ord(e) + 30) for e in ''.join([ e.decode('ROT13') for e in ['K', 'm', 'L', 'g', 'K', 'G', 'A', 'C', 'A', 'E', 'k', 'U', 'F', 'I', 'E', 'W', 'S', 'H', 'k', 'p', 'D', 'm', 'x', 'x', 'D', '0', '4', 'J', 'E', 'F', 'q', 'V'] ]).decode('base64')[::-1] ][i + 4 + 4 + 4 + 4 + 4] for i in range(4) ]) else: print 'No :('
最初の条件の==を!=にして、適当なpassを入力すると、フラグが表示された。
>python auth.py You pass:aa flag:{EazrSKcBjgmT4W3eQ}
EazrSKcBjgmT4W3eQ
Crypto 100_1 (Crypto 100)
数字とアンダースコア(_)のみの暗号。数字2文字で、1つのアルファベットに対応すると考え、コードを書く。
alp = {'11': 'a', '12': 'b', '13': 'c', '14': 'd', '15': 'e', '21': 'f', '22': 'g', '23': 'h', '24': 'i', '25': 'k', '31': 'l', '32': 'm', '33': 'n', '34': 'o', '35': 'p', '41': 'q', '42': 'r', '43': 's', '44': 't', '45': 'u', '51': 'v', '52': 'w', '53': 'x', '54': 'y', '55': 'z' } with open('code.txt', 'r') as f: lines = f.readlines() for line in lines: s = '' code = '' for i in range(len(line)): c = line[i] if c == '_': s += c else: code += c if len(code) == 2: s += alp[code] code = '' print s
実行すると、以下の文になる。
wake_up_neo the_matrix_has_you follow_the_white_qabbit knock_knock_neo the_flag_is_the_third_line
follow_the_white_qabbitだと通らないので、最後の単語を意味のある単語に変える。
follow_the_white_rabbit
Crypto 400_1 (Crypto 400)
3組のN,Cが与えられ、eは3...ということでHastad's broadcast attackで攻撃する。
#!/usr/bin/env python3 n1 = 95118357989037539883272168746004652872958890562445814301889866663072352421703264985997800660075311645555799745426868343365321502734736006248007902409628540578635925559742217480797487130202747020211452620743021097565113059392504472785227154824117231077844444672393221838192941390309312484066647007469668558141 n2 = 98364165919251246243846667323542318022804234833677924161175733253689581393607346667895298253718184273532268982060905629399628154981918712070241451494491161470827737146176316011843738943427121602324208773653180782732999422869439588198318422451697920640563880777385577064913983202033744281727004289781821019463 n3 = 68827940939353189613090392226898155021742772897822438483545021944215812146809318686510375724064888705296373853398955093076663323001380047857809774866390083434272781362447147441422207967577323769812896038816586757242130224524828935043187315579523412439309138816335569845470021720847405857361000537204746060031 c1 = 64830446708169012766414587327568812421130434817526089146190136796461298592071238930384707543318390292451118980302805512151790248989622269362958718228298427212630272525186478627299999847489018400624400671876697708952447638990802345587381905407236935494271436960764899006430941507608152322588169896193268212007 c2 = 96907490717344346588432491603722312694208660334282964234487687654593984714144825656198180777872327279250667961465169799267405734431675111035362089729249995027326863099262522421206459400405230377631141132882997336829218810171728925087535674907455584557956801831447125486753515868079342148815961792481779375529 c3 = 43683874913011746530056103145445250281307732634045437486524605104639785469050499171640521477036470750903341523336599602288176611160637522568868391237689241446392699321910723235061180826945464649780373301028139049288881578234840739545000338202917678008269794179100732341269448362920924719338148857398181962112 import functools import itertools def chinese_remainder(n, a): sum = 0 prod = functools.reduce(lambda a, b: a*b, n) for n_i, a_i in zip(n, a): p = prod // n_i sum += a_i * mul_inv(p, n_i) * p return sum % prod def mul_inv(a, b): b0 = b x0, x1 = 0, 1 if b == 1: return 1 while a > 1: q = a // b a, b = b, a%b x0, x1 = x1 - q * x0, x0 if x1 < 0: x1 += b0 return x1 def inv_pow(c, e): low = -1 high = c+1 while low + 1 < high: m = (low + high) // 2 p = pow(m, e) if p < c: low = m else: high = m m = high assert pow(m, e) == c return m N = [n1, n2, n3] C = [c1, c2, c3] e = len(N) a = chinese_remainder(N, C) for n, c in zip(N, C): assert a % n == c m = inv_pow(a, e) print(bytes.fromhex(hex(m)[2:]).decode())
実行すると復号される。
theoretical_computer_scientist_johan_torkel_hastad
PPC 100_1(PPC 100)
年月日、曜日がファイル名に含まれているファイルが7937個与えられる。どうやら日付と曜日が合っているものを探せばよいらしい。コードは以下の通り。
import os import datetime WEEK_DAYS = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] files = os.listdir('messages\\') for file in files: str_date = file.split('.')[0] dweek = str_date.split('_', 1)[0] date = str_date.split('_', 1)[1] d = datetime.datetime.strptime(date, '%d_%B_%Y') if WEEK_DAYS[d.weekday()] == dweek: print file with open('messages\\' + file, 'r') as f: print f.read()
実行すると該当するファイルが1つだけ見つかり、ファイルの中身がフラグであった。
4eec2cd9e4bb0062d0e41c8af1bd8a0f