Emotet v5 Reversing (unpacking, basic analysis and Indiana Jones) [part. I]

Emotet est un cheval de Troie bancaire qui a été identifié pour la première fois en 2014 par des chercheurs en sécurité. Il était conçu à l’origine comme un malware bancaire qui tentait de pénétrer de manière sournoise dans votre ordinateur pour voler des informations sensibles et privées. Les versions suivantes du logiciel ont vu l’ajout de services de diffusion de spam et de malware, y compris d’autres chevaux de Troie bancaires.

Emotet a ciblé des individus, des entreprises et des entités gouvernementales d’un bout à l’autre des États-Unis et de l’Europe, en volant des identifiants bancaires, des données financières et même des portefeuilles Bitcoin.

Une attaque notable d’Emotet sur la ville d’Allentown, en Pennsylvanie, a nécessité une aide directe de l’équipe de réponse aux incidents de Microsoft. Le nettoyage et la maintenance auraient coûté plus de 1 million de dollars.

Maintenant qu’Emotet sert à télécharger et à diffuser d’autres chevaux de Troie bancaires, la liste des cibles est potentiellement encore plus importante. Les premières versions d’Emotet étaient utilisées pour attaquer les clients bancaires en Allemagne. Les versions suivantes ciblaient des organisations au Canada, au Royaume-Uni et aux États-Unis (source: Malwarebytes).

Ainsi, par un hasard un peu forcé par une soudaine envie d’explorer un « maldoc », je me suis rendu sur le site Hybrid Analysis dans l’espoir de trouver un Sample de quelque chose … à analyser.

Concernant ce Sample, je commence l’analyse en sachant que je dispose déjà d’informations intéressantes fournies dans le rapport d’incident lié à celui-ci.

Hybrid Analysis utilise Falcon Sandbox, une alternative commerciale à Cuckoo Sandbox. Ci-dessous, une présentation de quelques indicateurs de la section « Malicious Indicators ».

Dans la section « Informative » comme son nom l’indique …

Dans la section « Screenshots », nous pouvons observer en image, l’exécution du « maldoc ».

A propos de Cuckoo Sandbox, c’est un outil qui permet l’analyse automatisée de malwares et ainsi la compréhension rapide de ce que peut faire un fichier suspect (binaire, document, email, …) sur différentes plateformes (Windows, Linux, Android).

<PUB>
Vous pouvez lire le magazine e-Forensics du mois de mars 2019 dédié à Cuckoo Sandbox
</PUB>

Il est toujours intéressant de pouvoir disposer d’un tel outil/environnement d’analyses comportementales dans une entreprise (« Je dis ça, mais j’dis rien … »).

Mais, si nous devons faire tout ce travail à la main, il faut commencer par rechercher la charge utile dans le document Word.

Pour faire ceci, nous pouvons utiliser l’outil « oledump.py » de Didier Stevens pour regarder dans les sections de ce document.

A la recherche de codes VBA, d’une commande PowerShell, WMI, … ou toutes autres choses paraissant suspectes.

Ici, avec l’habitude, nous reconnaissons l’encodage base64 et les chaînes de caractères « PowE » et « rShell ». Nous supposons l’exécution d’une commande Powerhell.

Puis on regarde le payload (ce qu’il y a d’encoder).

Nous découvrons la liste des liens qui cachent le malware Emotet :

  • http://duanlocphatresidence.com/wp-admin/b8oyf2_w724r5u-66253/
  • http://superwhite.com.au/wp-content/2t9x_bmoau88p-89600496/
  • http://pneumorek.ma/calendar/EckAzvvl/
  • http://pure-vapedistribution.be/p52r/js74mi_zk0p5orhwa-651/
  • http://nitincarcare.com/wp-content/BbayinbUK/

Nous téléchargeons les 5 échantillons (les binaires ne sont peut-être pas identiques). Puis on vérifie le condensat SHA256 pour chaque échantillon.

