この大会は2022/7/2 3:00(JST)~2022/7/4 3:00(JST)に開催されました。
今回もチームで参戦。結果は405点で382チーム中112位でした。
自分で解けた問題をWriteupとして書いておきます。
ELECTRIC MAYHEM CLS (crypto)
AESの相関電力解析の問題。
9回同じ波形があり、最後の1回が似ているが特に後半が異なる波形になっている。このことからラウンド数が10のAES-128であると推測できる。平文と暗号文のペアと対応するトレースデータが50個ずつある。Square CTF 2018 の「leaky power」の問題で使ったスクリプトを流用して、秘密鍵を推測する。
#!/usr/bin/env python3 import numpy as np import json HW = [bin(n).count('1') for n in range(256)] sbox=( 0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16) def intermediate(pt, keyguess): return sbox[pt ^ keyguess] with open('traces.json', 'r') as f: input = json.load(f) NUM_TRACES = len(input) pt_list = [input[x]['pt'] for x in range(NUM_TRACES)] ct_list = [input[x]['ct'] for x in range(NUM_TRACES)] tr_list = [input[x]['pm'] for x in range(NUM_TRACES)] pt = np.array(pt_list) traces = np.array(tr_list) numtraces = np.shape(traces)[0] - 1 numpoint = np.shape(traces)[1] bestguess = [0] * 16 # Set 16 to something lower (like 1) to only go through a single subkey & save time! for bnum in range(0, 16): cpaoutput = [0] * 256 maxcpa = [0] * 256 for kguess in range(256): print('Subkey %2d, hyp = %02x: ' % (bnum, kguess), end='') # Initialize arrays & variables to zero sumnum = np.zeros(numpoint) sumden1 = np.zeros(numpoint) sumden2 = np.zeros(numpoint) hyp = np.zeros(numtraces) for tnum in range(0, numtraces): hyp[tnum] = HW[intermediate(pt[tnum][bnum], kguess)] # Mean of hypothesis meanh = np.mean(hyp, dtype=np.float64) # Mean of all points in trace meant = np.mean(traces, axis=0, dtype=np.float64) # For each trace, do the following for tnum in range(0, numtraces): hdiff = (hyp[tnum] - meanh) tdiff = traces[tnum,:] - meant sumnum = sumnum + (hdiff*tdiff) sumden1 = sumden1 + hdiff*hdiff sumden2 = sumden2 + tdiff*tdiff cpaoutput[kguess] = sumnum / np.sqrt( sumden1 * sumden2 ) maxcpa[kguess] = max(abs(cpaoutput[kguess])) print(maxcpa[kguess]) # Find maximum value of key bestguess[bnum] = np.argmax(maxcpa) print('Best Key Guess: ', end='') key = ''.join([chr(b) for b in bestguess]) print(key) flag = 'CTF{%s}' % key print('flag:', flag)
実行結果は以下の通り。
: Subkey 15, hyp = cc: 0.45401490813444945 Subkey 15, hyp = cd: 0.49010720993093665 Subkey 15, hyp = ce: 0.47146697427617695 Subkey 15, hyp = cf: 0.5068288359807762 Subkey 15, hyp = d0: 0.4838081788859939 Subkey 15, hyp = d1: 0.4854645790828718 Subkey 15, hyp = d2: 0.47397043847121284 Subkey 15, hyp = d3: 0.5154221414830332 Subkey 15, hyp = d4: 0.4634683845549041 Subkey 15, hyp = d5: 0.49131398564000117 Subkey 15, hyp = d6: 0.4967844598971371 Subkey 15, hyp = d7: 0.5193739416317773 Subkey 15, hyp = d8: 0.4572149886848642 Subkey 15, hyp = d9: 0.43301119798033977 Subkey 15, hyp = da: 0.44607019995923475 Subkey 15, hyp = db: 0.48586908211596014 Subkey 15, hyp = dc: 0.4547689799953138 Subkey 15, hyp = dd: 0.49644633789896647 Subkey 15, hyp = de: 0.48473268198250025 Subkey 15, hyp = df: 0.5015684523731578 Subkey 15, hyp = e0: 0.4855245154529038 Subkey 15, hyp = e1: 0.4773965708833608 Subkey 15, hyp = e2: 0.483905093869241 Subkey 15, hyp = e3: 0.5556550860760712 Subkey 15, hyp = e4: 0.4352508778926109 Subkey 15, hyp = e5: 0.5122373178124859 Subkey 15, hyp = e6: 0.48014300426842854 Subkey 15, hyp = e7: 0.4643384099621492 Subkey 15, hyp = e8: 0.4744772626333159 Subkey 15, hyp = e9: 0.45481497339412846 Subkey 15, hyp = ea: 0.5126674568619023 Subkey 15, hyp = eb: 0.43493989441426584 Subkey 15, hyp = ec: 0.43329852870845154 Subkey 15, hyp = ed: 0.45082959861817234 Subkey 15, hyp = ee: 0.4564515034569882 Subkey 15, hyp = ef: 0.5165751160466153 Subkey 15, hyp = f0: 0.4382706117302386 Subkey 15, hyp = f1: 0.4925133649778097 Subkey 15, hyp = f2: 0.49171365134234124 Subkey 15, hyp = f3: 0.5044774672690812 Subkey 15, hyp = f4: 0.4813231064962157 Subkey 15, hyp = f5: 0.4651318090071481 Subkey 15, hyp = f6: 0.5422507667075844 Subkey 15, hyp = f7: 0.6048876171470424 Subkey 15, hyp = f8: 0.4727434836122757 Subkey 15, hyp = f9: 0.5027699323037813 Subkey 15, hyp = fa: 0.508061038753254 Subkey 15, hyp = fb: 0.4922862591756897 Subkey 15, hyp = fc: 0.5668312430143295 Subkey 15, hyp = fd: 0.46998646853436393 Subkey 15, hyp = fe: 0.45107537517359675 Subkey 15, hyp = ff: 0.4851766132658818 Best Key Guess: W0ckAwocKaWoCka1 flag: CTF{W0ckAwocKaWoCka1}
CTF{W0ckAwocKaWoCka1}