CTF(Capture The Flag)/Line 2021

babycrypto1

cyanhe_wh 2021. 3. 22. 21:59
반응형

풀이

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

서버에 접속하면, AES 암호로 암호화된 token + test 를 받고, IV 값과 Message 값을 보낼 수 있다.

그리고 보낸 IV와 Message로 암호화한 데이터를 받는다.

그 뒤로 보낸 암호화를 복호화 해준다. 만약 복호화 데이터가 token + show 가 맞으면 flag를 출력해준다.

여기서 우리가 조작해야할 부분은 test를 show로 만드는 것이다.

암호화 구조를 보면 16byte씩 나눠 IV로 xor 하고 key로 암호화를 한다. 그리고 뒤 데이터는 앞 cipher text를 IV 값으로 사용한다.

token(160) + test(4) + pad(14) 마지막 뒤에 test+pad 를 암호화할 때는 token의 마지막 16byte를 암호화한 데이터를 VI로 사용해서 xor 연산하고 암호화를 한다.

만약 token의 마지막 16byte를 VI로 사용해서 show 를 암호화해서 test 암호화된 부분을 빼고 show 암호화 데이터를 보내면, flag를 얻을 수 있다.

Solve Code

from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
from base64 import b64decode, b64encode
from pwn import *

r = remote('35.200.115.41', 16001)

print(r.recvuntil('test Command: '))
test_enc = b64decode(r.recvuntil('\n', drop=True))
real_iv = test_enc[:16]
enc_data = test_enc[16:176]
log.info(f'iv: {real_iv}')
log.info(f'enc_data: {enc_data}')
print(len(enc_data))
pad = test_enc[176:]
log.info(f'pad: {pad}, len: {len(pad)}')
print()

enc_16byte = test_enc[160:176]
print(r.sendlineafter('IV...: ', b64encode(enc_16byte)))

msg = b'show'
print(r.sendlineafter('Message...: ', b64encode(msg)))

print(r.recvuntil('Ciphertext:'))
cipher_text = b64decode(r.recvuntil('\n', drop=True))
print(cipher_text)
print(f'len: {len(cipher_text)}')
show_data = cipher_text[16:]
log.info(f'show_data: {show_data}, len: {len(show_data)}')

data = real_iv + enc_data[:160] + show_data
print(data)

print(r.sendlineafter('Enter your command: ', b64encode(data)))
r.interactive()

Flag

LINECTF{warming_up_crypto_YEAH}

반응형

'CTF(Capture The Flag) > Line 2021' 카테고리의 다른 글

babycrypto3  (0) 2021.03.22
babycrypto2  (0) 2021.03.22