Nous remarquons que c’est le même hash, mais aussi que la plupart des sites hébergeant cette variante d’Emotet utilisent le CMS WordPress.

Sans doute ont-ils une vulnérabilité commune ?

J’ai pu observer quelques CVEs sur Shodan à propos des serveurs ci-dessus et des références à WooComerce avec Wappalyzer.

Aussi, je suppose que ce sont des serveurs légitimes qui se sont fait « poutrer » via un upload de fichiers arbitraires, de l’exécution de codes ou autres …

Binary reversing / Unpacking

Si nous regardons de plus près le binaire récupéré, nous observons qu’il contient seulement 2 sections.

  • La section « .text » pour ce qui est du code exécutable,
  • La section « .joi » qui laisserait supposer que quelque chose se cache ici.

Avec IDA (Interactive DisAssembler) le constat n’est pas glorieux.

Il faudra sans doute user de l’analyse dynamique pour faire sortir Emotet de son tombeau.

Ainsi avec l’aide de x32dbg, nous pouvons observer l’initialisation du binaire. Par la suite, à l’adresse 0x0040257B, la fonction « VirtualAllocEx » est appelée pour allouer de la place dans la mémoire.

C’est dans cet espace tampon que sera stocké le code qui servira à unpacker Emotet.

Dans l’exemple ci-dessous, le registre EAX contient le point d’entrée de la plage mémoire allouée à l’adresse 0x001B0000 (dans mon cas).

L’exécution continue donc à l’adresse « 0x001B0000 ». C’est ici que le processus d’unpacking commence.

Plus loin, le chargement des sections .data, .rdata et .reloc.

Puis il quitte l’espace mémoire avec l’instruction « JMP ESI » qui n’est autre qu’un saut vers l’OEP (Original Entry Point).

A ce stade, il est possible de reconstruire le PE non packé (avec le plugin Scylla) pour mieux l’étudier.

File > Dump Memory > Dump PE

Une fois le « dump » effectué, on peut quitter le debugger et vérifier le nouveau binaire avec (PEiD || Detect It Easy) && PeStudio.

Avec IDA, nous obtenons une représentation plus cohérente de cette souche d’Emotet.

Du coté des antivirus, les taux de détection sont encore bien bas …

Loading Emotet / Première partie

Une fois « unpacké », ce n’est pas gagné pour autant. En effet, le code est « obfuscé » (les chaînes de caractères sont cryptées, les noms des APIs sont stockés sous forme de valeurs de hachage dans le binaire).

Par exemple, le code ci-dessous est utilisé pour obtenir certaines fonctions de « ntdll.dll ».

En observant avec x32dbg, nous constatons qu’Emotet énumère via le PEB (Process Environment Block), en comparant les hashs sdbm respectifs de ntdll.dll et de kernel32.dll, pour obtenir un « handle » vers ces librairies.

Plus tard, nous observerons que les autres DLL sont chargées tout simplement en utilisant la fonction « LoadLibraryW » (en déchiffrant préalablement le nom de la DLL).

#!/usr/bin/env python2.7

string = "ntdll.dll"

hash = int(0)
for i in range(0, len(string)) :
  hash = (ord(string[i]) + hash) & 0xffffffff
  if i != (len(string) - 1) : hash = (hash * 65599) & 0xffffffff

print hex(hash)

Pour résoudre les API, c’est la même fonction de hashage qui est utilisée, avec un XOR en plus. Notons que la clé XOR est propre à chaque librairie.

#!/usr/bin/python

def sdbm_hash(string, key = 0) :
  hash = int(0)
  for i in range(0, len(string)) :
    hash = (ord(string[i]) + hash) & 0xffffffff
    if i != (len(string) - 1) : hash = (hash * 65599) & 0xffffffff
  return(hex((hash ^ key) & 0xffffffff)[2:])

def hash_comp(path_to_file, hash, key) :
  with open(path_to_file) as fp :
    line = fp.readline()
    while line :
      if sdbm_hash(line.strip(), key).upper() == hash :
        print("[%s] -> %s" % (hash, line.strip()))
      line = fp.readline()

