BreizhCTF 2019: CrazyLooper
Détails du challenge
| Event | Challenge | Category | Points | Solves |
|---|---|---|---|---|
| BreizhCTF 2019 | CrazyLooper | Programmation | 150 | 2 |
Challenge : chall md5sum : 339457087fe3c986e45937eaf26cbfea
TL;DR
Nous avions un fichier encodé récursivement avec plusieurs algorithmes. Chaque algorithme était indiqué au début du fichier décodé. Nous avons écrit un programme qui décode récursivement le premier fichier jusqu’à obtenir le dernier texte en clair.
Méthodologie
Premier coup d’œil au fichier
La commande file ne nous a renvoyé que « data », mais un examen plus approfondi du début du fichier nous a apporté davantage d’informations :
xxd chall | head -n 1
00000000: 786f 725f 4a3a 3225 3815 0170 637b 335e xor_J:2%8..pc{3^
Nous avons constaté que le fichier commence par « xor_J: », ce qui signifie qu’il faut décoder le fichier en effectuant un xor avec la lettre « J ».
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
Nous obtenons un second xor avec une autre lettre.
Passons au script
Voici mon script final. À noter que nous avons plusieurs algorithmes (pas seulement xor mais aussi base32, base64, uuencode, bzip2, …). Vous pouvez également remarquer que, parfois, la clé xor est donnée sous forme d’entier.
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
Le programme plante pour le fichier chall149.
cat chall149
breizhctf{crazy_encodings_looperz}
Flag
breizhctf{crazy_encodings_looperz}