Début mars 2019, un nouvel échantillon de logiciels malveillants macOS du groupe OceanLotus a été téléchargé sur VirusTotal, un service multiscanner en ligne populaire. Cet exécutable de porte dérobée présente les mêmes caractéristiques que la précédente variante de macOS que nous avons examinée, mais sa structure a changé et sa détection a été rendue plus difficile. Malheureusement, nous n'avons pas pu trouver le dropper associé à cet échantillon et nous ne connaissons donc pas le vecteur de compromis initial.

Nous avons récemment publié une mise à jour détaillée sur OceanLotus et sur la façon dont ses opérateurs utilisent un large éventail de techniques pour obtenir l'exécution du code, obtenir la persistance et laisser le moins de traces possible sur un système Windows. OceanLotus est également connu pour avoir un composant macOS malveillant. Cet article détaille ce qui a changé par rapport à la version précédente visant macOS, analysée par Trend Micro et décrit comment, tout en analysant le code de cette variante, vous pouvez automatiser le déchiffrement des chaînes de caractères en utilisant l'API IDA Hex-Ray.

Analyse

Les trois sections suivantes de ce billet décrivent l'analyse de l'échantillon avec le hachage SHA-1 : E615632C9998E4D3E5ACD8851864ED09B02C77D2. Le fichier, appelé flashlightd, est détecté par les produits ESET comme OSX/OceanLotus.D.

Anti-débogage et anti-sandbox

Comme d'habitude pour les binaires macOS d'OceanLotus, l'échantillon est rempli d'UPX, mais la plupart des outils d'identification d'empaqueteur ne le reconnaissent pas comme tel, probablement parce qu'ils incluent principalement une signature qui repose sur la présence d'une chaîne UPX. De plus, les signatures Mach-O sont moins courantes et moins régulièrement actualisées. Cette caractéristique particulière rend la détection statique plus difficile. Une fois dépaqueté, il est intéressant de noter que le point d'entrée se trouve au début de la section __cfstring du segment .TEXT. Cette section a les attributs de drapeau vus dans la figure 1.

Figure 1 - Attributs de la section __cfstring de MACH-O.

Comme le montre la Figure 2, le fait que le code se trouve dans la section __cfstring permet d'utiliser certains outils de désassemblage pour afficher le code sous forme de chaînes.

Figure 2 - Le code de la backdoor est défini comme des données par IDA

Lorsqu'il est lancé, le binaire crée d'abord un thread en tant que gardien anti-débogage, dont le seul but est de vérifier en permanence si un débogueur est présent. Pour ce faire, ce fil :

  • Essaye de détacher n'importe quel débogueur en appelant ptrace avec PT_DENY_ATTACH comme paramètre de requête;
  • Vérifie si certains ports d'exception sont ouverts en appelant la fonction task_get_exception_ports;
  • Vérifie si un débogueur est attaché, comme le montre la Figure 3, en vérifiant si l'indicateur P_TRACED est activé dans le processus en cours.

Figure 3 - Vérifier si un débogueur est connecté via la fonction sysctl.

Si le gardien détecte la présence d'un débogueur, la fonctio nexit est appelée. De plus, l'échantillon vérifie ensuite son environnement en émettant les deux commandes suivantes :
ioreg -l | grep -e “Manufacturer” et sysctl hw.model
et vérifie la valeur de retour par rapport à une liste codée en dur des chaînes connues du système de virtualisation : oracle, vmware, virtualbox ou parallèles. Enfin, le commandement :
system_profiler SPHardwareDataType 2>/dev/null | awk ‘/Boot ROM Version/ {split($0, line, “:”);printf(“%s”, line[2]);}
vérifie si la machine est l'une de celles-ci : MBP, MBA, MB, MM, IM, MP et XS. Ces codes représentent le modèle du système. Par exemple, « MBP » signifie MacBook Pro, « MBA » signifie MacBook Air et ainsi de suite...

Mises à jour majeures

Même si les commandes de la porte dérobée n'ont pas changé depuis l'article de Trend Micro, nous avons remarqué quelques autres modifications. Les serveurs C&C utilisés pour cet échantillon sont assez récents puisque leur date de création est le 2018-10-22.

  • daff.faybilodeau[.]com
  • sarc.onteagleroad[.]com
  • au.charlineopkesston[.]com

