Analyse LockBit

Analyse statique du code

VĂ©rification de l’Anti-Debug

Au dĂ©but du programme, celui-ci vĂ©rifie que le flag NtGlobalFlag (0x70) est set. Si c’est le cas, le binaire rentre dans une boucle infinie.

Sinon le binaire continue son exécution.

Figure 1

Figure 1: VĂ©rification de l’Anti-Debug.

Chargement des DLL

Le binaire charge très peu de DLL et fonction au démarrage.

Figure 2

Figure 2: Liste des DLL chargés par le programme.

Si l’on continue dans le code, on peut voir des modifications de chaĂ®ne de caractère depuis la stack.

Figure 3

Figure 3: Ajout d’une string sur la stack.

On s’aperçoit ensuite que la chaĂ®ne est XORĂ© avec une clĂ© statique. Dans cette exemple, la clĂ© est 0x20. On peut facilement le vĂ©rifier avec Python.

Figure 4

Figure 4: XOR de la chaîne avec la clé 0x20.

Figure 5

Figure 5: Code du binaire permettant de XOR la chaîne.

Chaque nom de DLL est encodé avec une fonction différente.

La liste des DLL encodé est la suivante :

  • gdiplus.dll
  • ws2_32.dll
  • shell32.dll
  • advapi32.dll
  • user32.dll
  • ole32.dll
  • netapi32.dll
  • gpredit.dll
  • oleaut32.dll
  • shlwapi.dll
  • msvcrt.dll
  • activeds.dll
  • gdiplus.dll
  • mpr.dll
  • bcrypt.dll
  • crypt32.dll
  • iphlpapi.dll
  • wtsapi32.dll
  • win32u.dll
  • Comdlg32.dll
  • cryptbase.dll
  • ombase.dll
  • winspool.drv

RĂ©solution des DLL Dynamique

Une fois le nom des DLL résolu, le binaire doit résoudre dynamiquement les adresses des DLL afin de pouvoir utiliser les fonctions.

Pour cela, il résout dans un premier temps Kernel32.dll puis LoadLibraryA afin de résoudre chacune des fonctions.

Figure 6

Figure 6: RĂ©solution des fonctions dynamiquement.

Kernel32.dll

Pour la rĂ©solution de cette DLL, le binaire rĂ©alise un hash FNV du nom de la DLL en minuscule et la vĂ©rifie avec une chaĂ®ne harcodĂ©. Si cette valeur est juste alors l’adresse de base de la DLL est retournĂ©.

Figure 7 Figure 7: VĂ©rification du nom de la DLL et renvoie de l’adresse de base.

Figure 8

Figure 8: RĂ©sultat d’un hash FNV sur la chaĂ®ne Kernel32.dll.

LoadLibraryA

Pour la rĂ©solution de cette fonction, le binaire rĂ©alise les mĂŞmes opĂ©rations. Il boucle dans les fonctions prĂ©sents dans Kernel32.dll puis pour chaque fonction rĂ©alise son hash FNV et le compare Ă  une valeur hardcodĂ©. Si la valeur est la mĂŞme alors il retourne l’adresse de base de la fonction.

Figure 9 Figure 9: VĂ©rification du nom de la fonction et renvoie l’adresse de base.

Figure 10

Figure 10: RĂ©sultat d’un hash FNV sur la chaĂ®ne LoadLibraryA.

Pas touche Ă  ma langue

Le binaire va ensuite rĂ©cupĂ©rer la fonction GetSystemDefaultUILanguage afin de vĂ©rifier la langue par dĂ©faut sur l’ordinateur pour ne pas chiffrer les systèmes ayant une certaine langue par dĂ©faut.

Figure 11

Figure 11: RĂ©cupĂ©ration de l’adresse de base de la fonction GetSystemDefaultUILanguage.

Figure 12

Figure 12: RĂ©sultat d’un hash FNV sur la chaĂ®ne GetSystemDefaultUILanguage.

