Where hacking and UX meet

Desjardins : Analyse dynamique de programme malveillant

J’ai participé récemment au UnitedCTF, une compétition individuelle organisée par un regroupement de clubs de cybersécurité d’universités québécoises. La coopérative Desjardins, banque bien implantée au Québec, y avait également envoyé un représentant afin de développer une track sur l’analyse dynamique de logiciels malveillants. N’ayant pratiquement jamais fait cela avant, je me suis lancé dessus directement. Au total, on retrouvait cinq défis qui nous menaient vers notre objectif.

Outils

Les énoncés des défis suggéraient certains outils à utiliser pour résoudre la track. J’ai personnellement utilisé les suivants :

  • Wireshark (capture réseau et analyse de paquets)
  • Burp Suite Community Edition (proxy permettant entre autre d’intercepter des paquets, mais aussi plusieurs types d’attaques)
  • Flask (extension Python qui permet la mise en place rapide de serveurs HTTP avec des routes configurées)
  • Procmon64 (utilitaire qui permet de capturer les différents événements système selon leur catégorie)
  • Machine virtuelle Windows 11 avec VMWare

Premier défi : Proxy Address

The malware communicates over HTTPS, using a hardcoded proxy. What is the proxy the malware uses? It is recommended to solve this challenge with procmon or wireshark. Format: {ip}:{port}

L’approche suggérée était d’utiliser Procmon pour résoudre cette partie du défi. Procmon n’était pas un outil avec lequel j’étais familier, mais j’ai pu en apprendre dessus en l’utilisant pour ce flag spécifique. Notamment, il est possible de l’utiliser pour filtrer seulement les événements réseaux. L’idée ici est d’exécuter le fichier fourni, malware.exe, dans notre VM et d’«espionner» avec Procmon les différents événements réseaux. J’ai toutefois omis de mettre un filtre au début pour pouvoir voir l’ensemble des événements qui se déroulaient autour de l’exécution de malware.exe. J’ai remarqué que le fichier générait un dossier temporaire dans lequel il créait un fichier main.exe pour tout de suite le supprimer après l’avoir lancé! Fort de cette découverte, j’ai mis des filtres dans Procmon sur les deux fichiers: malware.exe et main.exe. En sélectionnant seulement les événements réseaux, j’ai remarqué que les communications du main.exe s'effectuaient à partir de ma machine… vers ma machine. On en comprend que le proxy est fort probablement localhost:8080, et c’était en effet la réponse pour ce défi.

On aurait aussi pu le réaliser avec Wireshark (j’ai longtemps essayé), mais il faut avoir la présence d’esprit de capturer les paquets sur l’interface de localhost, ce qui ne m’est jamais venu à l’idée, persuadé que j’étais qu’on recherchait une adresse IP externe.

Événements réseaux pertinents

Deuxième défi : First connection test

Before reaching to it's real C2 domain, the malware tests that internet connectivity works by reaching out to a known Website (to prevent sandboxes to extract the C2 easily). What is the URI (the part after the domain name, including the first /) of the first request?

Il était proposé de résoudre ce second défi à l’aide de Burp, donc c’est ce que j’ai fait. Par bonheur et heureux hasard (!) (wink) l’adresse par défaut sur laquelle écoute Burp est localhost:8080, donc le main.exe s’y connectait directement. Ainsi, en exécutant le malware avec Burp ouvert, on pouvait voir dans l’historique des requêtes HTTP la requête que le malware faisait et on avait directement accès au URI qui était le flag pour ce défi.

Deuxième Flag 

Troisième défi : HTTPS connection test

The malware then does a call to the same domain, but with a different URI and using HTTPS. What is this new URI? Note: The malware checks that the certificate is trusted by the machine.

Ici, on nous informe que le malware utilise ensuite HTTPS dans la requête subséquente. La note nous donne un indice important: la malware vérifie si le certificat en est un auquel la machine fait confiance.

