Malware Analysis - IcedID
This blog post is available in english here.
Sommaire
- Introduction
- Reconnaissance
- Overview
- Analyse
- 1) Stage 1
- 2) Stage 2
- A) Unpack
- B) Élévation de privilèges
- C) Injection sous Svchost.exe
- 3) Stage 3
- A) Reconstruction de l’IAT et dump du processus
- B) Gestion des erreurs et des exceptions
- C) Extraction des URL du serveur de contrôle
- 1) OSINT divorought.com
- 2) OSINT percalabia.com
- D) Récolte d’informations systèmes
- E) Méthodes de persistance
- F) Proxy local
- G) Anti-VM et anti-debug
- H) Exfiltration
- Indicateurs d’infection
Introduction
L’exécutable analysé dans cet article est le suivant:
d4abe68c54567b9db2bc35a03ae91bc9
Celui-ci est téléchargeable sur la plateforme Malshare ou sur VirusBay
A la différence du précédent article sur le malware Dexter, ce sample est beaucoup plus récent (première apparition le 17 Avril 2018) et est bien plus agressif. Une grande prudence est recommandée lors du téléchargement et de la manipulation du fichier. Attention à bien exécuter le binaire dans un environnement contrôlé qui ne dispose d’aucune passerelle vers d’autres machines. Le malware IcedID est capable de se propager au sein d’un réseau local via de simples dossiers partagés.
Reconnaissance
VirusTotal label le fichier comme étant malicieux, et plusieurs anti-virus sont capable d’identifier la famille “IcedID” : A noter qu’un des anti-virus reconnaît bien le fait que ce malware possède une capacité d’injection dans d’autres processus: • Le binaire actuel n’est pas packé, mais celui-ci possède une section avec une très haute entropie, ce qui laisse soupçonner qu’une ressource chiffrée/packée sera extraite par la suite.
• Les chaînes de caractères présentes dans le fichier sont très banales et presque inexploitables.
• Afin d’aiguiller mon analyse, je décide de lancer le malware tout en observant les événements systèmes avec procmon, et les interactions entres processus avec procexp, afin d’identifier un premier comportement suspect. Il se trouve que dès les premières secondes, le malware lance une copie de lui-même, avant de créer un processus svchost suspect: Cette injection me sert de point de départ pour cette analyse.
Overview
Analyse
Stage 1
Le malware commence par s’injecter dans un nouveau processus au nom homonyme. Pour dumper ce processus, il suffit de surveiller les appels systèmes généralement liés à une injection en mémoire, à savoir WriteProcessMemory, VirtualAlloc, CreateProcess et CreateProcessInternal : Sans surprise, un nouveau processus est donc initié avec le même nom que le sample analysé: La fonction WriteProcessMemory est ensuite utilisée pour écrire ce nouveau processus, ce qui permet d’en intercepter directement le contenu pour y observer un fichier PE: Il ne reste qu’à dumper ce processus en traçant l’adresse mémoire où réside le contenu du futur processus (“follow in memory map”) puis d’extraire le tout (“dump memory to file”). Avant de continuer, il est nécessaire de patcher le header du nouveau binaire obtenu de façon à faire correspondre les adresses et tailles physiques et virtuels des différentes sections pour garder le fichier au format unmaped (fichier utilisable sur le disque, à l’inverse d’un fichier maped, utilisable uniquement en mémoire):
Stage 2
A) Unpack
Comme le nom des sections obtenu plus haut le démontre, le dump du stage 2 du malware semble packé avec UPX. Malheureusement, il sera nécessaire de l’unpacker à la main: Pour rappel, le but est ici de trouver un jmp vers une adresse mémoire lointaine pour obtenir l’EOP du stage 2 en clair. En cas de doutes, je renvoie vers mon article sur l’unpack manuel d’un sample UPX. Le saut en question est identifiable graphiquement: Une fois l’adresse sur laquelle pointe ce saut extrait, il ne reste qu’à en dumper le contenu. J’utilise ici le plugin pour x64dbg : Scylla. Celui-ci me permet de récupérer le nouveau fichier en précisant l’EOP, et surtout de résoudre les imports du dump en reconstruisant automatiquement l’IAT:
B) Élévation de privilèges
Pour commencer, le malware va récupérer la version windows avec la fonction RtlGetVersion, puis celui-ci va s’informer des privilèges avec lesquels il a été lancé. Si les privilèges ne sont pas suffisants, le malware se relance avec des privilèges administrateurs via la commande “runas” : En résulte ainsi une UAC demandant des privilèges administrateurs:
C) Injection sous Svchost.exe
Afin de s’injecter dans le processus svchost.exe, IcedID va placer un hook sur la fonction RtlExitUserProcess. Dans un premier temps, un buffer contenant la suite du code malicieux est extrait en mémoire.
La fonction RtlExitUserProcess est hookée, afin de modifier le code de la fonction, et d’y ajouter une instruction jmp. Ce saut est à destination de l’espace mémoire contenant le contenu du buffer extrait à l’étape précédente: Par la suite, la fonction CreateProcess est appelée avec comme unique argument, svchost.exe. L’auteur du malware à ici ajoutée une pointe d’obfuscation en construisant la chaine de caractère “svchost” de manière dynamique, et en poussant les lettres unes par unes sur la stack: Lorsqu’un processus svchost est créé sans arguments supplémentaires, celui-ci se ferme automatiquement. C’est ici le cas, et la fonction NtTerminateProcess est appelée par l’OS. NtTerminateProcess appel lui même RtlExitUserProcess, ce qui déclenche l’exécution du code malicieux, puisque la fonction a été altérée juste auparavant.
Par cette méthode, le processus svchost est maintenu en vie, et celui-ci fait désormais tourner le code malveillant injecté par le malware: Pour intercepter le code injecté dans le processus svchost.exe, il faut donc attacher le nouveau processus à un debugger lorsque celui-ci est créé, puis surveiller les appels de l’API RtlExitUserProcess afin de récupérer l’adresse du jmp injecté à la suite du hook. A cette adresse mémoire se situe le coeur du malware IcedID.
Stage 3
A) Reconstruction de l’IAT et dump du processus
Afin de pouvoir effectuer une analyse statique du code injecté dans le processus svchost.exe, il est nécessaire d’en récupérer une copie. Mais un problème se pose : les appels systèmes ne sont pas résolus naturellement dans la section injectée: Les calls sont faits sur des pointeurs amenant à une section mémoire vide: L’IAT va donc être construite dynamiquement dans cette section mémoire. En exécutant la première fonction à disposition, les appels systèmes sont en partie résolues: Enfin, puisque certains calls sont résolus en pointant sur d’autres sections mémoires éloignées, il va être nécessaire de dumper le code injecté ainsi que la section distance contenant quelques fonctions supplémentaires.
Pour analyser statiquement le code injecté, il faudra donc ouvrir les deux dump sous IDA pour résoudre quelques calls systèmes. Enfin, pour terminer, des outils comme APIscout peuvent être utiles pour résoudre d’autres appels systèmes et compléter le dump du code injecté, et faciliter le travail d’analyse du malware.
B) Gestion des erreurs et des exceptions
Afin de rester incognito sur le système infecté, IcedID commence par cacher les erreurs systèmes pouvant être affichées à l’utilisateur. Lorsque la fonction SetErrorMode est appelée avec l’argument 0x8007h, tous les messages d’erreurs applicatifs restent cachés: En cas de crash ou de problèmes causé par le malware, l’utilisateur ne sera pas averti. Plus précisément, les modes suivants sont activés:
C) Extraction des URL du serveur de contrôle
Les URL des serveurs de contrôle sont ensuite dynamiquement extraites de la configuration du malware par une fonction de désobfuscation: Ce sample est capable d’extraire deux URL de sa configuration:
1) OSINT divorought.com
À l’heure actuelle, l’adresse n’est plus attribuée.
En revanche, l’URL ayant été active mi-avril 2018, possède un passif malicieux: Celle-ci est bien liée à la campagne de spread du malware IcedID, mais aussi Emotet et Hancitor-malspam.
L’enregistrement du nom de domaine à été fait avec les informations suivantes: Cette adresse mail a servi pour enregistrer de très nombreux nom de domaines, souvent liés à des activités malicieuses en lien avec IcedID ou Emotet.
2) OSINT percalabia.com
Sans grande surprise, ce nom de domaine à lui aussi été enregistré avec le même compte que l’entrée DNS précédente: Cette adresse est elle aussi liée à la campagne IcedID et Emotet.
Les deux URL extraites de la configuration sont bien liées entres elles, et servent de point de contrôle pour l’opérateur derrière IcedID.
D) Récolte d’informations systèmes
Comme tout trojan qui se respecte, IcedID chercher à récolter des informations sur la machine infectée, mais ici, de manière parcimonieuse. Dans un premier temps, le SID (Security Identifier) est récupéré, ainsi que le nom de la machine et de la session: La version Windows est ensuite récupérée à l’aide de la fonction RtlGetVersion: Des informations sur l’architecture de la machine et sur le token de sécurité sont elles aussi récoltées: Pour finir, l’adresse du contrôleur de domaine (s’il existe), et retrouvée avec la fonction NetGetDCName:
E) Méthodes de persistance
La technique employée par IcedID pour survivre au reboot de la machine est très sommaire, mais terriblement efficace. Un faux service de mise à jour est ajouté dans le planificateur de tâches, avec une exécution prévue à chaque ouverture de session sur le système. Ce service de mise à jour est une simple copie du stage 2 du malware. IcedID commence ici par générer un nom aléatoire qui servira à l’exécutable appelé par le planificateur de tâches: Dans mon cas, le fichier exécutable s’appelle “denrmircp.exe”.
Ensuite, le malware cherche un dossier déjà présent sous \AppData\Local\, afin d’y placer le nouveau fichier. Un dossier choisi au hasard va héberger cette copie du malware:
Le fait de générer un nom aléatoirement et de placer la copie dans un dossier déjà existant permet de semer la confusion si un utilisateur tombe sur le fichier malicieux.
La tâche planifiée est ensuite créée, via l’utilisateur système actuel, avec le nom “Update” et la description “Check Update”:
Pour vérifier si la méthode de persistance doit être exécutée (dans le cas ou le système serait déjà infecté par exemple, le malware n’utilisant pas de mutex), une comparaison est faite sur le nom du fichier depuis lequel le processus a été lancé et sur le nom de fichier généré pour être utilisé via le planificateur de tâche. De cette façon, le malware est capable de déterminer s’il est lancé suite au planificateur de tâche, ou s’il s’agit de l’étape initiale de l’infection:
F) Proxy local & MITM
Afin d’intercepter et d’altérer les données web de la machine infectée, IcedID met en place un proxy sur la boucle local. Afin de rester discret, le malware extrait un certificat PCA (Primary Certificate Authority) de sa configuration. Celui-ci permet de signer les pages HTTPS interceptées avec une infinité de certificats produit par la propre autorité de certification du malware.
Le certificat est construit dynamiquement, dans un fichier créé sous \AppData\Local\Temp\[A-Z0-9]{8}.tmp: Il s’agit d’un certificat Verisign datant de 2006: L’entièreté du certificat est ensuite généré, et celui-ci est ajouté à la liste des certificats Windows: Par la suite, le proxy local est mis en place: Le proxy est ainsi initié sur le protocole TCP, sur l’adresse local 127.0.0.1, et en utilisant le port 5000: Une liste de domaines à spoofer est extraite de la configuration puis obfusquée dans une clé de registre sous “\SOFTWARE\Classes\CLSID{B2C9B96F-A3E9-0806-9617-338F1ECD9918}”. Le malware est ainsi prêt à récolter des identifiants et mots de passe d’institutions bancaires.
G) Anti-VM et anti-debug
Étrangement, le malware ne cherche pas à détecter les environnements virtuels de manière agressive, mais juste afin de faire remonter l’information au serveur de contrôle. La détection d’une machine virtuelle n’entraîne pas le crash du malware ou une quelconque perte d’informations. Deux principales méthodes sont utilisées.
• L’instruction CPUID permet de retourner des informations sur le processeur: En appelant l’instruction CPUID avec la valeur 40000000 dans le registre EAX, des informations sur la technologie de virtualisation peuvent être extraites. La fonction est construite de la sorte: En fonction de la technologie de virtualisation trouvée (ou non), une valeur est attribuée à la machine. De 0x0 à 0x4, cela signifie que le malware n’est pas dans une machine virtuelle, de 0x4 à 0x7 qu’il est dans une VM VMware, et ainsi de suite…
• L’instruction RDTSC retourne un timestamp relatif au processeur. En appelant cette instruction deux fois, mais en laissant des instructions entre, il est possible de comparer le temps mis pour exécuter quelques instructions, et ainsi déterminer si le code est exécuté à la main, au travers d’un débugger: Les instructions RDTSC sont placés “stratégiquement” autour de l’instruction CPUID, afin d’empêcher la modification de la valeur retournée, mais ceci est inutile puisque l’information peut être dynamiquement modifiée plus tard.
H) Exfiltration
Un thread responsable des capacités d’exfiltration réseau du malware est créé: Afin de préparer la première communication avec le serveur de contrôle, les informations nécessaires pour identifier la machine sont extraites. Ces informations concernent le nom de la machine, le groupe de travail et l’utilisateur de la session active : Ces informations sont encodées au format URL: Une requête POST est ensuite créé avec les données récupérées (en plus de la version Windows). Une lettre est associée à chacunes des informations: Le tout en donc passé en paramètre de la requête POST suivante: Pour terminer, le malware envoi la requête à ses serveurs de contrôles.
Le serveur de contrôle est désormais capable de répondre et d’envoyer des instructions précises au malware. IcedID va ensuite télécharger des modules supplémentaires lorsque le C2 lui répondra avec des instructions spécifiques.
Le sample actuelle n’ayant plus de serveurs de contrôle online, il m’est impossible d’analyser les modules externes du malware IcedID.
Les instructions exécutables par le serveur de contrôle sont les suivantes :
Le malware entre ensuite en sommeil, à moins de recevoir de nouvelles instructions, ou s’il dispose d’informations à exfiltrer.
Indicateurs d’infection
Hash du binaire stage 1 (Injector) : d4abe68c54567b9db2bc35a03ae91bc9
Hash du binaire stage 2 (UPX unpacked) : 4ad54337918cd6e6c77eae69f68da239
Serveur de contrôle : 46.148.26.106 - divorought.com
Serveur de contrôle : 5.187.0.158 - percalabia.com
Requête Http : POST */*.php?a=[0-9]&b=[A-Z0-9]{17}&d=[0-9]&f=[0-9]&g=[0-9]
Fichier système : C:\Users\%USERNAME%\AppData\Local\%RANDOM_DIR%[a-z]{9}.exe
Certificat VériSign: C:\Users\%USERNAME%\AppData\Local\Temp\[A-Z0-9]{8}.tmp
Tâche planifiée : “Update”, “Ready”, “A l’ouverture de la session”, “Démarrer un programme”, “C:\Users\%USERNAME%\AppData\Local\%RANDOM_DIR%\[a-z]{9}.exe”