La valeur renvoyé par cette fonction est ensuite comparé avec des entiers qui correspondent à la langue du système.

Figure 13 Figure 13: Vérification de la langue du système.

En se basant sur la documentation officiel de microsoft, il est possible de récupérer la liste des langues comparés avec la variable.

  • Azeri (Cyrillic)
  • Azeri (Latin)
  • Armenian - Armenia
  • Belarusian
  • Georgian
  • Kazakh
  • Kyrgyz (Cyrillic)
  • Russian - Moldava
  • Russian
  • Tajik
  • Turkmen
  • Uzbek (Cyrillic)
  • Uzbek (Latin)
  • Ukrainian

Si la langue est dans la liste alors, le binaire rĂ©sout la fonction ExitProcess pour terminer l’exĂ©cution.

Figure 14

Figure 14: RĂ©solution de la fonction ExitProcess.

Figure 15

Figure 15: RĂ©sultat du hash FNV pour ExitProcess.

RĂ©duction des droits sur le process

Le binaire va rĂ©duire ses droits d’accès au process en modifiant sa propre liste d’accès.

Pour cela, il résout la fonction NtOpenProcess pour avoir un handle sur son process en cours et récupère les droits via GetSecurityInfo.

Suite Ă  cela, il appelle RtlAllocateAndInitializeSid pour crĂ©er une nouvelle structure SID afin d’appeler RtlAddAccessDeniedAce et mettre les droits du groupe EVERYONE Ă  ACCESS_DENIED.

Figure 16

Figure 16: Récupération des droits sur le process.

Enfin, le binaire va appeler RtlGetAce afin de passer sur chaque ACE et ajouter une ACL via RtlAddAce. Le binaire appelle ensuite SetSecurityInfo pour appliquer toutes les ACL et bloquer l’accès Ă  tout le monde sur le process.

Figure 17

Figure 17: Blocage du process pour tout le monde.

Error Stack Trace

Le binaire utilise la fonction NtSetInformationProcess afin de bloquer le moindre message d’erreur. Il utilise trois flags qui sont les suivants :

  • SEM_FAILCRITICALERRORS
  • SEM_NOGPFAULTERRORBOX
  • SEM_NOALIGNMENTFAULTEXCEPT

Figure 18

Figure 18: Blocage des messages d’erreurs.

DĂ©codage de la configuration

La fonction suivante permet de décoder la configuration dans le binaire.

Un simple XOR avec la clé 0x5F est réalisé, il est donc facile de récupérer les chaînes en réalisant un XOR sur tout le binaire.

Après avoir effectuĂ© le XOR, il est possible de rĂ©cupĂ©rer une image via binwalk. L’image affiche le logo de LockBit.

Figure 19

Figure 19: RĂ©cupĂ©ration de l’image dans la configuration du binaire.

Une seule image ressort, pourtant il existe 9 fichiers.

  • Fichier EMF: Contient le vecteur graphique du texte “ALL YOUR IMPORTANT FILES ARE STOLEN AND ENCRYPTED”
  • Fichier EMF: Contient le vecteur graphique pour “LOCKBIT 2.0”
  • Un fichier Blender Pro Medium TTF
  • Un fichier Proxima Nova TTF
  • Le texte du logo LockBit en PNG
  • Le logo LockBit en PNG
  • Un logo grand logo LockBit en PNG
  • Une liste de processus
  • Une liste de services

Le binaire va ensuite compter le nombre de processus dans la liste afin de les mettre dans une liste.

La configuration elle, est stocké dans une liste de bytes.

Si le byte contient 0xFF alors l’option est activĂ© dans le cas contraire, la valeur du byte est 0xAA.

Figure 20

Figure 20: Configuration du binaire.

