PicoCTF - Compress and Attack
tags: PicoCTF
CTF
Crypto
Background
- zlib compression property
詳細說明一下zlib的壓縮特性是當壓縮的內容出現重複字元的時候,壓縮過後的長度會不變
1
2
3
4
5
6
7
8
9
10>>> import zlib >>> enc = zlib.compress(bytes("picoCTF{picoCTF{testing_123456}".encode("utf-8"))) >>> len(enc) 33 >>> enc = zlib.compress(bytes("picoCTF{tepicoCTF{testing_123456}".encode("utf-8"))) >>> len(enc) 33 >>> enc = zlib.compress(bytes("picoCTF{tekpicoCTF{testing_123456}".encode("utf-8"))) >>> len(enc) 34
此時重複的部分就是
picoCTF{
,若是繼續增加重複的部分(例如:picoCTF{te
),壓縮後的長度也不會變,這樣就可以當作一個oracle,也就是利用長度來判斷增加的字元是不是flag重複的一部分
Source code
:::spoiler
#!/usr/bin/python3 -u
import zlib
from random import randint
import os
from Crypto.Cipher import Salsa20
flag = open("./flag").read()
def compress(text):
return zlib.compress(bytes(text.encode("utf-8")))
def encrypt(plaintext):
secret = os.urandom(32)
cipher = Salsa20.new(key=secret)
return cipher.nonce + cipher.encrypt(plaintext)
def main():
while True:
usr_input = input("Enter your text to be encrypted: ")
compressed_text = compress(flag + usr_input)
encrypted = encrypt(compressed_text)
nonce = encrypted[:8]
encrypted_text = encrypted[8:]
print(nonce)
print(encrypted_text)
print(len(encrypted_text))
if __name__ == '__main__':
main()
:::
Recon
這一題很有趣,可以看一下source code發現他特意把encrypted_text
的長度leak出來當作解題的一部分資訊,透過上述提到的zlib
特性,可以把這個資訊當成一個oracle
1 |
|
透過上述測試,可以判斷長度應該就是固定48,此時我們就可以依序加入guessing character,並透過oracle判斷加入的字元是對的還是錯的
Exploit
from pwn import *
context.arch = 'amd64'
r = remote("mercury.picoctf.net", 33976)
def oracle(plaintext):
r.recvuntil(b"Enter your text to be encrypted: ")
r.sendline(plaintext.encode())
nonce = r.recvline().strip().hex()
encrypted_text = r.recvline().strip().hex()
return r.recvline().strip().decode()
current_char = ""
guessing_flag = "picoCTF{"
fit_length = oracle(guessing_flag)
print(guessing_flag)
while current_char != "}":
for i in string.printable:
if oracle(guessing_flag + i) == fit_length:
print(i)
guessing_flag += i
current_char = i
break
print(guessing_flag)
r.close()
Flag: picoCTF{sheriff_you_solved_the_crime}