def resolve_api(path_to_hash, path_to_modules, key) :
  with open(path_to_hash) as fp :
    line = fp.readline()
    while line :
      hash_comp(path_to_modules, line.strip().replace('h', '').upper(), key)
      line = fp.readline()

print("-= ntdll.dll =-")
resolve_api("modules.hash/ntdll.txt", "modules.list/ntdll.txt", 0x571BDDC1)

print("-= kernel32.dll =-")
resolve_api("modules.hash/kernel32.txt", "modules.list/kernel32.txt", 0x2068f5EB)

Ainsi, lors de son exécution, Emotet charge les fonctions dont il a besoin de cette façon.

Nous remarquons au passage que certaines valeurs de hash sont fausses. Peut-être pour tromper l’analyste ?

Ensuite, il fait un GetModuleFileNameW pour obtenir le chemin complet de son emplacement sur le disque, puis il utilise sa fonction de hashage sur le « path » obtenu.

Nous remarquons le call à l’adresse 0x001ACA10 (attention tenir compte de ASLR) qui appelle une fonction qui sert à déchiffrer des données. Dans le cas ci-dessous, elle déchiffre la chaine « –%x » qui sera utilisée en tant qu’argument pour le formatage dans la fonction _snwprintf.

Donc, vient l’appel à la fonction _snwprintf qui permet d’écrire des données formatées dans une chaîne de caractères.

Par la suite, il fait un appel à GetCommandLineW pour obtenir la ligne de commande et ses arguments afin d’établir si le binaire est exécuté avec le commutateur « –1e458dc6 » (dans notre cas).

Car vous l’aurez compris, le commutateur correspond au hash du résultat obtenu par la fonction GetModuleFileNameW (chemin du binaire sur le disque).

Si l’argument n’existe pas, Emotet restart sur un appel à CreateProcessW et ajoute le commutateur désiré à la commande, puis ExitProcess.

De retour vers l’analyse statique, nous avons précédemment trouvé une fonction cryptographique (en fait, un simple XOR) qui est utilisée pour chiffrer des données (chaînes de caractères, valeurs de hash, …). Simple mais efficace pour faire de l’obfuscation.

La clé XOR est différente pour chaque chaîne de caractères (l’objectif remplit bien son rôle … ralentir le RE).

Comme expliqué plus haut, lors du chargement de ntdll.dll et kernel32.dll, Emotet énumère le PEB.

Pour les autres librairies, c’est un appel à LoadLibraryW qui fait le travail. Le nom de la librairie est déchiffré préalablement.

Nous savons comment « reverser » la fonction de crypto, nous pouvons nous servir de ces informations pour décrypter les chaînes de caractères dans le programme.

L’objectif est de trouver le(s) adresse(s) IP de communication vers le (C2C || Relay).

Notre attention est retenue par la chaîne de caractères « %u.%u.%u.%u » qui est compatible avec le format d’une adresse IP.

Nous localisons la fonction qui fait un traitement sur cette valeur.

Mettons cette information de côté et poursuivons …

Loading Emotet / Seconde partie

Nous relançons le binaire en prenant soin d’ajouter le bon commutateur « –5c0f3203 » à la ligne de commande.

A l’adresse 0x012FCA79 (ASLR), le commutateur « –5c0f3203 » dans la ligne de commande est trouvé. C’est la fonction lstrcmpiW qui se charge d’effectuer cette comparaison.

Grosso merdo, lors de cette seconde exécution, Emotet met en place sa persistance en se recopiant dans son « home directory ». S’il est exécuté avec des privilèges d’administration, le malware s’installe dans le répertoire « %windir%\SysWOW64 ». Sinon il se positionne dans « %localappdata% ».

En se recopiant, il génère un nouveau nom d’exécutable. Je n’ai pas analysé ce passage en détail mais en gros, il semblerait qu’il utilise deux listes de noms qu’il « concatène » en utilisant comme vecteur, une valeur de taille fixe (par exemple, le hostname mais ce n’est qu’une supposition) pour choisir le nom de l’exécutable dans son répertoire de destination (son « home directory »).

