CTF(Capture The Flag)/Line 2021

babycrypto2

cyanhe_wh 2021. 3. 22. 22:01
반응형

풀이

#!/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