PicoCTF - XtraORdinary
Background
How to Convert Hex String to Bytes in Python? Python 好用模組介紹 - itertools & more-itertools Python File readline() Method Python append to a file
Source code
:::spoiler Source Code
#!/usr/bin/env python3
from random import randint
with open('flag.txt', 'rb') as f:
flag = f.read()
with open('secret-key.txt', 'rb') as f:
key = f.read()
def encrypt(ptxt, key):
ctxt = b''
for i in range(len(ptxt)):
a = ptxt[i]
b = key[i % len(key)]
ctxt += bytes([a ^ b])
return ctxt
ctxt = encrypt(flag, key)
random_strs = [
b'my encryption method',
b'is absolutely impenetrable',
b'and you will never',
b'ever',
b'ever',
b'ever',
b'ever',
b'ever',
b'ever',
b'break it'
]
for random_str in random_strs:
for i in range(randint(0, pow(2, 8))):
for j in range(randint(0, pow(2, 6))):
for k in range(randint(0, pow(2, 4))):
for l in range(randint(0, pow(2, 2))):
for m in range(randint(0, pow(2, 0))):
ctxt = encrypt(ctxt, random_str)
with open('output.txt', 'w') as f:
f.write(ctxt.hex())
:::
Recon
這一題我覺得出的不錯,首先他把flag和secret-key做XOR,然後做了一大堆random_strs之間的XOR,但我們都知道XOR做了兩次等於沒做,所以最後的output其實就是 \(flag \oplus key \oplus lots\ of\ random\ string=output\) 所以如果我們要得到flag首先就是要先把random string的成分拿掉,因為他只有32種結果,也就是
my encryption method
is absolutely impenetrable
and you will never
ever
break it
之間的排列組合,進行XOR,然後我們可以用itertools中的combinations method,先把所有組合排出來(這個寫法還不錯,可以學起來),然後依序把結果存起來,接著我們就要找出key是多少,由於第14行會把key延伸(反正大概就是這個意思),而我們唯一知道的是最後的flag一定是picoCTF{
開頭,也就是說這個key有大機率應該只有8個字元,那我們就可以拿前面得到的32種結果,直接和picoCTF{
進行XOR然後查看一下最後的strings有沒有有意義且長度小於8的,從結果來看,的確有一個Africa!
的東西印入眼簾,看起來應該就是我們的key,所以我們就可以直接進行最後的XOR得到flag
Exploit
from itertools import product
from pwn import *
from itertools import combinations
root_path = "D:/NTU/CTF/PicoCTF/Crypto/XtraORdinary/"
with open(root_path + 'output.txt', 'r') as f:
cipher = bytes.fromhex(f.read())
temp_pt = open(root_path + 'temp_plaintext.txt', 'a')
def decrypt(ctxt, key):
ptxt = b''
for i in range(len(ctxt)):
a = ctxt[i]
b = key[i % len(key)]
ptxt += bytes([a ^ b])
return ptxt
def sub_lists (l):
comb = []
for i in range(1,len(l)+1):
comb += [list(j) for j in combinations(l, i)]
return comb
random_strs = [
b'my encryption method',
b'is absolutely impenetrable',
b'and you will never',
b'ever',
b'break it'
]
combos = sub_lists(random_strs)
'''
1st Step - Try to xor all combination of random strings
'''
for i in range(len(combos)):
tmp_cipher = cipher
for j in range(len(combos[i])):
# print(combos[i][j])
tmp_cipher = decrypt(tmp_cipher, combos[i][j])
# print()
print(bytes.fromhex(tmp_cipher.hex()).decode('cp437'))
temp_pt.writelines(tmp_cipher.hex() + '\n')
temp_pt.close()
'''
2nd Step - Try to find key
'''
key = b'picoCTF{'
cipher = open(root_path + 'temp_plaintext.txt', 'r').readlines()
for i in range(len(cipher)):
ptxt = decrypt(bytes.fromhex(cipher[i].strip()), key)
print(bytes.fromhex(ptxt.hex()).decode('cp437'))
'''
3rd Step - Find flag
'''
key = b'Africa!'
cipher = open(root_path + 'temp_plaintext.txt', 'r').readlines()
for i in range(len(cipher)):
ptxt = decrypt(bytes.fromhex(cipher[i].strip()), key)
if 'picoCTF{' in bytes.fromhex(ptxt.hex()).decode('cp437'):
print(f"Flag = {bytes.fromhex(ptxt.hex()).decode('cp437')}")
break
Reference
pico crypto XtraORdinary wp - partender810 XtraORdinary WP - whiteSHADOW1234