😺

ångstromCTF 2021 - Keysar v2

2021/04/12に公開

問題概要

Wow! Aplet sent me a message... he said he encrypted it with a key, but lost it. Gotta go though, I have biology homework!

Source Output

chall.py
import string

with open("key.txt", "r") as f:
    shift = int(f.readline())
    key = f.readline()

with open("flag.txt", "r") as f:
    flag = f.read()


stdalph = string.ascii_lowercase
rkey = ""

for i in key:
    if i not in rkey:
        rkey += i
for i in stdalph:
    if i not in rkey:
        rkey += i
rkey = rkey[-shift:] + rkey[:-shift]

enc = ""
for a in flag:
    if a in stdalph:
        enc += rkey[stdalph.index(a)]
    else:
        enc += a

print(enc)

シーザー暗号に似たような感じに感じますが、それ以前に置換暗号と捉えたほうがよさそう。

解説

置換暗号は単語の長さから推測する等の攻撃が有効だったりします。例えば1文字の単語は"a"もしくは"I"である可能性が高い、等。

ということで、置換理由をまとめながら置換して出力するプログラムがこちら。置換は出力結果を見ながら確定した文字(赤く表示)から次の推測をしていく感じです。

solve.py
swap_list = [
        # flag format: actf{...}
        ("q", "a"),
        ("u", "c"),
        ("f", "t"),
        ("x", "f"),
        # I
        ("b", "i"),
        # that
        ("z", "h"),
        # it's, that's
        ("d", "s"),
        # hitchhiqwv -> hitchhike?
        ("q", "k"),
        ("w", "e"),
        # tx, xf -> to, of
        ("x", "o"),
        # cam't -> can't
        ("m", "n"),
        # kno?n -> known???
        ("q", "w"),
        # the?e -> there???
        ("u", "r"),
        # c?ass -> class???
        ("b", "l"),
        # ?lack an? ?ellow! -> black and yellow!?
        ("d", "b"),
        ("v", "d"),
        ("x", "y"),
        # welco?e -> welcome
        ("u", "m"),
        # I told yo? -> I told you?
        ("g", "u"),
]

with open("out.txt", "r") as f:
    s = list(f.read())
    for i in range(len(s)):
        for swap in swap_list:
            if s[i] == swap[0]:
                s[i] = "\033[31m" + swap[1] + "\033[0m"
                break
            elif s[i] == swap[1]:
                s[i] = swap[0]
    print("".join(s))

Discussion