1. 문제 설명
2. 문제 풀이
1. challenge.py 분석
challenge.py 코드를 살펴 보면, 초기 벡터(IV)와 키가 동일하며, CBC 모드를 사용하고 있음을 알 수 있다.
만약에 0으로 채워진 한 블록을 CBC 모드로 암호화한다면,
$E_{K}(P+IV) = E_{K}(0+K) = E_{K}(K)$
따라서 $E_{K}(K)$를 구할 수 있게 된다.
그리고 총 두 개의 블록을 복호화한다고 가정하면,
CBC 모드의 마지막 암호문 블록을 복호화하는 과정은 아래와 같다.
$P_{2} = D_{K}(C_{2}) + C_{1}$
이때 $C_{1}$을 0으로, $C_{2}$를 $E_{K}(K)$라고 한다면,
$P_{2} = K$가 된다.
2. 복호화 코드 작성
from pwn import *
from Crypto.Util.Padding import unpad
from Crypto.Cipher import AES
# 서버 연결
host = "host3.dreamhack.games"
port = 18609
r = remote(host, port)
# 16-byte의 0 암호화해서 E(k, k) 구하기
p = bytes(16).hex()
r.sendlineafter("[3] Get Flag\n", "1")
r.sendlineafter("(hex): ", p)
enc_iv = r.recvline().decode()
enc_iv = bytes.fromhex(enc_iv)
# 키 구하기
r.sendlineafter("[3] Get Flag\n", "2")
r.sendlineafter("(hex): ", p + enc_iv.hex())
key = r.recvline().decode()
key = bytes.fromhex(key)[16:32]
# 암호화된 flag 값 받아오기
r.sendlineafter("[3] Get Flag\n", "3")
r.recvuntil("flag = ")
enc_flag = r.recvline().decode()
enc_flag = bytes.fromhex(enc_flag)
# flag 복호화
BLOCK_SIZE = 16
decrypt = lambda ct: unpad(AES.new(key, AES.MODE_CBC, key).decrypt(ct), BLOCK_SIZE)
flag = decrypt(enc_flag)
print(flag)
3. DH{...} 형식의 플래그 응답을 확인하고 정답을 입력한다.