この大会は2019/3/16 20:00(JST)~2019/3/17 20:00(JST)に開催されました。
今回もチームで参戦。結果は330点で546チーム中56位でした。
自分で解けた問題をWriteupとして書いておきます。
Sanity check (warmup)
freenodeで#p4teamチャネルに接続する。
20:01 *topic : Teaser lasts from March 16th 11:00UTC to March 17th 11:00UTC | https://confidence2019.p4.team | p4{thanks_for_playing_:)}
p4{thanks_for_playing_:)}
Count me in! (crypto, warmup)
AESのCTRもどき。各ブロックごとに並列で暗号化するが、カウンターを共有しており、61ブロックを32本の同時並行処理だと同じカウンターを使う確率が高い。フラグの部分以外は平文と暗号文が分かっている。
各ブロックの平文と暗号文のXORのどれかがフラグの各ブロックの平文と暗号文のXORになっていると推測し、復号する。
def chunk(input_data, size): return [input_data[i:i + size] for i in range(0, len(input_data), size)] def xor(*t): from functools import reduce from operator import xor return [reduce(xor, x, 0) for x in zip(*t)] def xor_string(t1, t2): t1 = map(ord, t1) t2 = map(ord, t2) return "".join(map(chr, xor(t1, t2))) def is_printable(s): for c in s: if ord(c) < 32 or ord(c) > 126: return False return True def unpad(s): return s[:-ord(s[-1])] pt_head = """The Song of the Count You know that I am called the Count Because I really love to count I could sit and count all day Sometimes I get carried away I count slowly, slowly, slowly getting faster Once I've started counting it's really hard to stop Faster, faster. It is so exciting! I could count forever, count until I drop 1! 2! 3! 4! 1-2-3-4, 1-2-3-4, 1-2, i love couning whatever the ammount haha! 1-2-3-4, heyyayayay heyayayay that's the sound of the count I count the spiders on the wall... I count the cobwebs in the hall... I count the candles on the shelf... When I'm alone, I count myself! I count slowly, slowly, slowly getting faster Once I've started counting it's really hard to stop Faster, faster. It is so exciting! I could count forever, count until I drop 1! 2! 3! 4! 1-2-3-4, 1-2-3-4, 1, 2 I love counting whatever the ammount! 1-2-3-4 heyayayay heayayay 1-2-3-4 That's the song of the Count! """ with open('output.txt', 'r') as f: enc = f.read().decode('hex') enc_list = chunk(enc, 16) pt_head_list = chunk(pt_head, 16) flag = '' for i in range(4): enc_flag_parts = enc_list[i - 4] for j in range(len(enc_list) - 4): key = xor_string(enc_list[j], pt_head_list[j]) dec_flag_parts = xor_string(enc_flag_parts, key) if i == 3: dec_flag_parts = unpad(dec_flag_parts) if is_printable(dec_flag_parts): flag += dec_flag_parts print flag
p4{at_the_end_of_the_day_you_can_only_count_on_yourself}
Bro, do you even lift? (crypto)
p(=35671)の1乗からpの100乗までmodulusを段階的に増やし、元のデータに近づいていくような方式でフラグを求める。
from Crypto.Util.number import * p = 35671 a1 = 12172655049735206766902704703038559858384636896299329359049381021748 a2 = 11349632906292428218038992315252727065628405382223597973250830870345 a3 = 9188725924715231519926481580171897766710554662167067944757835186451 a4 = 8640134917502441100824547249422817926745071806483482930174015978801 a5 = 170423096151399242531943631075016082117474571389010646663163733960337669863762406085472678450206495375341400002076986312777537466715254543510453341546006440265217992449199424909061809647640636052570307868161063402607743165324091856116789213643943407874991700761651741114881108492638404942954408505222152223605412516092742190317989684590782541294253512675164049148557663016927886803673382663921583479090048005883115303905133335418178354255826423404513286728 pre_base = [0] for i in range(1, 101): tmp_a1 = a1 % (p**i) tmp_a2 = a2 % (p**i) tmp_a3 = a3 % (p**i) tmp_a4 = a4 % (p**i) tmp_a5 = a5 % (p**i) base = [] for b in pre_base: for x in range(p): y = b + x * (p**(i-1)) f = (tmp_a1 * y**4 + tmp_a2 * y**3 + tmp_a3 * y**2 + tmp_a4 * y + tmp_a5) % (p**i) if f == 0: base.append(y) pre_base = base print '%03d' % i, pre_base for b in pre_base: flag = long_to_bytes(b) if flag.startswith('p4{'): print flag
p4{Th4t5_50m3_h34vy_l1ft1n9}