728x90
1.문제 분석
- AES의 CBC모드를 통해 flag를 구하는 문제
- base64 인코딩과 디코딩이 섞인 문제
2. 기본 아이디어
- CBC 모드는 바로 전 블록이 해당 블록의 IV임을 이해한다.
- IV를 알면 원하는 암호화 문자열을 만들 수 있다.
3.문제 풀이
문제 코드는 아래와 같다.
#!/usr/bin/env python
from base64 import b64decode
from base64 import b64encode
import socket
import multiprocessing
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
import hashlib
import sys
class AESCipher:
def __init__(self, key):
self.key = key
def encrypt(self, data):
iv = get_random_bytes(AES.block_size)
self.cipher = AES.new(self.key, AES.MODE_CBC, iv)
return b64encode(iv + self.cipher.encrypt(pad(data,
AES.block_size)))
def encrypt_iv(self, data, iv):
self.cipher = AES.new(self.key, AES.MODE_CBC, iv)
return b64encode(iv + self.cipher.encrypt(pad(data,
AES.block_size)))
def decrypt(self, data):
raw = b64decode(data)
self.cipher = AES.new(self.key, AES.MODE_CBC, raw[:AES.block_size])
return unpad(self.cipher.decrypt(raw[AES.block_size:]), AES.block_size)
flag = open("flag", "rb").read().strip()
COMMAND = [b'test',b'show']
def run_server(client, aes_key, token):
client.send(b'test Command: ' + AESCipher(aes_key).encrypt(token+COMMAND[0]) + b'\n')
client.send(b'**Cipher oracle**\n')
client.send(b'IV...: ')
iv = b64decode(client.recv(1024).decode().strip())
client.send(b'Message...: ')
msg = b64decode(client.recv(1024).decode().strip())
client.send(b'Ciphertext:' + AESCipher(aes_key).encrypt_iv(msg,iv) + b'\n\n')
while(True):
client.send(b'Enter your command: ')
tt = client.recv(1024).strip()
tt2 = AESCipher(aes_key).decrypt(tt)
client.send(tt2 + b'\n')
if tt2 == token+COMMAND[1]:
client.send(b'The flag is: ' + flag)
client.close()
break
if __name__ == '__main__':
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(('0.0.0.0', 16001))
server.listen(1)
while True:
client, address = server.accept()
aes_key = get_random_bytes(AES.block_size)
token = b64encode(get_random_bytes(AES.block_size*10))[:AES.block_size*10]
process = multiprocessing.Process(target=run_server, args=(client, aes_key, token))
process.daemon = True
process.start()
우선 이 코드를 통해 알 수 있는 점은 다음과 같다.
1. AES의 CBC 모드를 쓴다는 것.
2. 사용자가 IV를 입력할 수 있고, 암호화하고 싶은 msg를 작성할 수 있다는 것.
3. 1024 사이즈 만큼의 값을 입력 가능하다는 것.
4. token(160bytes)+b'test'가 주어지고 내가 작성한 암호화된 문자열이 token(160bytes)+b'show'와 같아야 한다는 것.
따라서 해야할 행동은 다음과 같다.
1. 주어지는 testCommand를 블록단위로 쪼갠 후 b'test' 바로 앞의 블록을 b'show'를 암호화 하기위해 가져온다.
2. b'show'를 찾았다면 앞선 token+b'test'에서 token을 가져온 후 token+b'show'를 base64인코딩해서 입력해준다.
3. 잘 암호화되었다면 tt2 = token+b'show'에 의거해 flag가 나올 것이다.
exploit code는 다음과 같다.
from pwn import *
r = remote("host3.dreamhack.games", 10690)
r.recvuntil("test Command: ")
test = r.recvuntil("\n**Cipher oracle**\n", drop=True)
#print(test)
test = base64.b64decode(test)
iv = test[-32:-16]
#print(iv)
r.recvuntil("IV...: ")
r.send(base64.b64encode(iv))
r.recvuntil("Message...: ")
r.send(base64.b64encode(b'show'))
r.recvuntil("Ciphertext:")
b = r.recvuntil("\n", drop=True)
#print(b)
b = base64.b64decode(b)
final = base64.b64encode(test[:-32]+b)
print(r.sendlineafter("Enter your command: ", final))
r.interactive()
728x90
'Dreamhack > CryptoPS' 카테고리의 다른 글
[Dreamhack][CryptoPS] Textbook-RSA (2) | 2023.11.23 |
---|---|
[Dreamhack][CryptoPS] [LINE CTF 2021] babycrypto3 (1) | 2023.11.22 |
[Dreamhack][CryptoPS] Chinese what? (0) | 2023.11.11 |
[Dreamhack][CryptoPS] Basic_Crypto (0) | 2023.11.09 |
[Dreamhack][CryptoPS] darimchall_001 (0) | 2023.11.09 |