Les index de la liste correspondent Ă  :

  • Index 0: DĂ©sactivation du bypass de l’UAC.
  • index 1: Activation de l’auto suppression.
  • Index 2: Activation de la page de log.
  • Index 3: Activation du chiffrement par le rĂ©seau.
  • Index 4, 5, 6: Si un de ces 3 flags est Ă  0xFF alors le binaire se rĂ©plique via les GPO.
  • Index 7: Mise en place de clĂ© de registre pour les fichiers .lockbit.
  • Index 8: Impression de la page de ransom sur les imprimantes.

On remarque que contrairement aux malwares dans la nature, celui-ci à une configuration modifié.

Il n’active pas le chiffrement par le rĂ©seau et ne met pas en place de clĂ© de registre pour les fichiers .lockbit.

Escalade de privilège

Pour avoir tous les droits sur la machine courante, le binaire va utiliser une technique connu nommĂ© Juicy Potato pour Ă©lever ses droits. Cette technique abuse du Golden Privileges afin d’Ă©lever ses droits en local.

Log

Le binaire va ensuite vĂ©rifier si le flag de Log est activĂ© dans la configuration. Etant donnĂ© que ce n’est pas le cas dans notre configuration, je vais passer cette partie.

Bypass UAC

Pour bypass l’UAC, le binaire va dans un premier temps vĂ©rifier qu’il est admin puis, va bypass l’UAC via l’interface COM ColorDataProxy/CCMLuaUtil. Cette technique connu peut ĂŞtre trouvĂ© sur Github.

RĂ©plication via GPO

Si le binaire est admin et qu’un des flags pour la rĂ©plication GPO est activĂ© alors, celui-ci va ensuite essayer de se rĂ©pliquer via les GPO.

Figure 21

Figure 21: Vérification des droits et des flags pour lancer la réplication via GPO.

Dans un premier temps, le binaire vĂ©rifie s’il est exĂ©cutĂ© sur l’Active Directory en rĂ©cupĂ©rant le nom de l’ordinateur courant et celui de l’Active Directory afin de comparer les deux.

Figure 22

Figure 22: Check si l’ordinateur actuel est un AD.

Si l’ordinateur actuel n’est pas un AD, alors cette partie s’arrĂŞte et le binaire n’essaye de pas de crĂ©er de GPO.

Le binaire, va ensuite rĂ©cupĂ©rer le nom DNS de l’AD ainsi que le nom du compte Administrateur afin de se connecter au domain.

Suite Ă  cela, il va prĂ©parer la chaĂ®ne pour la crĂ©ation de la GPO. Pour cela, il s’aide de la format string %02X%02X%02X%02X%02X%02X%02X utilisĂ© sur la clĂ© publique hardcodĂ© dans le programme.

Cette clé publique aussi est différente des autres samples rencontré dans la nature.

A l’aide de cette chaĂ®ne, le binaire va ensuite se connecter au domaine.

Figure 23

Figure 23: CrĂ©ation de la chaĂ®ne Ă  l’aide de la format string et connexion au domaine.

Dans cette continuitĂ©, en s’aidant de la chaĂ®ne LDAP formatĂ© juste avant, le binaire va crĂ©er la GPO dans le domaine.

Figure 24

Figure 24: Création de la GPO.

Une fois cette GPO créé, le binaire va créer et mettre à jour le fichier GPT.INI.

Ce fichier va contenir la chaîne suivante formaté:

[General]
Version=%s
displayName=%s

La version est contenu sur la stack est XORé ce qui permet de la récupérer. La valeur pour la version est 2621892.

Figure 25

Figure 25: Contenu du fichier GPT.INI.

Maintenant, le binaire va mettre Ă  jour le dossier de la GPO pour y ajouter les fichiers suivants :

  • \MACHINE\Preferences\NetworkShares\NetworkShares.xml: Permet de mettre en partage rĂ©seau tous les disques du serveur.
  • \MACHINE\Preferences\Services\Services.xml: ArrĂŞte une liste de service trouvĂ© prĂ©cĂ©demment.
  • \MACHINE\Preferences\Files\Files.xml: Place le binaire sur le Bureau de tous les partages.
  • \MACHINE\Preferences\ScheduledTasks\ScheduledTasks.xml: Kill tous les process de la liste trouvĂ© prĂ©cĂ©demment.
  • \MACHINE\Registry.pol: Contient des clĂ©s de registre.
  • \MACHINE\comment.cmtx

