One of our VIP clients, who wishes to remain anonymous, has apparently been hacked and all their important documents are now corrupted. Can you help us recover the files? We found a strange piece of software that might have caused all of this. MD5 of the file : ccaab91b06fc9a77f3b98d2b9164df8e Fichiers: http://cloud.id-iot.team/s/e2ZgLdHKwMoFQ8x
Etat des lieux
Cette épreuve commence donc avec une archive zip contenant plusieurs fichiers:
Le fichier “READ_THIS.txt” contient un message charmant:
We have hacked all your files. Buy 1 BTC and contact us at hacked@virus.com
Le fichier “virus.cpython-37.pyc” rappelle un fichier de python compilé. Malheureusement pycdc ne décompile pas correctement le “virus”. Heureusement qu’il existe des outils en ligne pour tout et n’importe quoi:
Le résultat est vraiment mieux, après corrections de quelques petites choses, on obtient le code suivant:
|
|
Bien plus simple à analyser.
Analyse du code python
Rien qu’avec les imports, on voit que le malware va faire de l’AES et probablement générer clé / iv de manière aléatoire. Ensuite, les variables globales peuvent interpeler:
- TARGET_DIR: le repertoire à chiffrer;
- C2_URL: l’url du serveur de command and control de l’attaquant, en l’occurence il n’existe pas / plus;
- TARGETS: une ribambelle de noms et prénoms.
La fonction qui va être intéressante est lock_file(path)
. Les premières lignes vont servir à générer la clé AES:
|
|
La clé est donc le md5 du username. Les deux lignes suivantes servent à initialiser l’AES:
|
|
Il faut de l’AES ECB avec comme clé le md5(username)
et génère un vecteur d’initialisation (IV). Hors, l’AES ECB n’a pas d’IV.
Les deux lignes suivantes envoient les paramètres AES au serveur de command and control:
|
|
Bon, et maintenant le vif du sujet: la crypto. On va reprendre cette fonction en ne gardant que l’algo:
|
|
L’algo “tambouille”, rappelle l’AES CBC, utilisant l’IV. A savoir que la différence entre l’AES ECB et CBC est justement ce vecteur d’initialisation. Le schéma suivant représente l’AES CBC lors du chiffrement:
On admet donc que c’est de l’AES CBC dont on connait la clé mais pas l’IV. On peut dire qu’on connait la clé, car les usernames utilisées sont présent dans la liste TARGETS, il suffira de bruteforce pour trouver le bon.
Euréka
Analysons les informations en notre possessions:
- Images JPEG chiffrées
- AES CBC dont on connait la clé mais pas l’IV
Et ci-dessous le schéma de déchiffrement de l’AES CBC:
Le schéma ci-dessus donne une information vraiment intéressante: si on ne connais pas l’IV, seul le premier block sera illisible, mais tout le reste se base sur la clé.
On peut faire un test très simple:
|
|
On génère un chiffré d’une string connue avec un IV aléatoire et on déchiffre avec la clé mais un IV fait que de null bytes. Ce snippet retourne:
b’\xf3fw\xf6\x15MFTq\xbd\xad\x9c\xbd\x06\xad\x83aucoup les fleurs, surtout quand elle sentent bo'
Seul le premier block est illisible. Le second est parfaitement déchiffré.
Format JPEG
Intéressons nous au format JPEG, pour savoir s’il est possible de reconstruire ce premier block. Prenons 3 images aléatoires sur Google images:
- http://image.jeuxvideo.com/medias-md/157675/1576752756-4689-card.jpg
- https://static.lpnt.fr/images/2017/08/07/9591045lpw-9591057-article-jpg_4474173_980x426.jpg
- https://www.digital.security/fr/sites/default/files/illu-actu/logo_digital-security.jpg
|
|
Maintenant regardons les headers de ces 3 images JPEG:
|
|
Une bonne partie du premier block est identique. En patchant le future fichier déchiffré avec:
ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01
Alors il est possible que l’image soit déchiffrée malgrès l’absence de l’IV. Cependant, avant de faire ça, il faut trouver le bon username pour trouver la clé AES.
Pour cela, on sait que le premier bloc déchiffré sera le dernier bloc de la photo. De plus, on sait qu’un fichier JPEG se termine toujours par \xff\xd9
:
|
|
Trouver la clé AES
Sachant ça, on peut supposer que le username utilisé est dans la liste “TARGETS”. Le snippet suivant va bruteforce jusqu’à trouver la signature de fin:
|
|
Jack Sheerack
Le MD5 de ce username est donc la clé.
Déchiffrer les images
Maintenant qu’on a la clé et qu’on peut potentiellement reconstruire le header d’un JPEG, il ne reste qu’à tester sur une image:
|
|
Ce qui donne:
Flag
SANTA{Jacques_Th3_R1pp3R}