728x90
1.문제 분석
- CBC 모드의 Key를 구하는 문제
- IV와 Key가 같을 때를 가정한 문제
- 임의의 문장에 대한 암복호화가 가능한 문제
2. 기본 아이디어
- XOR의 특성상 text ^ 0 = text임을 이용한다.
- key를 구했다면 flag를 추출해 복호화한다.
3.문제 풀이
이 문제에서는 다음과 같은 파이썬 코드가 주어진다.
from Crypto.Util.Padding import pad, unpad
from random import choices, randint
from Crypto.Cipher import AES
BLOCK_SIZE = 16
flag = open("flag", "rb").read()
key = bytes(randint(0, 255) for i in range(BLOCK_SIZE))
encrypt = lambda pt: AES.new(key, AES.MODE_CBC, key).encrypt(pad(pt, BLOCK_SIZE))
decrypt = lambda ct: unpad(AES.new(key, AES.MODE_CBC, key).decrypt(ct), BLOCK_SIZE)
print("Welcome to dream's AES server")
while True:
print("[1] Encrypt")
print("[2] Decrypt")
print("[3] Get Flag")
choice = input()
if choice == "1":
print("Input plaintext (hex): ", end="")
pt = bytes.fromhex(input())
print(encrypt(pt).hex())
elif choice == "2":
print("Input ciphertext (hex): ", end="")
ct = bytes.fromhex(input())
print(decrypt(ct).hex())
elif choice == "3":
print(f"flag = {encrypt(flag).hex()}")
exit()
else:
print("Nope")
간단하게 3번에서 flag를 추출해 냅다 2번에서 디코딩하려했지만 exit() 때문에 불가능하다.
그렇다면 1번과 2번을 통해 key를 구할 수 밖에 없다.
IV를 구하는 방법은 다음과 같다.
[1]. 블록사이즈가 16이므로 "00"을 16바이트만큼 채워서 encrypt하면 enc(IV)가 나올것이다.
[2]. 결과값을 디코딩할 때, 똑같은 key를 사용하므로 "00" * 16 + enc(IV)를 해준다.
[3]. [2]의 과정을 거치면 dec(0 ^ enc(IV)) = dec(enc(IV)) = IV = key가 도출된다.
드디어 나온 key값을 flag를 복호화 할 때 사용해주면 된다.
익스플로잇 코드는 다음과 같다.
from random import choices, randint
from Crypto.Cipher import AES
BLOCK_SIZE = 16
encrypt = lambda pt: AES.new(key, AES.MODE_CBC, key).encrypt(pad(pt, BLOCK_SIZE))
decrypt = lambda ct: unpad(AES.new(key, AES.MODE_CBC, key).decrypt(ct), BLOCK_SIZE)
r = remote("host3.dreamhack.games", 9302)
r.sendlineafter("[3] Get Flag\n", "1")
r.sendlineafter("(hex): ", "00" * 16)
b = bytes.fromhex(r.recvline(keepends=False).decode())
r.sendlineafter("[3] Get Flag\n", "2")
r.sendlineafter("(hex): ", "00" * 16 + b.hex())
key = bytes.fromhex(r.recvline(keepends=False).decode())[16:32]
r.sendlineafter("[3] Get Flag\n", "3")
r.recvuntil("flag = ")
ct = bytes.fromhex(r.recvline(keepends=False).decode())
print(decrypt(ct))
key에서 16:32만 따로 빼준 이유는 앞에 00 또한 함께 디코딩되어 있기 때문에 key만 추출해준 것이다.
728x90
'Dreamhack > CryptoPS' 카테고리의 다른 글
[Dreamhack][CryptoPS] [GCHD2022] 암호의 기초1 (0) | 2023.11.24 |
---|---|
[Dreamhack][CryptoPS] [KCTF] RSA-wiener (0) | 2023.11.23 |
[Dreamhack][CryptoPS] Textbook-RSA (2) | 2023.11.23 |
[Dreamhack][CryptoPS] [LINE CTF 2021] babycrypto3 (1) | 2023.11.22 |
[Dreamhack][CryptoPS] [LINE CTF 2021] babycrypto1 (0) | 2023.11.21 |