Les chaînes de caractères de chaque fichier sont situés sur la stack et encodé différemment à chaque fois. Pour le cas de ScheduledTasks.xml le contenu du fichier est encodé de la manière suivante :

Figure 26

Figure 26: Décodage de la chaîne pour le fichier ScheduledTasks.xml.

Une fois le contenu des fichiers mise en place, le programme attend une minute avant de lancer une réplication.

Pour la réplication, le programme passe par PowerShell, cette chaîne est encodé dans la stack puis décodé avec une simple soustraction.

Figure 27

Figure 27: Commande de réplication PowerShell.

Le binaire vĂ©rifie Ă©videmment si la commande s’est bien dĂ©roulĂ©. En cas de problème celui-ci passe par le LDAP pour envoyer un gpudpate sur tous les postes.

Figure 28 Figure 28: Fin de la fonction de réplication.

Suppression des Shadows Copies

Une fois le malware implanté, celui-ci va supprimer les backups pour que le système ne soit plus récupérables. Pour cela, il va passer par des chaînes encodés sur la stack et va exécuter les commandes suivantes :

  • cmd.exe /c vssadmin Delete Shadows /All /Quiet
  • cmd.exe /c bcdedit /set {default} recoveryenabled No
  • cmd.exe /c bcdedit /set {default} bootstatuspolicy ignoreallfailures
  • cmd.exe /c wmic SHADOWCOPY /nointeractive
  • cmd.exe /c wevtutil cl security
  • cmd.exe /c wevtutil cl system
  • cmd.exe /c wevtutil cl application

Figure 29

Figure 29: Exécute chacune des commandes pour supprimer les shadows copies.

Impression des notes du ransomware

Figure 30

Figure 30: Lancement de la fonction pour imprimer la ransomnote.

Pour ce qui est de l’impression, dans un premier temps le binaire rĂ©cupère toutes les imprimantes sur le système Ă  l’aide de la fonction EnumPrintersW.

Une fois la liste de toutes les imprimantes rĂ©cupĂ©rĂ©s, il va s’assurer de ne pas imprimer dans des fichiers en comparant les imprimantes avec les chaĂ®nes Microsoft Print to PDF et Microsoft XPS Document Writer.

Une fois ce filtrage effectuĂ©, le binaire va ouvrir l’imprimante, Ă©crire le contenu de la ransomnote et fermer l’imprimante pour chacune des imprimantes prĂ©sentes.

Figure 31

Figure 31: Fermeture de l’imprimante.

Processus de chiffrement

Le binaire appelle la fonction FindFirstVolumeW afin de trouver le premier volume de disponible sur la machine pour commencer son chiffrement. Il itère les volumes suivants avec FindNextVolumeW pour trouver ceux disponibles.

Figure 32

Figure 32: Itération pour récupérer tous les volumes.

Pour initialiser son contexte cryptographique, le binaire essaye d’importer la DLL bcrypt, s’il Ă©choue il rĂ©cupère alors la fonction CryptAcquireContextW prĂ©sente dans la DLL advapi32.

Figure 33

Figure 33: Initialisation de la fonction Cryptographique.

Le binaire crĂ©Ă© ensuite une paire de clĂ© publique et privĂ©e, Ă  l’aide de l’algorithme Libsodium. Il chiffre la clĂ© publique et supprime la clĂ© privĂ©e de la mĂ©moire.

Figure 34

Figure 34: Génération, Chiffrement, Suppression.

Pour sa dernière partie de process, le binaire va lancer la fonction NtCreateIoCompletion pour lui permettre d’accĂ©lĂ©rer son process de chiffrement et va lancer autant de Thread de chiffrement qu’en contient le CPU.