La ressource URL utilisée a changé en /dp/B074WC4NHW/ref=gbps_img_m-9_62c3_750e6b35.

Le premier paquet envoyé au serveur C&C contient plus d'informations sur la machine hôte. Toutes les données recueillies par les commandes du tableau suivant sont incluses.

Commands Description
    system_profiler SPHardwareDataType 2>/dev/null

  • awk '/Processor / {split($0,line,":"); printf("%s",line[2]);}'
  • machdep.cpu.brand_string

Gather processor information
    system_profiler SPHardwareDataType 2>/dev/null

  • awk '/Memory/ {split($0,line, ":"); printf("%s", line[2]);}'
Gather memory information
ifconfig -l Gather network interface MAC addresses
    ioreg -rd1 -c IOPlatformExpertDevice

  • awk '/IOPlatformSerialNumber/ { split($0, line, "\""); printf("%s", line[4]); }'
Retrieves the serial number of the device

En plus de ce changement de configuration, cet exemple n'utilise pas la librairie libcurl pour l'exfiltration du réseau. Au lieu de cela, il utilise une bibliothèque externe. Pour le localiser, la porte dérobée tente de déchiffrer chaque fichier du répertoire courant à l'aide de AES-256-CBC en utilisant la clé gFjMXBgyXWULmVVVzyxy entourée de zéros. Chaque fichier est déchiffré et enregistré sous /tmp/store et une tentative de le charger sous forme de bibliothèque est faite en utilisant la fonction dlopen. Lorsqu'une tentative de déchiffrage aboutit à un appel réussi à dlopen, la porte dérobée récupère alors les fonctions exportées Boriry et ChadylonV, qui semblent être responsables de la communication réseau avec le serveur. Comme nous n'avons pas le compte-gouttes ou d'autres fichiers de l'emplacement de l'échantillon original, nous n'avons pas pu analyser cette bibliothèque. De plus, comme le composant est chiffré, une règle YARA basée sur ces chaînes ne correspondrait pas au fichier trouvé sur le disque.

Tel qu’expliqué dans l'analyse de l'ancienne porte dérobée macOS du groupe, un clientID est créé. Cet identificateur est le hachage MD5 de la valeur de retour de l'une des commandes suivantes :

  • ioreg -rd1 -c IOPlatformExpertDevice | awk '/IOPlatformSerialNumber/ { split($0, line, "\""); printf("%s", line[4]); }'
  • ioreg -rd1 -c IOPlatformExpertDevice | awk '/IOPlatformUUID/ { split($0, line, "\""); printf("%s", line[4]); }'
  • ifconfig en0 | awk \'/ether /{print $2}\' (pour obtenir l'adresse MAC)
  • Une commande inconnue ("\x1e\x72\x0a"), correspondant à « uuidgen » dans les échantillons précédents.

Avant le hachage, le caractère « 0 » ou « 1 » est ajouté à la valeur de retour indiquant les privilèges root. Ce clientID est stocké dans Library/Storage/File System/HFS/25cf5d02-e50b-4288-870a-528d56c3cf6e/pivtoken.appex / si le code est exécuté en tant que root, ou dans ~/Library/SmartCardsServices/Technology/PlugIns/drivers/snippets.ecgML dans le cas contraire. Ce fichier est normalement masqué par la fonction _chflags  et son horodatage est modifié par la commande touch –t avec une valeur aléatoire.

Déchiffrement des chaînes de caractères