Juste avant d’effectuer ce travail, il charge les librairies advapi32.dll et shell32.dll pour pouvoir faire appel à des fonctions supplémentaires.

Dans mon cas, le malware se nomme « sonicredist.exe » et son emplacement potentiel sur le disque est :

  • %localappdata%\sonicredist\sonicredist.exe (en tant qu’utilisateur)
  • %windir%\SysWOW64\sonicredist.exe (en tant qu’administrateur)

Emotet vérifie s’il est déjà installé dans son « home directory ». Si ce n’est pas le cas, il déclenche ses procédures de persistance et « restart » au bon emplacement.

Le nom du service est choisi de la même façon mais avec quelques différences, en utilisant une seule et unique liste de noms (différente de celle utilisée précédemment), et donc ici, pas de concaténation avec une autre liste.

Loading Emotet / Troisième partie

S’il est localisé dans son « home directory » avec le nom d’exécutable attendu (dans mon cas « %windir%\SysWOW64\sonicredist.exe ») et s’il est exécuté à cet emplacement en utilisant le commutateur « –15fc565b », Emotet exécute ses routines cryptographiques, de communications et autres …

Il utilise les fonctions cryptographiques de Microsoft, à ce stade, les librairies ntdll.dll, kernel32.dll, advapi32.dll, shell32.dll, crypt32.dll, urlmon.dll, userenv.dll, wininet.dll et wtsapi32.dll sont chargées.

Mais notre objectif, dans le cadre de cet article, est de localiser l(es) adresse(s) IP qu’utilise Emotet pour communiquer.

Nous positionnons un « break point » à l’adresse 0x00AE68B0 (ASLR), dans cette fonction, nous avons précédemment trouvé un appel à _snwprintf et la chaîne de formatage « %u.%u.%u.%u » qui fait fortement penser au format IPv4.

Donc, on positionne un autre « break point » plus bas à l’adresse 0x00AE6962 (ASLR) pour découvrir la première adresse IP.

Puis une seconde adresse IP.

Et ainsi de suite …

Du coté de l’analyse statique avec IDA, nous obtenons la liste des adresses IP comme définie dans la représentation ci-dessous :

Cependant, il est difficile de savoir pour le moment si ces adresses IP correspondent à :

  • des centres de contrôle exposés directement sur Internet (peu probable),
  • des serveurs relais pour justement ne pas exposer le/les centre(s) de contrôle (fortement probable),
  • un mixte des deux (possible …)

 

Conclusions

Bien que notre analyse nous permette de connaître le schéma d’exécution de cette version d’Emotet, il reste beaucoup à apprendre. En effet, certaines fonctions peuvent être revues plus en détail :

  • Le processus d’unpacking peut être étudié dans l’éventualité de coder un outil pour récupérer les informations « packées » et regarder dans les sections sans avoir besoin de « debugger ».
  • La génération du nom de l’exécutable et du service Windows. Quel est le vecteur de taille fixe ?
  •  A quoi servent exactement les fonctions cryptographiques de Windows ?
  • Comment fonctionne le protocole de communication ?
  • Quelles sont les premières requêtes qui sont envoyées au centre de contrôle ? Y a t’il des vulnérabilités ?
  • Et sûrement d’autres trucs …

L’analyse manuelle est en mon sens, bien plus précise qu’une analyse automatisée avec une Sandbox. L’interaction entre le malware et l’analyste est beaucoup plus … intime.

Cependant, vous pouvez vous appuyer sur un outil comme CAPE (Malware Configuration And Payload Extraction) qui offre également la possibilité de soumettre sur leur plateforme en ligne.

Le lien du rapport CAPE de notre version d’Emotet se trouve ICI

 

 

 

 

 

Ce contenu a été publié dans Reverse Engineering. Vous pouvez le mettre en favoris avec ce permalien.