๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿด‍โ˜ ๏ธ CTF ๐Ÿด‍โ˜ ๏ธ/๐Ÿงฎ ์•”ํ˜ธํ•™ ๐Ÿงฎ

[Dream Hack - Crypto] [LINE CTF 2021] babycrypto1

๋ฐ˜์‘ํ˜•

CBC ๋ชจ๋“œ

AES์˜ CBC (Cipher Block Chaining) ๋ชจ๋“œ๋Š” ๋ธ”๋ก ์•”ํ˜ธํ™” ๋ชจ๋“œ ์ค‘ ํ•˜๋‚˜๋กœ, ๊ฐ ๋ธ”๋ก์„ ์•”ํ˜ธํ™”ํ•  ๋•Œ ์ด์ „ ๋ธ”๋ก์˜ ์•”ํ˜ธ๋ฌธ๊ณผ XOR ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค.

  1. IV(Initialization Vector) ์„ ํƒ: ๋ฌด์ž‘์œ„๋กœ ์„ ํƒ๋œ IV๋Š” ์ฒซ ๋ฒˆ์งธ ๋ธ”๋ก์„ ์•”ํ˜ธํ™”ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.
  2. ๋ธ”๋ก ๋‹จ์œ„ ์•”ํ˜ธํ™”: ํ‰๋ฌธ์„ ๋ธ”๋ก ํฌ๊ธฐ๋กœ ๋‚˜๋ˆˆ ํ›„, ๊ฐ ๋ธ”๋ก์€ ์ด์ „ ๋ธ”๋ก์˜ ์•”ํ˜ธ๋ฌธ๊ณผ XOR ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•œ ๋’ค AES ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์•”ํ˜ธํ™”๋œ๋‹ค.

 

์ฃผ์–ด์ง„ ์ฝ”๋“œ ํ•ด์„

1. token + b'test' ๋ฅผ aes_key ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•”ํ˜ธํ™”ํ•˜๊ณ  ์ด๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

aes_key = get_random_bytes(AES.block_size)
token = b64encode(get_random_bytes(AES.block_size*10))[:AES.block_size*10]
client.send(b'test Command: ' + AESCipher(aes_key).encrypt(token+COMMAND[0]) + b'\\n')

 

2. IV ์™€ Message ๋ฅผ ์ž…๋ ฅ ๋ฐ›์•„ aes_key ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•”ํ˜ธํ™”ํ•˜๊ณ  ์ด๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

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')

 

3. ์•”ํ˜ธ๋ฌธ์„ ์ž…๋ ฅ ๋ฐ›๊ณ  ๊ทธ ๊ฐ’์ด token + b'show' ์™€ ์ผ์น˜ํ•˜๋Š” ๊ฒฝ์šฐ flag๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

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)
				print(b'The flag is: ' + flag)
				client.close()
				break

 

ํ’€์ด ๋ฐฉ๋ฒ•

์ฃผ์–ด์ง„ ์ฝ”๋“œ์—์„œ๋Š” ๋™์ผํ•œ ํ‚ค๊ฐ€ ๊ณ„์† ์‚ฌ์šฉ๋˜์–ด ์•”ํ˜ธํ™”์™€ ๋ณตํ˜ธํ™”๊ฐ€ ์ด๋ฃจ์–ด์ง„๋‹ค. ๋˜ํ•œ, AES๊ฐ€ 16 ๋ฐ”์ดํŠธ ๋ธ”๋ก ์•”ํ˜ธ๋ผ๋Š” ํŠน์„ฑ์„ ํ™œ์šฉํ•˜์—ฌ token + b'show' ๋ฌธ์ž์—ด์˜ ์•”ํ˜ธ๋ฌธ์„ ๊ตฌํ•˜์ž.

 

1. token์˜ ์•”ํ˜ธ๋ฌธ์€ C0~C10 ์— ํ•ด๋‹นํ•œ๋‹ค. test์˜ ์•”ํ˜ธ๋ฌธ์€ C11์— ํ•ด๋‹นํ•œ๋‹ค.

2. Cipher Oracle์„ ์‚ฌ์šฉํ•˜์—ฌ token + b'show' ์— ๋งˆ์ง€๋ง‰ ๋ธ”๋ก ์•”ํ˜ธ๋ฌธ์„ ์ƒ์„ฑํ•œ๋‹ค. ์ด๋•Œ IV๋Š” C10, Message๋Š” ‘show’๋กœ ์„ค์ •ํ•œ๋‹ค.

3. C0~C10 ๊ณผ ์ƒˆ๋กœ ์ƒ์„ฑํ•œ C11์„ ํ†ตํ•ด flag๋ฅผ ํš๋“ํ•œ๋‹ค.

 

ํ’€์ด ์ฝ”๋“œ

from pwn import *
import base64

p=remote("host3.dreamhack.games", 11224)

## token + 'test' ๊ฐ€ ์•”ํ˜ธํ™”๋œ ๊ฐ’
p.recvuntil(b"test Command: ")
test_command = p.recvline().decode('utf-8')

## C10 + 'show' ๊ฐ€ ์•”ํ˜ธํ™”๋œ ๊ฐ’
p.recvuntil(b"IV...:")
iv = base64.encodebytes(base64.b64decode(test_command)[160 : 176])
p.send(iv)
p.recvuntil(b"Message...:")
p.send(base64.encodebytes(b"show"))
p.recvuntil(b"Ciphertext:")
cipher_text = p.recvline().decode('utf-8')

## token + 'show' ๊ฐ€ ์•”ํ˜ธํ™”๋œ ๊ฐ’ ์ž…๋ ฅใ„ด
p.recvuntil(b"Enter your command: ")
p.send(base64.encodebytes(base64.b64decode(test_command)[0 : 176] + base64.b64decode(cipher_text)[16 : 32]))

print(p.recvline())
print(p.recv(512))

 

๋ฐ˜์‘ํ˜•