Le fichier lapin.py
chiffre le flag avec AES-GCM, en utilisant une clé dérivée du code PIN (un entier à 4 chiffres) avec la fonction scrypt.
Pour retrouver le flag, il faut :
- Deviner le PIN (il y a au maximum 9999 possibilités).
- Reconstituer la clé à partir du PIN avec scrypt().
- Déchiffrer le flag avec AES-GCM.
Nous pouvons bruteforcer le PIN en testant toutes les valeurs possibles (0001
à 9999
) et voir laquelle permet de déchiffrer correctement le message.
Voici un script Python qui le fait :
from Crypto.Cipher import AES
from Crypto.Protocol.KDF import scrypt
from Crypto.Util.number import long_to_bytes
import binascii
# Données fournies
enc_hex = "f049de59cbdc9189170787b20b24f7426ccb9515e8b0250f3fc0f0c14ed7bb1d4b42c09d02fe01e0973a7233d99af55ce696f599050142759adc26796d64e0d6035f2fc39d2edb8a0797a9e45ae4cd55074cf99158d3a64dc70a7e836e3b30382df30de49ba60a"
enc = bytes.fromhex(enc_hex)
# Séparation des éléments (nonce, ciphertext, tag)
nonce, ciphertext_tag = enc[:16], enc[16:]
ciphertext, tag = ciphertext_tag[:-16], ciphertext_tag[-16:]
salt = b"FCSC"
# Brute-force des PINs possibles
for pin in range(1, 10000):
pin_bytes = long_to_bytes(pin)
key = scrypt(pin_bytes, salt, 32, N=2**10, r=8, p=1)
try:
aes = AES.new(key, AES.MODE_GCM, nonce=nonce)
flag = aes.decrypt_and_verify(ciphertext, tag)
print(f"PIN trouvé : {pin}")
print(f"Flag : {flag.decode()}")
break
except Exception:
continue
Explication du script :
- Conversion de l’hexadécimal : on transforme la sortie
enc.hex()
en bytes. - Séparation des parties :
- nonce (16 octets)
- ciphertext et tag (les 16 derniers octets sont le tag)
- Bruteforce du PIN :
- On génère la clé avec scrypt
- On tente de déchiffrer le texte
- Si la vérification
decrypt_and_verify
ne lève pas d’erreur, alors le bon PIN a été trouvé.
Ce script récupérera le flag en quelques secondes, car il ne teste que 9999 valeurs au maximum.