Solution de U03 pour Hamac

intro crypto symétrique

25 janvier 2025

Nous devons retrouver le flag qui a été chiffré en avec l’algorithme AES en mode CBC avec un vecteur d’initialisation (iv).

iv = get_random_bytes(16)
k  = SHA256.new(password).digest()
c  = AES.new(k, AES.MODE_CBC, iv = iv).encrypt(pad(open("flag.txt", "rb").read(), 16))
r = {
	"iv": iv.hex(),
	"c": c.hex(),
	"h": h.hexdigest(),
}

Pour procéder au déchiffrement il nous faut les 3 éléments qui ont été utilisés pour le chiffrement :

{
  "iv": "ea425b2ea4bb67445abe967e3bd1b583",
  "c": "69771c85e2362a35eb0157497e9e2d17858bf11492e003c4aa8ce1b76d8d3a31ccc3412ec6e619e7996190d8693299fc3873e1e6a96bcc1fe67abdf5175c753c09128fd1eb2f2f15bd07b12c5bfc2933",
  "h": "951bd9d2caae0d9e9a5665b4fc112809aac9f5f9ecbcfc5ad8e23cb1d020201d"
}

Nous ne disposons pas directement de clé de chiffrement, cette clé est le SHA256 d’un mot de passe entré pour l’ulisateur pour chiffer le flag.

Nous n’avons pas le mot de passe en question, uniquement une valeur h qui est le résultat d’un HMAC du texte FCSC2022 avec l’algorithme SHA256 et le mot de passe comme clé.

h = HMAC.new(password, digestmod = SHA256)
h.update(b"FCSC2022")

Les algorithmes de hachage sont par nature difficilement inversibles et donc notre seul espoir est d’utiliser la force brute pour trouver le mot de passe… Heureusement, même si l’énoncé de l’épreuve est énigmatique et pas très long il fait référence à “rockyou” qui est une base de mot de passe classiques.

Nous pourrions écrire un programme pour essayer tous les mots de passe et trouver celui qui permet d’obtenir 951bd9d2caae0d9e9a5665b4fc112809aac9f5f9ecbcfc5ad8e23cb1d020201d comme résultat du HMAC_SHA256. Il existe un programme appelé hashcat qui permet de faire ce genre de choses de manière plus performante en utilisant au mieux les ressources matérielles disponibles (CPU/GPU/FPGA…)

Pour utiliser hashcat nous devons contruire un fichier avec le HMAC et la valeur sur laquelle porte le HMAC :

951bd9d2caae0d9e9a5665b4fc112809aac9f5f9ecbcfc5ad8e23cb1d020201d:FCSC2022

On appelle hashcat comme ceci:

# hash-type  : 1450 (HMAC-SHA512 (key = $pass)
# attack-mode: 0 (Straight: A partir d'un fichier dictionnaire)
#
hashcat --hash-type 1450 --attack-mode 0 hashcat.txt rockyou.txt.gz

Nous pouvons écrire un programme qui automatise les opérations à partir du fichier output.txt :

#!/usr/bin/python3 

from Cryptodome.Cipher import AES
from Cryptodome.Util.Padding import pad, unpad
from Cryptodome.Hash import HMAC, SHA256
from Cryptodome.Random import get_random_bytes

import json
import subprocess

j = json.loads(open("output.txt", "r").read())

print(f"iv: {j['iv']}\n c: {j['c']}\n h: {j['h']}\n")

with open('hashcat.txt', 'w') as f:
    f.write(f"{j['h']}:FCSC2022")

hashcat = subprocess.run("hashcat --quiet --potfile-disable --hash-type 1450 --attack-mode 0 hashcat.txt rockyou.txt.gz".split(), stdout=subprocess.PIPE)

password = hashcat.stdout[:-1].split(b':')[2]

print(f"password: {password}")

k  = SHA256.new(password).digest()

flag  = unpad(AES.new(k, AES.MODE_CBC, iv = bytes.fromhex(j['iv'])).decrypt(bytes.fromhex(j['c'])), 16)

print(flag)

Le script suivant automatise les opérations :

#!/bin/bash

set -e

if [ ! -f output.txt ]; then
    wget https://hackropole.fr/challenges/fcsc2022-crypto-hamac/public/output.txt -O output.txt
fi

if [ ! -f rockyou.txt.gz ]; then
    wget https://gitlab.com/kalilinux/packages/wordlists/-/raw/kali/master/rockyou.txt.gz -O rockyou.txt.gz
fi

python3 025_Hamac.py

Le résultat est le suivant :

--2025-01-25 21:10:11--  https://hackropole.fr/challenges/fcsc2022-crypto-hamac/public/output.txt
Resolving hackropole.fr (hackropole.fr)... 51.91.236.193, 2001:41d0:301::28
Connecting to hackropole.fr (hackropole.fr)|51.91.236.193|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 284 [text/plain]
Saving to: ‘output.txt’
output.txt                                         100%[====>]     284  --.-KB/s    in 0s      
2025-01-25 21:10:12 (102 MB/s) - ‘output.txt’ saved [284/284]

--2025-01-25 21:10:12--  https://gitlab.com/kalilinux/packages/wordlists/-/raw/kali/master/rockyou.txt.gz
Resolving gitlab.com (gitlab.com)... 172.65.251.78, 2606:4700:90:0:f22e:fbec:5bed:a9b9
Connecting to gitlab.com (gitlab.com)|172.65.251.78|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 53357341 (51M) [application/octet-stream]
Saving to: ‘rockyou.txt.gz’
rockyou.txt.gz                                     100%[====>]  50,88M  26,8MB/s    in 1,9s    
2025-01-25 21:10:14 (26,8 MB/s) - ‘rockyou.txt.gz’ saved [53357341/53357341]

iv: ea425b2ea4bb67445abe967e3bd1b583
 c: 69771c85e2362a35eb0157497e9e2d17858bf11492e003c4aa8ce1b76d8d3a31ccc3412ec6e619e7996190d8693299fc3873e1e6a96bcc1fe67abdf5175c753c09128fd1eb2f2f15bd07b12c5bfc2933
 h: 951bd9d2caae0d9e9a5665b4fc112809aac9f5f9ecbcfc5ad8e23cb1d020201d

password: b'omgh4xx0r'
b'FCSC{xxxxxxxx}'