Ransomware Documentation

fait par Thomas et Simon

Introduction

Pour commencer, veuillez noter qu'un ransomware est un programme malveillant et qu'il est donc fortement déconseillé de l'utiliser sans en connaitre son fonctionnement.

Celui-ci est un programme qui a été créé dans un but éducatif. Nous révoquons toutes responsabilités quant à l'usage que vous pourriez en faire.

Qu'est-ce qu'un ransomware

Un ransomware est un programme malveillant ayant pour but de couper l'accès à certaines données en les chiffrant afin que la personne victime du programme ne puisse plus y accéder. Le but est souvent de soutirer de l'argent en échange de la récupération de données, même si parfois, malgré le fait que la victime paye, la clef de déchiffrement ne sera jamais envoyée.

Le système de chiffrement utilisé est souvent symétrique car la vitesse de ce système est beaucoup plus rapide que le chiffrement asymétrique qui requiert deux clefs et qui est plus lent. Le chiffrement asymétrique est souvent utilisé pour envoyer la clef utilisée par le chiffrement symétrique afin qu'une tierce personne ne puisse la récupérer.

Le ransomware utilise aussi souvent le réseau, soit pour se propager, soit pour récupérer des informations (clef, données sensibles, ...) ce qui peut aussi être une faiblesse si l'adresse du serveur est retrouvée, ce qui permettrait d'identifier l'attaquant.

Fonctionnement global du ransomware

Created with Raphaël 2.2.0./ransomargc < 2 ?usage( )returnargc == 2 ?ENCRYPT = 1dir == argv[1]key == getKey( )encDir(dir, key)returnargc == 3 ?ENCRYPT = 0dir == argv[1]key == argv[2]yesnoyesnoyes

Le ransomware fonctionne comme ceci en ligne de commande : ./ransom <path> [key]

Compiler le programme

Il y a un Makefile qui permet de le compiler pour la plateforme de votre choix :

Porter le programme à une autre plateforme

Le programme est conçu de manière à ce que la partie ransomware sans serveur (main.c, libcom.c, libcom.h) puisse être portée d'une machine à une autre, à condition qu'elle dispose de la librairie C standard. La seule partie non portable du ransomware est la partie réseau qui est contenu dans les fichiers liblinet libwinpour Linuxet Windows, il vous suffit donc de porter cette partie pour porter complètement le ransomware sur votre plateforme.

Quant au serveur du ransomware, pour le porter sur Windows ou autre, tout sera à refaire puisque le code utilise les librairies système linux, même si les fonctions système pour les sockets ne changent pas beaucoup entre Linux et Windows.

Pour le serveur proxy, étant programmé en Go, il suffit de modifier les variables environnements GOOS et GOPATH qui permettent la compilation multiplateforme.

Les fonctions du ransomware

Les fonctions principales sont :

char* getKey()

getKey() va essayer de se connecter au serveur de l'attaquant afin de recevoir une clef, si cela échoue, le programme va utiliser une clef qui est directement écrite dans le code (qui sera chiffré avec les autres fichiers lors du processus de chiffrement)

int processFile(char* path, const char* key)

processFile(char *path, const char *key) reçoit le chemin du fichier à chiffrer ainsi que la clef. La fonction va regarder l'extension du fichier, si celui-ci ne se termine pas par .st alors le fichier sera chiffré

int encDir(char* path, const char* key)

encDir(char* path, const char* key) est la fonction principale du programme, c'est elle qui va boucler de manière récursive afin d'envoyer en argument les fichiers à processFile()

Fonctions à usage plus basique

FILE* openFile(const char* path, const char* mode) ouvre un fichier dans le mode donné en argument et examine s'il y a des erreurs, retourne un pointeur vers la structure du fichier

int closeFile(FILE*, FILE*) ferme le fichier d'entrée et de sortie

int docrypt(FILE* input, FILE* output, const char* key,int (*)(int, char[], const char*,int*)) reçoit un fichier d'entrée et de sortie et utilise la fonction donnée en argument pour soit chiffrer soit déchiffrer le fichier d'entrée

int encrypt(int n, char[n], const char*, int*) chiffre la chaine de caractères donnée en argument

int decrypt(int n, char[n], const char*, int*) déchiffre la chaine de caractères donnée en argument

char* addext(const char* path, const char* ext) ajoute l'extension .st au fichier et renvoie le nom du fichier

char* remext(const char* input) enlève l'extension .st au fichier et renvoie le nom du fichier

int isDir(char* path) examine si le chemin donné pointe vers un dossier ou non

char* addPath(const char* path, const char* file) ajoute le chemin d'accès complet au fichier et renvoie celui-ci à l'appelant

void leaveExplanation() écrit dans stdout et dans un fichier readme comment récupérer les données.

char* net_get(int* ID) reçoit un identifiant en argument et essaie de se connecter au serveur :
s'il n'y arrive pas alors l'identifiant est mit à 0
s'il y arrive alors renvoie la clef obtenue

void send_ID(SOCKET sock, int* ID) envoie l'identifiant au serveur afin qu'il puisse générer une clef unique

char* get_data(SOCKET sock) reçoit la clef du serveur

SOCKET set_socket() crée le socket avec les bons paramètres et le renvoie

SOCKADDR_IN set_addr() paramètre l'adresse ip et le port de destination du socket

int bytes_to_hexa(const unsigned char bytes_string[], char *hex_string, int size) convertit une chaine de caractères en hexa

int hexa_to_bytes(char hex_string[], unsigned char val[], int size); convertit un tableau de nombres hexa en chaine de caractères

Les fonctions du serveur

char *gen_key(int ID) génère une clef en utilisant l'identifiant donné en paramètre et renvoie la clef générée

void save(int ID, char* key, char* hkey) sauvegarde l'identifiant et la clef en ascii et en hexa dans un fichier

void handleClients(SOCKET sock) s'occupe d'un client (recevoir l'identifiant, générer la clef, envoyer la clef)

Serveur intermédiaire

Nous avons mis en place un proxy qui représente un service de serveur en ligne qui ne tient pas de journal. Cela permettrait à un attaquant d'engager le serveur le temps d'attaquer puis de se désinscrire sans laisser de traces. Le client ransomware n'aura que le serveur de service comme adresse, ce qui aide à protéger l'anonymat de l'attaquant.

Exemple

Conclusion

En conclusion, il est préférable de ne pas exécuter un programme sans être sûr de la provenance de celui-ci. Car en développant ce projet, surtout en faisant des tests, on se rend rapidement compte que sans la clef de déchiffrement, il est très difficile de pouvoir récupérer les fichiers intacts. En cas de manipulation distraite, une solution de rattrapage ne serait pas simple. Si malgré le versement d'argent, la clef n'est pas correcte, voire inexistante, une solution de dernier espoir serait d'essayer de récupérer un fichier à la force brute (essayer toutes les combinaisons possibles). Des backups sont donc fortement conseillés !