BreizhCTF 2019: CrazyLooper
Challenge details
Event | Challenge | Category | Points | Solves |
---|---|---|---|---|
BreizhCTF 2019 | CrazyLooper | Prog | 150 | 2 |
Challenge: chall md5sum : 339457087fe3c986e45937eaf26cbfea
TL;DR
We had a file recursively encoded with multiple algorithms. Each algorithm was given at the beginning of the decoded file. We wrote a program that recursively decode the first file until we got the last clear text.
Methodology
First look at the file
The file
command gave us only “data” but a deeper look at the head of the file gave us more information:
xxd chall | head -n 1
00000000: 786f 725f 4a3a 3225 3815 0170 637b 335e xor_J:2%8..pc{3^
We saw that the file start with “xor_J:” which means that we need to decode the file by xoring with the “J” letter.
with open("chall","rb") as f:
c = f.read()
algo,content = c.split(":",1)
out = ""
for l in content:
out += chr(ord(l)^ord("J")) # Xor content with "J"
with open("challoutput","wb") as f2:
f2.write(out)
xxd challoutput | head -n 1
00000000: 786f 725f 4b3a 2931 7914 2824 2f2e 2871 xor_K:)1y.($/.(q
We got a second xor with another letter.
Time to script
Here is my final script. Note that we got multiple algorithm (not only xor but also base32, base64, uuencode, bzip2, …). You can also notice that, sometimes, xor key is given as an integer.
cp chall chall0
import bz2
import base64
import zlib
def isInt(s):
try:
int(s)
return True
except ValueError:
return False
n = 0
while 1:
with open("chall"+str(n),"rb") as f:
l = f.read()
algo,content = l.split(":",1)
if "xor" in algo:
key = algo.replace("xor_","")
if not isInt(key):
key = ord(key)
else:
key = int(key)
out = ""
for l in content:
out += chr(ord(l)^key)
with open("chall"+str(n+1),"wb") as f:
f.write(out)
elif "base16" in algo:
with open("chall"+str(n+1),"wb") as f:
f.write(base64.b16decode(content))
elif "base32" in algo:
with open("chall"+str(n+1),"wb") as f:
f.write(base64.b32decode(content))
elif "base64" in algo:
with open("chall"+str(n+1),"wb") as f:
f.write(base64.b64decode(content))
elif "uu_codec" in algo:
with open("chall"+str(n+1),"wb") as f:
f.write(content.decode("uu"))
elif "bz2_codec" in algo:
with open("chall"+str(n+1),"wb") as f:
f.write(bz2.decompress(content))
elif "zlib_codec" in algo:
with open("chall"+str(n+1),"wb") as f:
f.write(zlib.decompress(content))
else:
print(algo)
n += 1
The program crash for the chall149 file.
cat chall149
breizhctf{crazy_encodings_looperz}
Flag
breizhctf{crazy_encodings_looperz}