BackdoorCTF 2019 Writeup

この大会は2019/10/27 0:30(JST)~2019/10/28 0:30(JST)に開催されました。
今回もチームで参戦。結果は1336点で128チーム中7位でした。
自分で解けた問題をWriteupとして書いておきます。

minecraft (crypto)

$ cat mine.py
def revmine(block):
    bl = block
    i = 0
    while True:
        i+=1
        sid = hexhash(long_to_bytes(block['nonce'])+long_to_bytes(i)+block['prev'].encode('utf-8'))
        if sid[:3] == '000':
            bl['data'] = i
            bl['self'] = sid
            bl['nonce'] = (s1*i+s2)%s3
            return bl

flag.encの内容は以下の形式で37個のデータが入っている。

[{"self": <sid>, "hashalg": "sha256", "prev": <sha256>, "data": <i>, "nonce": <(s1*i+s2)%s3>}, ...]

nonceは書き換えられている。一つのデータでハッシュの計算からブルートフォースで試してみると元のnonceは100前後の数値になった。ASCIIコードとして文字にできるかもしれない。
また、prevの値は他のデータのselfで設定されているものばかりで、prevが0000000000000000のデータがあるのでそのデータから始まると推測できる。順番に並び替え、それぞれ元のnonceから文字にしていく。

from Crypto.Util.number import *
from hashlib import sha256

def get_nonce(data, prev, self):
    nonce = 0
    while True:
        text = long_to_bytes(nonce) + long_to_bytes(data) + prev
        if sha256(text).hexdigest() == self:
            return nonce
        nonce += 1


with open('flag.enc', 'r') as f:
    enc = eval(f.read())

hashes = ['0000000000000000']
for i in range(len(enc)):
    for e in enc:
        if e['prev'] == hashes[i]:
            hashes.append(e['self'])
            break

flag = ''
for h in hashes[1:]:
    for e in enc:
        if e['self'] == h:
            nonce = get_nonce(e['data'], e['prev'], e['self'])
            flag += chr(nonce)

print flag

実行結果は以下の通り。

flag{1337_cr33p3r_kn0ws_4b0ut_b10cks}
$ echo -n flag{1337_cr33p3r_kn0ws_4b0ut_b10cks} | sha256sum
70b2803c59f0259737834fdb664d1c6bc7fdf997d3e4815a63f5b485b42142c9  -
70b2803c59f0259737834fdb664d1c6bc7fdf997d3e4815a63f5b485b42142c9

feedback

アンケートに答えたら、フラグが表示された。

flag{thanks_please_rate_on_ctftime}
$ echo -n flag{thanks_please_rate_on_ctftime} | sha256sum
c228a4f59201e3e15b1041845418f2ac745ddc0f1958cc701c5934893925dd80  -
c228a4f59201e3e15b1041845418f2ac745ddc0f1958cc701c5934893925dd80