반응형
풀이
#!/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()
AES_KEY = get_random_bytes(AES.block_size)
TOKEN = b64encode(get_random_bytes(AES.block_size*10-1))
COMMAND = [b'test',b'show']
PREFIX = b'Command: '
def run_server(client):
client.send(b'test Command: ' + AESCipher(AES_KEY).encrypt(PREFIX+COMMAND[0]+TOKEN) + b'\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 == PREFIX+COMMAND[1]+TOKEN:
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', 16002))
server.listen(1)
while True:
client, address = server.accept()
process = multiprocessing.Process(target=run_server, args=(client, ))
process.daemon = True
process.start()
AES 암호화된 데이터를 받고, 암호화된 데이터를 보내면 복호화를 해준다.
만약, 복호화 데이터가 PREFIX+show+token
이면 flag를 준다.
데이터를 받으면, 앞에 16byte는 IV 값이고 그뒤로 암호화된 데이터이다.
AES 복호화를 할 때, Key로 복호화를 하고, IV와 xor연산을 통해 평문을 구한다.
만약, IV 값을 조작을 한다면, xor 연산시 평문이 조작될 것이다.
그렇다면 IV의 10~13(4자리)를 조작하면, test를 show로 바꿀 수 있다.
Solve Code
from base64 import b64decode, b64encode
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
from pwn import *
r = remote('35.200.39.68', 16002)
print(r.recvuntil('test Command: '))
test_command = b64decode(r.recvuntil('\n', drop=True))
real_iv = test_command[:9] + xor(xor(test_command[9:13], b'test'), b'show') + test_command[13:16]
print(real_iv)
enc_data = test_command[16:]
log.info(f'iv: {real_iv}, len: {len(real_iv)}')
log.info(f'enc_data: {enc_data}')
r.recvuntil('Enter your command: ')
data = real_iv + enc_data
r.sendline(b64encode(data))
data = r.recvuntil('\n', drop=True)
r.interactive()
Flag
LINECTF{echidna_kawaii_and_crypto_is_difficult}
반응형
'CTF(Capture The Flag) > Line 2021' 카테고리의 다른 글
babycrypto3 (0) | 2021.03.22 |
---|---|
babycrypto1 (0) | 2021.03.22 |