CTRIME

문제

우리의 평문에는 중복되는 부분이 많을 수 있으니, 먼저 압축해보는 것은 어떨까요?

https://aes.cryptohack.org/ctrime/

풀이

더보기

 

 

from Crypto.Cipher import AES
from Crypto.Util import Counter
import zlib


KEY = ?
FLAG = ?


@chal.route('/ctrime/encrypt/<plaintext>/')
def encrypt(plaintext):
    plaintext = bytes.fromhex(plaintext)

    iv = int.from_bytes(os.urandom(16), 'big')
    cipher = AES.new(KEY, AES.MODE_CTR, counter=Counter.new(128, initial_value=iv))
    encrypted = cipher.encrypt(zlib.compress(plaintext + FLAG.encode()))

    return {"ciphertext": encrypted.hex()}

 

먼저 encrypt함수에서 plaintext와

ctr모드로 암호화된 flag값 합친 후 zlib을 사용하여 연결된 문자열을 압축하고,

이를 hex값으로 출력한다.

 

 

import requests

def pr_len_encrypt(plaintext) :
    get_encrypt= requests.get('http://aes.cryptohack.org/ctrime//encrypt/'+plaintext+'/')
    encrypted=get_encrypt.json()["ciphertext"]
    print(encrypted)
    print(len(encrypted))

flag_a=b'crypto{'.hex()
flag_b=b'crypto{a'.hex()

pr_len_encrypt(flag_a)
pr_len_encrypt(flag_b)

 

flag값은 crypto{로 시작 되고, 이 일부분을 대입하면 암호문 길이가 68,

crypto{이후에 임의의 글자를 넣고 대입하면 암호문 길이가 70이 되었다.

이는 zlib이 중복된 문자열을 제거하므로 일반 텍스트의 실제 길이를 보여준다.

평문에 한글자를 추가해도 길이가 달라지지 않기에 이를 알아 낼수 있다고 생각했다.

 

그래서 브루트포싱으로 한글자씩 넣고 

맞으면 더하며 플래그값을 알아보았다.

import requests
import time

chr_all = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'

def get_encrypt(plaintext) :
    get_encrypt= requests.get('http://aes.cryptohack.org/ctrime//encrypt/'+plaintext+'/')
    encrypted=get_encrypt.json()["ciphertext"]
    return encrypted

flag = b'crypto{'
ciphertext=get_encrypt(flag.hex())
flag_len=len(ciphertext)


while True:
    for c in chr_all:
        ciphertext = get_encrypt((flag+c.encode()).hex())
        print(c, len(ciphertext))
        if flag_len == len(ciphertext):
            flag +=c.encode()
            flag_len = len(ciphertext)
            print(flag)
            print(flag_len)
            time.sleep(1)
            break
        
        if flag.endswith(b'M'):  
            flag += b'E'        
            print(flag.decode())
        if c == chr_all[-1]:
                flag_len += 2
                break
        
    if flag.endswith(b'}'):
        print(flag)
        break
브루트포싱중

M이후 텍스트의 길이가 70으로 증가하고, 그이후로 72이기에 E를 추가하고 브루트포싱을 하였다.

플래그값은 crypto{CRIME_571ll_p4y5}이다.

복사했습니다!