Comme les variantes précédentes, les chaînes de caractères sont chiffrées à l'aide d'AES-256-CBC (clé hexadécodée : 9D7274AD7BCEF0DED29BDBB428C251DF8B350B92, encadrée de zéros avec remplissage du IV avec des zéros) en utilisant la fonction CCCrypt. La clé a changé par rapport aux versions précédentes mais comme le groupe utilise toujours le même algorithme pour chiffrer les chaînes de caractères, le déchiffrement pourrait être automatisé. Parallèlement à cet article, nous publions un script IDA utilisant l'API Hex-Rays pour déchiffrer les chaînes présentes dans le binaire. Ce texte pourrait faciliter l'analyse future d'OceanLotus et l'analyse d'échantillons existants que nous n'avons pas encore été en mesure d'obtenir. Au cœur de ce script se trouve une méthode générique pour obtenir les arguments passés à une fonction. De plus, il recherche les affectations des paramètres afin de trouver leurs valeurs. Cette méthode pourrait être réutilisée pour récupérer la liste des arguments d'une fonction et les passer ensuite à un rappel.

Connaissant le prototype de la fonction decrypt, le script trouve d'abord tous les renvois à cette fonction, trouve tous les arguments, déchiffre les données et place le texte en clair dans un commentaire à l'adresse du renvoi. Pour que le script fonctionne correctement, l'alphabet personnalisé utilisé par la fonction de décodage base64 doit être défini dans le script et la variable globale contenant la longueur de la clé doit être définie (comme DWORD dans ce cas; voir Figure 4).

Figure 4 - Définition de la variable globale key_len

Dans la fenêtre Function, vous pouvez cliquer avec le bouton droit de la souris sur la fonction de déchiffrage et cliquer sur « Extraire et déchiffrer les arguments ». Le script devrait mettre les chaînes déchiffrées dans les commentaires, comme le montre la Figure 5.

Figure 5 - Le texte déchiffré affiché en commentaire

Cela permet de lister commodément les chaînes déchiffrées dans les xrefs d'IDA à la fenêtre pour cette fonction, comme le montre la Figure 6.

Figure 6 – Xrefsde la fonction f_decrypt.

Le script final peut être trouvé sur notre dépôt Github.

Conclusion

Comme nous l'avons récemment documenté dans un article précédent, le groupe OceanLotus continue d'améliorer et de mettre à jour son ensemble d'outils, et une fois de plus, il a amélioré ses outils pour cibler les utilisateurs Mac. Le code n'a pas beaucoup changé, mais comme de nombreux utilisateurs de Mac n'utilisent pas de logiciel de sécurité sur leurs appareils, la nécessité d'échapper à la détection est moins importante. Les produits ESET ont déjà détecté ce fichier lorsque nous l'avons trouvé. Comme la bibliothèque réseau utilisée pour la communication C&C est maintenant chiffrée sur le disque, le protocole réseau exact utilisé reste inconnu.

Indicateurs de compromission (IoCs)

Les IoCs de ce blogue, ainsi que les attributs MITRE ATT&CK, sont également disponibles dans notre répertoire GitHub.

Noms de domaine

  • daff.faybilodeau[.]com
  • sarc.onteagleroad[.]com
  • au.charlineopkesston[.]com

Ressources URL

  • /dp/B074WC4NHW/ref=gbps_img_m-9_62c3_750e6b35

Chemins d'accès

  • ~/Library/SmartCardsServices/Technology/PlugIns/drivers/snippets.ecgML
  • /Library/Storage/File System/HFS/25cf5d02-e50b-4288-870a-528d56c3cf6e/pivtoken.appex
  • /tmp/store

Sample analyzed SHA-1 hash ESET detection name
fleshlightd E615632C9998E4D3E5ACD8851864ED09B02C77D2 OSX/OceanLotus.D

Techniques MITRE ATT&CK

Tactic ID Name Description
Defense Evasion T1158 Hidden Files and Directories The backdoor hides the clientID file via chflags function.
T1107 File Deletion The backdoor can receive a “delete” command.
T1222 File Permissions Modification The backdoor changes the permission of the file it wants to execute to 755.
T1027 Obfuscated Files or Information The library used for network exfiltration is encrypted with AES-256 in CBC mode.
T1099 (macOS) Timestomp The timestamp of the file storing the clientID is modified with a random value.
Discovery T1082 System Information Discovery The backdoor performs a fingerprint of the machine on its first connection to the C&C server.
Exfiltration T1022 Data Encrypted The backdoor encrypts the data before exfiltration.
Command and Control T1094 Custom Command and Control Protocol The backdoor implements a specific format for the packet involving random values. See Trend Micro article.