Il faut savoir que Burp, comme proxy, s’impose comme intermédiaire entre le malware et le domaine qu’il cherche à contacter. Pour que Burp puisse intercepter les requêtes HTTPS et qu’il soit possible d’en lire le contenu, il faut que le malware utilise le certificat de Burp pour chiffrer la communication. Burp peut ensuite le déchiffrer et négocier la connexion avec le domaine final de son côté. Chaque installation de Burp a son propre certificat, il est donc impossible que la machine lui fasse confiance par défaut - le certificat de Burp n’est pas installé dessus.

Étapes pour exporter le certificat de l'installation de Burp

La figure ci-dessus montre comment obtenir le certificat de Burp. Il peut ensuite être installé dans les certificats de confiance de la machine, ce qui fait que le malware peut effectuer la seconde requête sans problème. On obtient alors le 3e flag en exécutant à nouveau malware.exe.

Troisième Flag

Quatrième défi : C2 Domain

The malware then does a call to the same domain, but with a different URI and using HTTPS. What is this new URI?

Cette partie du défi était plutôt simple considérant que la requête apparaissait directement suivant celle faite via HTTPS. La requête est faite sur le domaine totallylegitdomain-notevil.cn et il s’agit en toute logique du C2 (command and control center - centre de commande et de contrôle, bref, là où le malware communique). Il s’agit du quatrième et avant-dernier flag.

Quatrième Flag

Cinquième flag : C2 Handshake

Solving the previous challenge should reveal the real C2 behind this malware. However, before actually sending information to the server, a handshake is done to ensure the server is legitimate. Our CTI team told us that usually, the server needs to respond with the following content: None. Then, legend says the malware spits out a flag…

Il y avait plusieurs façons de résoudre le cinquième défi. Il fallait s’arranger pour que le serveur réponde à la requête sur /handshaketest, toutefois le malware ne parvenait jamais à atteindre le domaine puisqu’aucune entrée DNS n’existe pour ce domaine particulier. Cela signifie que l’ordinateur n’est jamais en mesure d’obtenir l’adresse IP associée à totallylegitdomain-notevil.cn. Burp nous l’apprend en effet, si on observe avec davantage d’attention, on remarque que la requête n’obtient jamais de réponse dû à l’erreur “Unknown host”.

Handshake dont le domaine ne résoud sur aucune adresse IP

Pour régler ce problème, j’ai édité le fichier hosts de mon ordinateur afin d’enregistrer moi-même une correspondance entre un domaine et une adresse IP. À cet effet, le domaine totallylegitdomain-notevil.cn était maintenant relié à l’adresse IP 127.0.0.1. Quel hasard, il s’agit justement de l’IP de mon ordinateur en réseau local!

C:\Windows\System32\drivers\etc\hosts
C:\Windows\System32\drivers\etc\hosts

La prochaine étape était donc de démarrer un serveur HTTPS sur le port 443 de mon ordinateur, puisqu’il s’agit du port sur lequel communique ce protocole par défaut.

À l’aide de Flask et de Python, j’ai pu facilement créer le petit script suivant qui démarre un serveur qui accepte HTTPS (option ssl_context) sur le port 443 avec un listener sur la route appropriée associée à une fonction qui retourne le ‘None’ demandé dans l’énoncé du défi.

from flask import Flask
app = Flask(__name__)

@app.route('/handshaketest')
def hello_world():
return 'None'

if __name__ == '__main__':
app.run(port=443, ssl_context='adhoc')

Ayant démarré le serveur avec python3 ./serv.py, j'ai relancé le malware et les requêtes suivantes sont apparues dans Burp!

Cinquième Flag

On remarque le dernier flag donné à la septième requête!

Conclusion

Bien que relativement guidée, cette suite de défis n’en a pas été moins intéressante et m’a permis d’en apprendre pas mal sur les bases de l’analyse dynamique de logiciel malveillant. J’ai pu appliquer des compétences connexes pour me rendre au bout et je remercie l’auteur d’avoir permis aux participants de United CTF de se mesurer à la track Desjardins!