TokyoWesterns CTF 5th 2019 Writeup

この大会は2019/8/31 9:00(JST)~2019/9/2 9:00(JST)に開催されました。
今回もチームで参戦。結果は557点で1005チーム中75位でした。
自分で解けた問題をWriteupとして書いておきます。

Welcome!! (Misc, Warmup)

問題文にフラグが書いてあった。

TWCTF{Welcome_to_TWCTF_2019!!!}

real-baby-rsa (Crypto, Warmup)

RSA暗号だが、フラグを1文字ずつ暗号している。1文字ずつ総当たりで復号する。

N = 36239973541558932215768154398027510542999295460598793991863043974317503405132258743580804101986195705838099875086956063357178601077684772324064096356684008573295186622116931603804539480260180369510754948354952843990891989516977978839158915835381010468654190434058825525303974958222956513586121683284362090515808508044283236502801777575604829177236616682941566165356433922623572630453807517714014758581695760621278985339321003215237271785789328502527807304614754314937458797885837846005142762002103727753034387997014140695908371141458803486809615038309524628617159265412467046813293232560959236865127539835290549091
e = 65537

with open('output', 'r') as f:
    cs = f.readlines()

dic = {}
for code in range(32, 127):
    enc = pow(code, e, N)
    dic[enc] = chr(code)

flag = ''
for c in cs:
    flag += dic[int(c.rstrip())]

print flag
TWCTF{padding_is_important}

Simple Logic (Crypto)

暗号化は鍵と論理和を取って(128ビットより上位は切り捨て)、鍵とXORすることを768回繰り返す。
鍵の違いは対応するビットから上位数ビットまでしか影響しないので、下位ビットから求める。鍵が求められたら、フラグはそのまま復号関数を使うだけ。

ROUNDS = 765
BITS = 128

def encrypt(msg, key):
    enc = msg
    mask = (1 << BITS) - 1
    for i in range(ROUNDS):
        enc = (enc + key) & mask
        enc = enc ^ key
    return enc

def decrypt(msg, key):
    enc = msg
    mask = (1 << BITS) - 1
    for i in range(ROUNDS):
        enc = enc ^ key
        enc = (enc - key) & mask
    return enc

enc_flag = 0x43713622de24d04b9c05395bb753d437
pt1 = 0x29abc13947b5373b86a1dc1d423807a
ct1 = 0xb36b6b62a7e685bd1158744662c5d04a
pt2 = 0xeeb83b72d3336a80a853bf9c61d6f254
ct2 = 0x614d86b5b6653cdc8f33368c41e99254
pt3 = 0x7a0e5ffc7208f978b81475201fbeb3a0
ct3 = 0x292a7ff7f12b4e21db00e593246be5a0
pt4 = 0xc464714f5cdce458f32608f8b5e2002e
ct4 = 0x64f930da37d494c634fa22a609342ffe
pt5 = 0xf944aaccf6779a65e8ba74795da3c41d
ct5 = 0xaa3825e62d053fb0eb8e7e2621dabfe7
pt6 = 0x552682756304d662fa18e624b09b2ac5
ct6 = 0xf2ffdf4beb933681844c70190ecf60bf

pt = [pt1, pt2, pt3, pt4, pt5, pt6]
ct = [ct1, ct2, ct3, ct4, ct5, ct6]

key = ''
for i in range(1, BITS + 1):
    for k in range(8):
        tmp_key = int(bin(k)[2:] + key, 2)
        found = True
        for j in range(6):
            enc = encrypt(pt[j], tmp_key)
            if bin(enc)[-i-2:] != bin(ct[j])[-i-2:]:
                found = False
        if found:
            key = bin(k)[-1] + key
            break

key = int(key, 2)
print 'key =', key

flag = decrypt(enc_flag, key)
flag = 'TWCTF{%x}' % flag
print flag

実行結果は以下の通り。

key = 62900030173734087782946667685685220617
TWCTF{ade4850ad48b8d21fa7dae86b842466d}
TWCTF{ade4850ad48b8d21fa7dae86b842466d}