🐕

ångstromCTF 2021 - Follow the Currents

2021/04/12に公開

問題概要

go with the flow... Source

import os
import zlib
def keystream():
	key = os.urandom(2)
	index = 0
	while 1:
		index+=1
		if index >= len(key):
			key += zlib.crc32(key).to_bytes(4,'big')
		yield key[index]
ciphertext = []
with open("plain","rb") as f:
	plain = f.read()
	assert b"actf{" in plain
	k = keystream()
	for i in plain:
		ciphertext.append(i ^ next(k))
with open("enc","wb") as g:
	g.write(bytes(ciphertext))

zlib.crc32というやや聞きなれないものを利用しているようです。

解説

問題点はkeystreamで利用されているkeyの初期化が2byteしかないという点です。これは全探索が容易な数値です。

また、暗号化の作業でXORを用いているので、一番最初の鍵さえ分かれば復元が可能です。ということで鍵を全探索してそれぞれの場合で復号が出来るか試します。

solve.py
import zlib

def keystream(key):
    index = 0
    while 1:
        index += 1
        if index >= len(key):
            key += zlib.crc32(key).to_bytes(4, 'big')
        yield key[index]

f = open("enc", "rb")
cipher = f.read()
for key in range(256 ** 2):
    keys = key.to_bytes(2, "big")
    k = keystream(keys)
    plain = []
    for i in cipher:
        plain.append((i ^ next(k)).to_bytes(1, "big"))
    plain = b"".join(plain)
    if b"actf{" in plain:
        print(plain)

Discussion