ECB Oracle

문제

ECB는 간단한 모드로, 각 평문 블록이 완전히 독립적으로 암호화됩니다..
이러한 경우, 당신의 입력이 비밀 플래그 앞에 붙여지고, 암호화되고, 그게 전부입니다.
우리는  심지어 복호화 기능도 제공하지 않습니다.
아마도 "ECB 오라클"이 있을 때 패딩 오라클이 필요하지 않을까요?

https://aes.cryptohack.org/ecb_oracle/

풀이

더보기
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()}

 

먼저 코드를 보게 되면

AES로 암호화 하기 전에 pad 함수를 사용해서,

입력한 평문 + Flag값의 암호화, 그리고 블록의 크기를 16바이트씩 맞추어 사용한다.

 

평문 + Flag값으로 암호화를 진행하여,

한 글자 (예시:"a")15개를 넣어두면 Flag값의 첫 한글자까지 해서 한 블록으로 묶인다.

 

그래서

브루트보스를 통해 "a"15개와, 무작위로 1바이트를 대입 했을때 한 글자의 flag를 알고

브루트보스를 통해 "a"14개+알고 있는 1바이트와, 무작위로 1바이트를 대입 했을때

한 글자의 flag를 아는 방식으로 패딩을 하나씩 줄여 flag 값을 알 수 있다.

 

먼저, 16바이트, 2블록으로 잡아 범위를 먼저 32로 잡고, 브루트 포싱을 하였다.

그 다음에 길이가 안나오면 16바이트, 3블록으로 잡아 48로 잡을 예정이었다.

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

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''

for i in range(0, 32):
    plaintext = b'\x61' * (31 - i)
    ciphertext = get_cipher(plaintext)[:32]
    plaintext += flag
    print("try %d" %(i+1))
    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)
꽤 시간이 오래걸린다.

 

플래그값이 나왔다.

플래그값은 'crypto{p3n6u1n5_h473_3cb}'이다.

   

 

복사했습니다!