Durant son process, le binaire va Ă©viter de chiffrer les dossiers, fichiers et extensions suivantes:

Dossiers:

  • $Windows.~bt
  • intel
  • msocache
  • $recycle.bin
  • $windows.~ws
  • tor browser
  • boot
  • windows nt
  • msbuild
  • microsoft
  • all users
  • system volume information
  • perflog
  • google
  • application data
  • windows
  • windows.old
  • appdata
  • mozilla
  • microsoft.net
  • microsoft shared
  • internet explorer
  • common files
  • opera
  • windows journal
  • windows defender
  • windowsapp
  • windowspowershell
  • usoshared
  • windows security
  • windows photo viewer

Fichiers:

  • ntldr
  • ntuser.dat.log
  • bootsect.bak
  • autorun.inf
  • thumbs.db
  • iconcache.db
  • restore-my-files.txt

Extensions:

  • .386
  • .cmd
  • .ani
  • .adv
  • .msi
  • .msp
  • .com
  • .nls
  • .ocx
  • .mpa
  • .cpl
  • .mod
  • .hta
  • .prf
  • .rtp
  • .rpd
  • .bin
  • .hlp
  • .shs
  • .drv
  • .wpx
  • .bat
  • .rom
  • .msc
  • .spl
  • .msu
  • .ics
  • .key
  • .exe
  • .dll
  • .lnk
  • .ico
  • .hlp
  • .sys
  • .drv
  • .cur
  • .idx
  • .ini
  • .reg
  • .mp3
  • .mp4
  • .apk
  • .ttf
  • .otf
  • .fon
  • .fnt
  • .dmp
  • .tmp
  • .pif
  • .wav
  • .wma
  • .dmg
  • .iso
  • .app
  • .ipa
  • .xex
  • .wad
  • .msu
  • .icns
  • .lock
  • .lockbit
  • .theme
  • .diagcfg
  • .diagcab
  • .diagpkg
  • .msstyles
  • .gadget
  • .woff
  • .part
  • .sfcache
  • .winmd

Auto Suppression

Une fois le processus de chiffrement terminé, le programme va procéder à sa suppression.

Pour cela, il va lancer une commande shell toujours encodé sur la stack.

Figure 35

Figure 35: DĂ©codage de la chaĂ®ne d’auto suppression.

La commande fsutil est utilisĂ© pour que le binaire ne soit plus sur le disque une fois l’exĂ©cution terminĂ©. C’est bien plus efficace qu’une simple suppression avec la commande rm car le fichier est totalement remplacĂ© sur le disque, il n’y a donc pas de moyen de le rĂ©cupĂ©rĂ© avec des outils une fois la suppression effectuĂ©.

De plus, il utilise la fonction MoveFileExW pour dire au système de supprimer le fichier après un reboot.

Fin d’exĂ©cution

Le binaire résout la fonction ExitProcess afin de se fermer.

Figure 36

Figure 36: ArrĂŞt du binaire.

Conclusion

La génération de clé de 32 bits suivis du chiffrement de la clé publique avec la clé publique de Lockbit et la suppression de la clé privée en mémoire rend le processus de décryptage impossible.

De plus, le binaire ne communique pas avec l’extĂ©rieur. Il n’envoie pas de message et ne se connecte Ă  aucun C2. Ils n’ont pas besoin de rĂ©cupĂ©rer d’information spĂ©cifique sur le chiffrement car toutes les informations sont stockĂ©s Ă  la fin des fichiers. Ces informations sont bien Ă©videmment aussi chiffrĂ©s.

Pour ce qui est de la propagation, sachez que si la configuration GPO est activĂ© dans le binaire et que vous dĂ©tectez une GPO pour dĂ©ployer le malware. Celui-ci Ă  de grande chance d’avoir Ă©tĂ© lancĂ© dans un premier temps sur l’Active Directory.