LOLZZ-CTF-WriteUps

KittyCrypt

There is example input, output and flag_output with encrypt code. Since we know pair of input and output, we can know what is the key and find the flag with that key.

import binascii

# Go 코드 CharSet의 역매핑 (이모지 → 16진수 한 글자)
CAT_TO_HEX = {
    "🐱": "0", "🐈": "1", "😸": "2", "😹": "3",
    "😺": "4", "😻": "5", "😼": "6", "😽": "7",
    "😾": "8", "😿": "9", "🙀": "A", "🐱‍👤": "B",
    "🐱‍🏍": "C", "🐱‍💻": "D", "🐱‍👓": "E", "🐱‍🚀": "F",
}

def cat_to_hex_str(cat_cipher: str) -> str:
    i = 0
    hex_chars = []
    sorted_keys = sorted(CAT_TO_HEX.keys(), key=len, reverse=True)

    while i < len(cat_cipher):
        for k in sorted_keys:
            if cat_cipher.startswith(k, i):
                hex_chars.append(CAT_TO_HEX[k])
                i += len(k)
                break
        else:
            raise ValueError(f"Unknown cat emoji at pos={i} -> {cat_cipher[i:i+5]}")
    return "".join(hex_chars)

def hex_str_to_keyed_text(hex_str: str) -> str:
    raw = binascii.unhexlify(hex_str)
    return raw.decode('utf-8', errors='replace')

def recover_key(plaintext: str, keyed_text: str) -> list:
    return [ord(k) - ord(p) for p, k in zip(plaintext, keyed_text)]

def decrypt_cat_cipher(cat_cipher: str, keys: list) -> str:
    hex_str = cat_to_hex_str(cat_cipher)
    keyed_text = hex_str_to_keyed_text(hex_str)

    decrypted = []
    for i, ch in enumerate(keyed_text):
        decrypted.append(chr(ord(ch) - keys[i]))
    return "".join(decrypted)

def main():
    with open("example_input.txt", "r", encoding="utf-8") as f:
        example_plain = f.read()
    with open("example_output.txt", "r", encoding="utf-8") as f:
        example_cipher = f.read()

    ex_hex_str = cat_to_hex_str(example_cipher)
    ex_keyed_text = hex_str_to_keyed_text(ex_hex_str)
    keys = recover_key(example_plain, ex_keyed_text)

    with open("flag_output.txt", "r", encoding="utf-8") as f:
        flag_cipher = f.read()

    flag_plain = decrypt_cat_cipher(flag_cipher, keys)
    print("[+] Flag:")
    print(flag_plain)

if __name__ == "__main__":
    main()

flag is: irisctf{s0m371m3s_bY735_4r3n7_wh47_y0u_3xp3c7}