또 뭐하지
[Dreamhack] No sub please! 본문
728x90
풀이
from AES import AES_implemented
import os
# For real AES without modification, this challenge is unsolvable with modern technology.
# But let's remove a step.
ret = lambda x: None
AES_implemented._sub_bytes = ret
AES_implemented._sub_bytes_inv = ret
# Will it make a difference?
secret = os.urandom(16)
key = os.urandom(16)
flag = open("flag.txt", "r").read()
cipher = AES_implemented(key)
secret_enc = cipher.encrypt(secret)
assert cipher.decrypt(secret_enc) == secret
print(f"enc(secret) = {bytes.hex(secret_enc)}")
while True:
option = int(input("[1] encrypt, [2] decrypt: "))
if option == 1: # Encryption
plaintext = bytes.fromhex(input("Input plaintext to encrypt in hex: "))
assert len(plaintext) == 16
ciphertext = cipher.encrypt(plaintext)
print(f"enc(plaintext) = {bytes.hex(ciphertext)}")
if plaintext == secret:
print(flag)
exit()
elif option == 2: # Decryption
ciphertext = bytes.fromhex(input("Input ciphertext to decrypt in hex: "))
assert len(ciphertext) == 16
if ciphertext == secret_enc:
print("No way!")
continue
plaintext = cipher.decrypt(ciphertext)
print(f"dec(ciphertext) = {bytes.hex(plaintext)}")
제공된 코드를 살펴보면, AES의 subbytes 부분을 없애고 secret과 key를 랜덤 16바이트를 받는다. 그리고 enc(secret) 값을 제공해주며 encrypt 옵션에 secret 값을 입력해주면 flag가 출력된다.
AES에서 SubBytes는 상태 배열의 각 바이트를 S-box를 참조하여 치환하는 함수이다. 이 치환 과정은 암호의 선형성을 없애, 대칭키 암호에서 혼돈 요건을 충족한다.
SubBytes를 없애면 선형 관계를 가지게 되어 아래의 성질을 만족하게 된다고 한다.
enc(a) ^ enc(b) = enc(0) ^ enc(a^b)
dec(a) ^ dec(b) = dec(0) ^ dec(a^b)
위 공식을 변형하면 dec(a) = dec(0) ^ dec(a^b) ^ dec(b) 인 것을 알 수 있고 이를 이용하여 필요한 secret을 얻을 수 있을 것 같다.
그러면 필요한 것은
dec(0)
dec(enc(secret)^b) (이 때 b는 아무값이나 써도 괜찮음)
dec(b) 이다
이를 바탕으로 익스플로잇 코드를 작성했다
from pwn import *
import os
r = remote("host3.dreamhack.games", 11147)
r.recvuntil(b'= ')
secret_enc = bytes.fromhex(r.recvline().decode())
b = os.urandom(16) #랜덤한 b를 받아옴
def decrypt(ciphertext):
r.sendline(b'2')
r.sendline(bytes.hex(ciphertext).encode())
r.recvuntil(b'= ')
plaintext = bytes.fromhex(r.recvline().decode())
return plaintext
def xor(a, b):
result = []
for i in range(len(a)):
tmp = a[i] ^ b[i]
result.append(tmp)
return bytes(result)
p1 = decrypt(bytes(16)) #dec(0)
p2 = decrypt(xor(secret_enc, b)) #dec(secret_enc^b)
p3 = decrypt(b) #dec(b)
p = xor(p1, xor(p2, p3)) # p1^p2^p3
r.sendline(b'1')
r.sendline(bytes.hex(p).encode())
r.interactive()
작동시키면 아래와 같이 flag를 얻을 수 있다!
* xor 함수 xor = lambda a, b: bytes([i^j for i, j in zip(a,b)]) 이렇게 짜면 간결 zip!!
* 아핀성질에 대해서 더 공부해야할 것 같다
'Write-up > Crypto' 카테고리의 다른 글
[Dreamhack] 40 Birthdays (0) | 2024.11.08 |
---|---|
[Dreamhack] Insecure Seed (0) | 2024.10.31 |
[Dreamhack] Easy Linguistics (0) | 2024.10.24 |
[Dreamhack] safeprime (1) | 2024.10.24 |
[Dreamhack] What is This??? (0) | 2024.10.04 |