diff --git a/src/assets/images/deadface-ctf-23/filtered-ransomware.png b/src/assets/images/deadface-ctf-23/filtered-ransomware.png new file mode 100644 index 0000000..ac3d039 Binary files /dev/null and b/src/assets/images/deadface-ctf-23/filtered-ransomware.png differ diff --git a/src/assets/images/deadface-ctf-23/ransomwared.png b/src/assets/images/deadface-ctf-23/ransomwared.png new file mode 100644 index 0000000..2d8e136 Binary files /dev/null and b/src/assets/images/deadface-ctf-23/ransomwared.png differ diff --git a/src/assets/images/spectrogram.png b/src/assets/images/deadface-ctf-23/spectrogram.png similarity index 100% rename from src/assets/images/spectrogram.png rename to src/assets/images/deadface-ctf-23/spectrogram.png diff --git a/src/content/blog/deadface-ctf.md b/src/content/blog/deadface-ctf.md index 29b9e88..84426db 100644 --- a/src/content/blog/deadface-ctf.md +++ b/src/content/blog/deadface-ctf.md @@ -49,6 +49,26 @@ Xen0M0rphMell0wz Il est probable que le mot de passe entré dans le terminal lors de l'exécution du programme soit comparé avec une chaîne de caractères et celle-ci pourrait bien être `Xen0M0rphMell0wz`. On relance donc le programme en entrant la chaîne précédemment trouvée lorsque le mot de passe est demandé. Bingo c'est le flag : `flag{XENO-DO-DO-DO-DO-DO-DOOOOO}`. +## Steganographie + +### You've been ransomwared + +On nous propose dans cette épreuve de retrouver le pseudonyme de l'attaquant ayant effectué une attaque par rançongiciel. Pour cela, nous avons l'image suivante à disposition : + +![Rançongiciel](@assets/images/deadface-ctf-23/ransomwared.png) + +Lorsque l'on regarde l'image de très près, il semble que l'on puisse distinguer du texte tout en bas de celle-ci écrit en rouge sur fond rouge. Pour plus de lisibilité, on peut ouvrir l'image avec `Gimp` et jouer avec la balance des couleurs. Cela nous donne l'image suivante : + +![Rançongiciel](@assets/images/deadface-ctf-23/filtered-ransomware.png) + +En saisissant le texte mis en évidence dans un traducteur de binaire, on obtient : + +```md +This ransomware brought to you by mirveal. +``` + +On a donc le flag : `flag{mirveal}` + ## Traffic analysis ### Git rekt @@ -172,6 +192,6 @@ Cette fois-ci on récupère une archive contenant un fichier `Untitlednosubject. On ouvre donc le fichier avec `audacity` et on affiche le spectrogramme avant de zoomer sur la partie qui nous intéresse. On découvre alors ceci : -![Spectrogramme](@assets/images/spectrogram.png) +![Spectrogramme](@assets/images/deadface-ctf-23/spectrogram.png) Il s'agit évidemment du mot de passe du fichier ou se trouve le nom de l'exécutable. On en déduit le flag : `flag{Wh1t3_N01Z3.exe}` \ No newline at end of file diff --git a/src/content/blog/ecw-ctf.md b/src/content/blog/ecw-ctf.md new file mode 100644 index 0000000..51890c1 --- /dev/null +++ b/src/content/blog/ecw-ctf.md @@ -0,0 +1,228 @@ +--- +author: Jean Chaput +pubDatetime: 2023-10-30T10:53:00Z +title: Write-up ECW CTF +postSlug: ecw-ctf +featured: true +draft: false +tags: + - ctf + - write-up +description: + Write-up de la ECW CTF +--- + +La ECW CTF s'est déroulée du 13 au 29 octobre 2023 et je propose ici une correction de deux épreuves. Plus de corrections seront proposées par un coéquipier sur [ce site web](https://www.enzo-cadoni.fr). La découverte tardive du déroulé de ces qualifications en pleine période de projet universitaire ne m'aura pas permis d'en faire plus. + +## Table des matières + +## Forensics + +### DumpCyber + +Pour cette épreuve de forensics, on démarre avec une image disque d'un système inconnu. Pour commencer, on peut essayer d'en savoir plus sur le système d'où provient l'image en question : + +```sh +sudo ~/Tools/volatility3-2.5.0/vol.py -f task.raw windows.info +``` + +Le résultat affiché est le suivant. + +```md +Volatility 3 Framework 2.5.0 +Progress: 100.00 PDB scanning finished +Variable Value + +Kernel Base 0xf8000260c000 +DTB 0x187000 +Is64Bit True +IsPAE False +layer_name 0 WindowsIntel32e +memory_layer 1 FileLayer +KdDebuggerDataBlock 0xf800027fd0a0 +NTBuildLab 7601.17514.amd64fre.win7sp1_rtm. +CSDVersion 1 +KdVersionBlock 0xf800027fd068 +Major/Minor 15.7601 +MachineType 34404 +KeNumberProcessors 1 +SystemTime 2023-08-17 16:20:26 +NtSystemRoot C:\Windows +NtProductType NtProductWinNt +NtMajorVersion 6 +NtMinorVersion 1 +PE MajorOperatingSystemVersion 6 +PE MinorOperatingSystemVersion 1 +PE Machine 34404 +PE TimeDateStamp Sat Nov 20 09:30:02 2010 +``` + +Étant donné qu'il s'agit d'une image disque windows, on peut utiliser le module `windows.filescan.FileScan` pour en lister les fichiers. Pour plus de simplicité, on redirige la sortie vers un fichier texte que l'on pourra parcourir par la suite : + +```sh +sudo ~/Tools/volatility3-2.5.0/vol.py -f task.raw windows.filescan.FileScan > files.txt +``` + +Maintenant que l'on a une liste des fichiers contenus dans le système, on a envie d'aller voir du côté des répertoires utilisateurs car c'est souvent ici que l'on trouve des choses intéressantes. Pour cela, on liste le répertoire utilisateur comme suit : + +```sh +cat files.txt | grep '\\Users' +``` + +On se rend compte qu'il y a un seul utilisateur `vboxuser` et en parcourant un peu ses fichiers il semble qu'il y ai des choses prometteuses sur son bureau. On liste donc le contenu de celui-ci : + +```sh +cat files.txt | grep '\\Users\\vboxuser\\Desktop\\' +``` + +```md +0x2fae8c0 \Users\vboxuser\Desktop\desktop.ini 216 +0xef58430 \Users\vboxuser\Desktop\file.rar 216 +0x3fa144a0 \Users\vboxuser\Desktop\generator.rar 216 +0x3fa18070 \Users\vboxuser\Desktop\file.txt.rar 216 +0x3fab94a0 \Users\vboxuser\Desktop\generator.rar 216 +0x3fabd070 \Users\vboxuser\Desktop\file.txt.rar 216 +0x3fb5e4a0 \Users\vboxuser\Desktop\generator.rar 216 +0x3fb62070 \Users\vboxuser\Desktop\file.txt.rar 216 +0x3fcd2430 \Users\vboxuser\Desktop\dessktop.ini 216 +0x3fd737b0 \Users\vboxuser\Desktop\deesktop.ini 216 +``` + +Maintenant que l'on dispose d'une liste de fichiers et de leurs adresses, on peut procéder à la récupération de ceux-ci : + +```sh +sudo ~/Tools/volatility3-2.5.0/vol.py -f task.raw -o ./ windows.dumpfiles.DumpFiles --physaddr 0x3fab94a0 +sudo ~/Tools/volatility3-2.5.0/vol.py -f task.raw -o ./ windows.dumpfiles.DumpFiles --physaddr 0x3fa18070 +sudo ~/Tools/volatility3-2.5.0/vol.py -f task.raw -o ./ windows.dumpfiles.DumpFiles --physaddr 0xef58430 +``` + +Étant donné qu'il s'agit de fichiers `.rar`, on procède à leur extraction : + +```sh +unrar x file.txt.rar +unrar x generator.rar +unrar x file.rar +``` + +On se retrouve donc avec un fichier `file.txt.enc` qui semble être un fichier chiffré. Rien d'étonnant puisque l'on nous demande de retrouver une clé et un vecteur d'initialisation. En plus de cela, on dispose de deux exécutables : `generator.exe` et `encryptor.exe`. + +A ce moment là on aurait pu procéder de plusieurs manières différentes mais pour ma part, j'ai simplement exécuté le générateur : + +```sh +wine generator.exe +``` + +Cela nous produit deux fichiers : `dessktop.ini` et `deesktop.ini`. C'est une très bonne piste puisqu'on se rappelle avoir vu ces fichiers sur le bureau de `vboxuser`. On passe donc à l'extraction de ces deux fichiers dont l'un doit-être notre clé et l'autre le vecteur d'initialiation : + +```sh +sudo ~/Tools/volatility3-2.5.0/vol.py -f task.raw -o ./ windows.dumpfiles.DumpFiles --physaddr 0x3fcd2430 +sudo ~/Tools/volatility3-2.5.0/vol.py -f task.raw -o ./ windows.dumpfiles.DumpFiles --physaddr 0x3fd737b0 +``` + +Pour savoir lequel est la clé et lequel est le vecteur d'initialisation on aurait pû décompiler le générateur, ou bien simplement essayer à tour de rôle. On essaye donc le déchiffrement AES du chiffré suivant sur le [Cyberchef](https://cyberchef.org/) : + +```md +e609874a80d1b27efd46cc0a131a4dcd01a866f5e31a99ae56ed91d8c517 +5c8b88a0d8d8c6412889bac60d5999cf61517bfdbf7f9fc6e2fa530e4263 +bd92af6a +``` + +Notre clé est `1b54ee420bd5b8396e15fc9fe01055f8` et le vecteur d'initialisation `e609874a80d1b27efd46cc0a131a4dcd`. En réglant le déchiffrement sur `CBC/NoPadding`, on obtient le texte clair suivant : + +```md +=À;K õ®AlñÐ 0flag{82a30fadcfc07d634fbed1bffe4a2aa1} +``` + +On a donc notre flag : `flag{82a30fadcfc07d634fbed1bffe4a2aa1}`. + +## Cryptographie + +### Random_key + +Cette épreuve de cryptographie tourne autour de deux fichiers. + +Le premier est un script **Python** : + +```python +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from ctypes import * +from Crypto.Cipher import AES + +SO_FILE = './generate_key.so' +FLAG_FILE = '../../flag.txt' + +with open(FLAG_FILE, 'r') as f: + FLAG = f.read().encode() + +def encrypt(plaintext, key): + return AES.new(key, AES.MODE_CBC, b'FEDCBA9876543210').encrypt(plaintext) + +if __name__ == '__main__': + print("""Un message chiffré a été envoyé par l'IA ALICE à son centre de contrôle. Vous avez réussi à mettre la main sur certains extraits de code utilisés par ALICE pour chiffrer son message ainsi que sur le texte chiffré. Votre mission est de retrouver le message en clair.""") + + generate_256bits_encryption_key = CDLL(SO_FILE).generate_256bits_encryption_key + generate_256bits_encryption_key.restype = c_char_p + key = generate_256bits_encryption_key(b'Control_center').hex().encode() + + enc = encrypt(FLAG, key) + print('Enc:', enc.hex()) + + # Enc: 21952f9ced6c9109f8ce7c41cd3e0e6981c97a84745d5fdc75b2584e9a5a05e0 +``` + +Le deuxième est un code en **C** : + +```c +unsigned char key[32] = { 0 }; + +void md5(unsigned char *in, unsigned char *out) +{ + MD5_CTX ctx; + MD5_Init(&ctx); + MD5_Update(&ctx, in, strlen(in)); + MD5_Final(out, &ctx); +} + +unsigned char *generate_256bits_encryption_key(unsigned char *recipient_name) +{ + int i = 0; + FILE *f = NULL; + time_t now1 = 0L; + time_t now2 = 0L; + time_t delta = 0L; + + now1 = time(NULL); + + f = fopen("/dev/urandom", "rb"); + fread(&key, 1, 32, f); + fclose(f); + + md5(recipient_name, key); + + now2 = time(NULL); + delta = now2 - now1; + + key[8] = delta; + + return key; +} +``` + +On se rend rapidement compte que pour chiffrer le flag, Alice a utilisé `FEDCBA9876543210` en vecteur d'initialisation ainsi qu'une clef générée par la fonction `generate_256bits_encryption_key(unsigned char *recipient_name)` avec comme paramètre : `Control_center`. + +Quand on regarde d'un peu plus près cette fonction, on voit que le procédé de création de la clef est le suivant : +1. Initialisation de la clef avec des valeurs aléatoires sur les 32 octets de `key` +2. Calcul du MD5 de `Control_center` et insertion dans les 16 premiers octets de `key` +3. Insertion du temps de calcul du MD5 dans la case d'indice 8 de `key` (9ème case) + +Ce procédé présente un problème. Le calcul du MD5 étant plus rapide qu'une seconde, le caractère `O` sera toujours inséré dans `key[8]`. Étant donné que l'octet nul est le caractère de fin de chaîne en **C** et que la clé est récupérée comme telle par le script **Python**, la clé est donc la moitié du MD5 de `Control_center`. + +```md +echo -n "Control_center" | md5sum +134abb7bd9d248a98d914daea81a8737 - +``` +On essaye donc le déchiffrement du flag sur notre [Cyberchef](https://cyberchef.org/) préféré avec comme vecteur d'initialisation `FEDCBA9876543210` et comme clef `134ABB7BD9D248A9` saisis en `UTF-8`. L'application de l'algorithme `CBC/NoPadding` nous donne le flag suivant : `ECW{random_key_7AgmwlBXo1tDhyqR}`. + +Et voilà, challenge validé. \ No newline at end of file