[5주차] block.py

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad

KEY = ?
FLAG = ?

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

    padded = pad(plaintext + FLAG.encode(), 16)
    cipher = AES.new(KEY, AES.MODE_ECB)
    try:
        encrypted = cipher.encrypt(padded)
    except ValueError as e:
        return {"error": str(e)}

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

flag도 key도 모름… plain은 넣을 수 있음
16바이트로 padding
음… 문제 감을 못잡겠어서 라이트업 참고했다…

ECB Oracle

해당 사이트에서 푸는 거였다

패딩은 16 단위이다. 왼쪽은 \x61을 15번 채우면 flag에서 한 글자를 가져올 수 있다.
오른쪽에서 브루트포스처럼 a부터 넣어서 같은 output을 출력하는 한 글자를 찾으면 그 값이 flag의 첫글자이다.
이후에는 \x61 14번 + 찾은 글자 + 찾을 flag 한 글자로 반복한다.

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import time
import requests

#ciphertext를 받아온다. 
def get_cipher(plaintext):
    chellenge_site = 'https://aes.cryptohack.org/ecb_oracle/encrypt/' + plaintext.hex() + '/'
    r = requests.get(chellenge_site)
    ciphertext = r.json()
    return bytes.fromhex(ciphertext['ciphertext'])

flag=b''

#range 범위 설정에 대해서는 후술... 
for i in range(0, 32):
    plaintext = b'\x61' * (31 - i)  #\x61을 31-i만큼 채운다 
    ciphertext = get_cipher(plaintext)[:32]  #보내고 ascii 하나씩 대입해서 비교 
    plaintext += flag  #찾아둔 flag들 더해야 함 
    print("try %d" % (i+1))
    
    #ascii 브루트포스 for문 
    for j in range(33, 127):
        plaintext = plaintext[:31]
        plaintext += j.to_bytes(1, byteorder='big')

        wr_ci = get_cipher(plaintext)[:32]
        #같다면 
        if (wr_ci == ciphertext):
            flag += j.to_bytes(1, byteorder='big')
            print(flag)
            break
        time.sleep(1)

길이는 어떻게 알았냐 하면…
61을 1번 넣고, 2번 넣고… 하다보면 7번의 61을 넣었을 떄 갑자기 cipher가 길어진다. -> 블록이 추가됐다는 뜻
7+x=32
x=25이다.