ZZZ
Catégorie: Reverse Difficulté: - Flag: CTFREI{1_h0p3_u_us3d_Z3_lol}
Challenge
Description
Sauras-tu trouver le bon flag à rentrer ?
Le flag est sous le format : CTFREI{flag_trouvé}
Solution
z3 solver est un outil pour résoudre des contraintes logiques et arithmétiques. Ici, j'utilise une librairie différente nommée pyton-constraint permettant également de résoudre des CSP (Constraint Satisfaction Problems). Elle est sans doute beaucoup moins performante, mais plus facile à appréhender.
On commence par créer un problème, on définit ensuite les variables que l'on va utiliser (je les ai nommées comme dans zzz.py a[0]
, a[1]
, etc. pour simplifier le parsing). Et enfin, on ajoute les contraintes. La librairie va ensuite optimiser les relations pour trouver une solution.
from constraint import Problem
import string
import re
# Création du problème à résoudre par contraintes
problem = Problem()
# Ajout des variables utilisées, on les nomme quand dans zzz.py
problem.addVariables([f'a[{i}]' for i in range(20)], [ord(c) for c in string.printable])
# Parsing du fichier zzz.py pour récupérer les conditions
with open('zzz.py', 'r') as f:
zzz = f.read().splitlines()
if_lines = zzz[4:47:2] # Les conditions sont toutes les 2 lignes à partir de la n°5
for line in if_lines:
# On skip les conditions sum() car inutiles et complique le parsing
if 'sum' in line:
continue
line = line.strip()[3:-1] # Retire le "if " au début de la ligne et ":" à la fin
calcul, result = line.split(' != ') # Sépare le calcul du résultat attendu
variables_used = list(set(re.findall('(a\[\d+\])', calcul))) # Récupère les variables utilisées dans le calcul
replace_variables_by = [(variables_used[i], 'abcdefg'[i]) for i in range(len(variables_used))] # Map chaque variable à une nouvelle lettre
for variable, new in replace_variables_by:
calcul = calcul.replace(variable, new) # Remplace dans le calcul les variables par leur nouvelle lettre
parameters = ', '.join([new for _, new in replace_variables_by]) # Les paramètres de la fonction lambda sont l'ensemble des lettres utilisées dans le calcul
constraint = f'lambda {parameters}: {calcul} == {result}'
variables = tuple([variable for variable, _ in replace_variables_by])
eval(f'problem.addConstraint({constraint}, {variables})') # On ajoute la contrainte qu'on vient de créer
# Calcul d'une solution (y en a qu'une seule de toutes façons)
solution = problem.getSolution()
# Les valeurs des variables sont l'ascii des caractères du flag
flag = ''.join([chr(solution[f'a[{i}]']) for i in range(20)])
print(f'CTFREI{{{flag}}}')
# CTFREI{1_h0p3_u_us3d_Z3_lol}
Dernière mise à jour
Cet article vous a-t-il été utile ?