-
[Clear] LINE CTF 2021 babycrypto2 WriteupCTF/LINE CTF 2021 2021. 3. 22. 20:37
주어진 파일을 분석해보자 .
#!/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') print(len(PREFIX+COMMAND[0])) print(len(TOKEN)) 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()
babycrypto1과 달라진 점은,
평문의 뒷부분이 아닌 앞부분이 다를 때의 암호문을 구해야 한다는 점이다.
즉 주어진 test Command 의 첫 번째 블록은 [Command: test???] 의 암호문일 것이다.
(1블록의 길이는 16이므로 뒤에 3바이트는 token의 앞부분일 것이다.)
우리는 첫 번째 블록이 [Command: show???] 일때의 암호문을 구해야 한다.
다시 CBC 암호화 방식을 보자. 첫 번째 암호 블록은
임의의 IV XOR Plaintext의 첫 블록 연산 후 암호화가 진행된다.
우선 test command를 그대로 전송해 ???값을 알아 낼 수 있다.
from pwn import * import base64 p=remote("35.200.39.68", 16002) p.recvuntil("test Command: ") test = p.recvuntil(b"\nEnter your command: ", drop=True) print(test) #print(test[-32:-16]) iv = list(base64.b64decode(test)[:16]) chiper = base64.b64decode(test)[16:] for i in range(16): iv[i] = 0 iv=bytes(iv) medium = base64.b64encode(iv+chiper) #print(final) p.send(test) p.recvuntil("test") temp_3byte = p.recv(3) print(b"temp_3byte: " + temp_3byte) p.recvuntil(b"Enter your command: ") p.send(medium) temp_16byte=p.recv(16) target = b"Command: show"+temp_3byte print(target) last_iv=list(target[i]^temp_16byte[i] for i in range(16)) print(last_iv) final = base64.b64encode(bytes(last_iv)+chiper) p.recvuntil("Enter your command: ") p.send(final) p.interactive()
또한, 암/복호화 과정에서 첫 번째 블록은 IV와 XOR 연산이 이루어지기 때문에 IV를 0*16으로 조작 한 값에 원하는 평문을 XOR시켜 연산해주면 원하는 평문일 때의 암호문을 얻을 수 있다.
[iv] XOR [Cipher_aftet_aes] = [test]
( [iv] XOR [Cipher_aftet_aes] XOR [test] ) XOR [test] XOR [show]
[test] XOR [test] XOR [show] = [show]
< exploit code >
from pwn import * import base64 p=remote("35.200.39.68", 16002) p.recvuntil("test Command: ") test = p.recvuntil(b"\nEnter your command: ", drop=True) print(test) #print(test[-32:-16]) iv = list(base64.b64decode(test)[:16]) chiper = base64.b64decode(test)[16:] for i in range(16): iv[i] = 0 iv=bytes(iv) medium = base64.b64encode(iv+chiper) #print(final) p.send(test) p.recvuntil("test") temp_3byte = p.recv(3) print(b"temp_3byte: " + temp_3byte) p.recvuntil(b"Enter your command: ") p.send(medium) temp_16byte=p.recv(16) #print(b"temp_16byte: "t + temp_16byte) target = b"Command: show"+temp_3byte print(target) last_iv=list(target[i]^temp_16byte[i] for i in range(16)) print(last_iv) final = base64.b64encode(bytes(last_iv)+chiper) p.recvuntil("Enter your command: ") p.send(final) p.interactive()
FLAG = LINECTF{echidna_kawaii_and_crypto_is_difficult}
반응형'CTF > LINE CTF 2021' 카테고리의 다른 글
[Study] LINE CTF 2021 Your note (0) 2021.03.29 [Clear] LINE CTF 2021 babycrypto1 Writeup (0) 2021.03.22 [Clear] LINE CTF 2021 diveinternal Writeup (0) 2021.03.22