Eval me 2

Catégorie: Programmation Difficulté: - Flag: CTFREI{3v4l_1s_d4ng3r0u5}

Challenge

Description


Arriveras-tu à passer toutes les étapes de ce programme ?

Il est conseillé d'utiliser pwntools afin de résoudre ce challenge.

Connexion: nc vps.ctfrei.fr 5003

Solution

Le serveur nous envoie une série d'expressions mathématiques à résoudre, il faut donc créer un client TCP pour s'y connecter et y répondre en boucle.

Le challenge attend de nous que nous utilisions la fonction eval, ce que je déconseille impérativement (d'ailleurs la suite de ce challenge "Eval me 2" essaie de se jouer de ça pour nous tendre un piège)

Une recherche sur google permet de trouver des alternatives safe pour faire la même chose, comme cette réponse StackOverFlow (cimer chef)

En utilisant le même script que le challenge précédent (Eval me 1) on obtient une erreur puisque le serveur essaie de nous faire évaluer :

exec("f=open(file,'r').read()[::-1];open(file, 'w').write(f);exit()")

Heureusement que nous avions prévu le coup, sinon notre fichier aurait été réécrit à l'envers...

Il faut simplement aujouter à notre script le fait d'envoyer un message vide lorsqu'il ne peut pas résoudre l'expression. Pour éviter une boucle infinie, si le mot CTFREI est détecté dans le message reçu, on coupe la boucle

import socket
import ast
import operator as op

# Evaluation safe d'une expression mathématiques
operators = {
  ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul,
  ast.Div: op.truediv, ast.Pow: op.pow, ast.BitXor: op.xor,
  ast.USub: op.neg
}

def eval_expr(expr):
  return eval_(ast.parse(expr, mode='eval').body)

def eval_(node):
  match node:
    case ast.Constant(value) if isinstance(value, int):
      return value  # integer
    case ast.BinOp(left, op, right):
      return operators[type(op)](eval_(left), eval_(right))
    case ast.UnaryOp(op, operand):  # e.g., -1
      return operators[type(op)](eval_(operand))
    case _:
      raise TypeError(node)
      
# Connexion au serveur
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('vps.ctfrei.fr', 5003))

while True:
  try:
    # Récupération et affichage du message du serveur
    data = client.recv(2048).strip().decode()
    print(data)
    
    # Quitte la boucle si le mot est dans la réponse du serveur
    if 'CTFREI' in data:
      break
    
    # Récupération de l'expression à résoudre dans le message
    expr = data.split('\n')[-1]
    
    # Evaluation de l'expression
    answer = eval_expr(expr)
    
    # Envoie de la réponse
    client.send(f"{answer}\n".encode())
  except:
    # Envoie un mesage vide si l'expression n'a pas pu être évaluée
    client.send(b"\n")

Dernière mise à jour

Cet article vous a-t-il été utile ?