A la mi-juin, la lutte contre le coronavirus au Kazakhstan battait son plein. Alarmées par l'augmentation du nombre de cas (alors même l'ancien président Nursultan Nazarbayev a été infecté), les autorités locales ont décidé de fermer à nouveau tous les centres commerciaux et de divertissement, les chaînes de magasins, les marchés et les bazars. Et à ce moment-là, les cybercriminels ont profité de la situation en envoyant des courriers malveillants à des entreprises russes et internationales.
Des lettres dangereuses, déguisées en appel du Ministre de la santé de la République du Kazakhstan, ont été interceptées par le Groupe IB du Système de détection des menaces (TDS). La pièce jointe contenait des documents qui, une fois lancés, installaient un programme malveillant de la famille Loki PWS (Password Stealer), conçu pour voler les identifiants et les mots de passe d'un ordinateur infecté. À l'avenir, les attaquants peuvent les utiliser pour accéder à des comptes de messagerie pour fraude financière, espionnage ou vendre sur des forums de pirates.
Dans cet article, Nikita Karpov, analyste au CERT-GIB , examine une instance de l'un des voleurs de données les plus populaires actuellement - Loki.
Aujourd'hui, nous allons considérer l'une des versions de bot populaires - 1.8. Il est activement vendu, et le panneau d'administration peut même être trouvé dans le domaine public: ici .
Exemple de panneau d'administration:
Loki est écrit en C ++ et est l'un des logiciels malveillants les plus populaires utilisés pour voler les informations utilisateur d'un ordinateur infecté. Comme le fléau de notre temps - les virus ransomwares - Data Stealer, après avoir été touché sur l'ordinateur de la victime, effectue la tâche à très grande vitesse - il n'a pas besoin de prendre pied et d'augmenter ses privilèges dans le système, il ne laisse presque pas le temps de se défendre contre une attaque. Par conséquent, dans les événements avec des logiciels malveillants qui volent les données des utilisateurs, le rôle principal est joué par l'enquête sur l'incident.
Déballage et obtention d'un vidage de malware fonctionnel
La distribution se fait dans la plupart des cas par le biais de pièces jointes dans les listes de diffusion. L'utilisateur, déguisé en fichier légitime, télécharge et ouvre la pièce jointe, lançant le malware.
Le marqueur d'injection suggère la présence d'un Loader.
Avec l'aide de DIE, nous obtenons des informations indiquant que le fichier source est écrit en VB6.
Le graphique d'entropie indique une grande quantité de données cryptées.
Une fois lancé, le premier processus crée un processus enfant, l'injecte et se termine. Le deuxième processus est responsable du travail du malware. Après une courte période de temps, nous arrêtons le processus et enregistrons le vidage de la mémoire. Pour confirmer que Loki est à l'intérieur du vidage, regardez à l'intérieur de l'url du centre de commande, qui dans la plupart des cas se termine par fre.php .
Nous vidons le fragment de mémoire contenant le Loki et corrigeons l'en-tête PE.
Nous vérifierons les performances du dump à l'aide du système TDS Huntbox.
Fonctionnalité du bot
Lors de l'examen du code du malware décompilé, nous trouvons une partie contenant quatre fonctions qui vont immédiatement après l'initialisation des bibliothèques nécessaires à l'opération. Après avoir démonté chacun d'eux à l'intérieur, nous déterminons leur objectif et la fonctionnalité de nos logiciels malveillants.
Les noms des fonctions ont été renommés pour être plus descriptifs pour plus de commodité.
La fonctionnalité du bot est déterminée par deux fonctions principales:
- Data Stealer est la première fonction chargée de voler les données de 101 applications et de les envoyer au serveur.
- Downloader - une demande des commandes CnC (Command & Control) pour l'exécution.
Pour plus de commodité, le tableau ci-dessous répertorie toutes les applications à partir desquelles l'instance Loki examinée tente de voler des données.
ID de fonction | application | ID de fonction | application | ID de fonction | application |
---|---|---|---|---|---|
1 | Mozilla Firefox | 35 | FTPInfo | 69 | ClassiqueFTP |
2 | Comodo IceDragon | 36 | LinasFTP | 70 | PuTTY / KiTTY |
3 | Safari aux pommes | 37 | FileZilla | 71 | Thunderbird |
4 | K-Meleon | 38 | Personnel-FTP | 72 | Foxmail |
cinq | SeaMonkey | 39 | BlazeFtp | 73 | Pocomail |
6 | Troupeau | 40 | NETFile | 74 | IncrediMail |
7 | NETGATE BlackHawk | 41 | GoFTP | 75 | Gmail notifier pro |
8 | Lunascape | 42 | ALFTP | 76 | Vérifier le courrier |
neuf | Google Chrome | 43 | DeluxeFTP | 77 | WinFtp |
Dix | Opéra | 44 | Commandant total | 78 | Martin Prikryl |
Onze | Navigateur QTWeb | 45 | FTPGetter | 79 | 32BitFtp |
12 | QupZilla | 46 | WS_FTP | 80 | Navigateur FTP |
treize | Internet Explorer | 47 | Fichiers de configuration du client de messagerie | 81 | Mailing
(softwarenetz) |
Quatorze | Opéra 2 | 48 | Poker Full Tilt | 82 | Courrier Opera |
quinze | Cyberfox | 49 | Pokerstars | 83 | Boîte aux lettres |
seize | Lune pale | 50 | ExpanDrive | 84 | FossaMail |
17 | Waterfox | 51 | Coursier | 85 | Becky! |
dix-huit | Sabir | 52 | FlashFXP | 86 | POP3 |
19 | SuperPutty | 53 | NovaFTP | 87 | Perspective |
20 | FTPShell | 54 | NetDrive | 88 | Ymail2 |
21 | NppFTP | 55 | Commandant total 2 | 89 | Trojitá |
22 | MyFTP | 56 | SmartFTP | 90 | TrulyMail |
23 | FTPBox | 57 | Gestionnaire FAR | 91 | Fichiers .spn |
24 | sherrod FTP | 58 | Bitvise | 92 | Liste des tâches |
25 | FTP maintenant | 59 | RealVNC
TightVNC |
93 | Stickies |
26 | NexusFile | 60 | Portefeuille mSecure | 94 | NoteFly |
27 | Xftp | 61 | Syncovery | 95 | RemarqueZilla |
28 | EasyFTP | 62 | FreshFTP | 96 | Notes autocollantes |
29 | SftpNetDrive | 63 | BitKinex | 97 | KeePass |
trente | AbleFTP | 64 | UltraFXP | 98 | Enpass |
31 | JaSFtp | 65 | FTP maintenant 2 | 99 | Mon RoboForm |
32 | Automatiser | 66 | Vandyk SecureFX | 100 | 1Mot de passe |
33 | Cyberduck | 67 | Expert FTP sécurisé d'Odin | 101 | Mikrotik WinBox |
34 | Fullsync | 68 | Jeter |
La mise en réseau
Deux problèmes doivent être résolus pour enregistrer les interactions réseau:
- Le centre de commande n'est disponible qu'au moment de l'attaque.
- Wireshark n'enregistre pas les communications du bot dans le bouclage, vous devez donc utiliser d'autres moyens.
La solution la plus simple consiste à transmettre l'adresse CnC avec laquelle Loki communiquera à localhost. Pour le bot, le serveur est désormais disponible à tout moment, même s'il ne répond pas, mais il n'est pas nécessaire d'enregistrer les communications du bot. Pour résoudre le deuxième problème, nous utiliserons l'utilitaire RawCap, qui nous permet d'écrire les communications dont nous avons besoin pour pcap. Ensuite, nous analyserons le pcap enregistré dans Wireshark.
Avant chaque communication, le bot vérifie la disponibilité de CnC et, si disponible, ouvre une socket. Toutes les communications réseau ont lieu au niveau du transport en utilisant le protocole TCP et au niveau de l'application, HTTP est utilisé.
Le tableau ci-dessous montre les en-têtes de paquets que Loki utilise en standard.
Champ | Valeur | La description |
---|---|---|
Agent utilisateur | Mozilla / 4.08 (Charon; Inferno) | Un agent utilisateur typique pour Loki |
J'accepte | * / * | |
Type de contenu | application / flux d'octets | |
Encodage de contenu | binaire | |
Clé de contenu | 7DE968CC | Résultat de hachage des en-têtes précédents (le hachage est effectué par un algorithme CRC personnalisé avec le polynôme 0xE8677835) |
Lien | Fermer |
- La structure des données enregistrées dépend de la version du bot, et dans les versions antérieures, aucun champ n'est responsable des options de chiffrement et de compression.
- Le serveur détermine par le type de demande comment traiter les données reçues. Il existe 7 types de données que le serveur peut lire:
- 0x26 Données de portefeuille volées
- 0x27 Données d'application volées
- 0x28 Demande de commande du serveur
- 0x29 Déchargement d'un fichier volé
- 0x2A POS
- Données du keylogger 0x2B
- Capture d'écran 0x2C
- Dans l'instance examinée, seuls 0x27, 0x28 et 0x2B étaient présents.
- Chaque demande contient des informations générales sur le bot et le système infecté, selon lesquelles le serveur identifie tous les rapports pour une machine, puis il y a des informations qui dépendent du type de demande.
- Dans la dernière version du bot, seule la compression des données est implémentée et les champs chiffrés sont préparés pour l'avenir et ne sont pas traités par le serveur.
- La bibliothèque APLib open source est utilisée pour compresser les données.
Lors de la formation d'une requête avec des données volées, le bot alloue un tampon de taille 0x1388 (5000 octets). La structure des requêtes 0x27 est indiquée dans le tableau ci-dessous:
Biais | La taille | Valeur | La description |
---|---|---|---|
0x0 | 0x2 | 0x0012 | Version du bot |
0x2 | 0x2 | 0x0027 | Type de demande (envoyer des données volées) |
0x4 | 0xD | ckav.ru | ID binaire (XXXXX11111 se produit également) |
0x11 | 0x10 | - | Nom d'utilisateur |
0x21 | 0x12 | - | Nom de l'ordinateur |
0x33 | 0x12 | - | Nom de domaine informatique |
0x45 | 0x4 | - | Résolution d'écran (largeur et hauteur)
|
0x49 | 0x4 | - | |
0x4D | 0x2 | 0x0001 | Drapeau des droits de l'utilisateur (1 si administrateur) |
0x4F | 0x2 | 0x0001 | Indicateur SID (1 si défini) |
0x51 | 0x2 | 0x0001 | Indicateur de bitness du système (1 si x64) |
0x53 | 0x2 | 0x0006 | Version Windows (numéro de version majeur) |
0x55 | 0x2 | 0x0001 | Version Windows (numéro de version mineur) |
0x57 | 0x2 | 0x0001 | Informations système supplémentaires (1 = VER_NT_WORKSTATION) |
0x59 | 0x2 | - | |
0x5B | 0x2 | 0x0000 | Les données volées ont-elles été envoyées |
0x5D | 0x2 | 0x0001 | La compression de données a-t-elle été utilisée |
0x5F | 0x2 | 0x0000 | Type de compression |
0x61 | 0x2 | 0x0000 | Le cryptage des données a-t-il été utilisé |
0x63 | 0x2 | 0x0000 | Type de chiffrement |
0x65 | 0x36 | - | MD5 à partir de la valeur de registre MachineGuid |
0x9B | - | - | Données volées compressées |
Taille du tampon: 0x2BC (700 octets)
Biais | La taille | Valeur | La description |
---|---|---|---|
0x0 | 0x2 | 0x0012 | Version du bot |
0x2 | 0x2 | 0x0028 | Type de demande (demande de commande du centre de commande) |
0x4 | 0xD | ckav.ru | ID binaire (XXXXX11111 se produit également) |
0x11 | 0x10 | - | Nom d'utilisateur |
0x21 | 0x12 | - | Nom de l'ordinateur |
0x33 | 0x12 | - | Nom de domaine informatique |
0x45 | 0x4 | - | Résolution d'écran (largeur et hauteur) |
0x49 | 0x4 | - | |
0x4D | 0x2 | 0x0001 | Drapeau des droits de l'utilisateur (1 si administrateur) |
0x4F | 0x2 | 0x0001 | Indicateur SID (1 si défini) |
0x51 | 0x2 | 0x0001 | Indicateur de bitness du système (1 si x64) |
0x53 | 0x2 | 0x0006 | Version Windows (numéro de version majeur) |
0x55 | 0x2 | 0x0001 | Version Windows (numéro de version mineur) |
0x57 | 0x2 | 0x0001 | Informations système supplémentaires (1 = VER_NT_WORKSTATION) |
0x59 | 0x2 | 0xFED0 | |
0x5B | 0x36 | - | MD5 à partir de la valeur de registre MachineGuid |
Taille du tampon: 0x10 (16 octets) + 0x10 (16 octets) pour chaque commande du paquet.
En-tête HTTP (début des données) | \ r \ n \ r \ n | [0D 0A 0D 0A] | 4 octets | ||
- | - | 4 | |||
2 | [00 00 00 02] | 4 | |||
4 |
4 |
4 |
4 |
() |
|
---|---|---|---|---|---|
#0
EXE- |
[00 00 00 00] | [00 00 00 00] | [00 00 00 00] | [00 00 00 23] | www.notsogood.site/malicious.exe |
#1
DLL |
[00 00 00 00] | [00 00 00 01] | [00 00 00 00] | [00 00 00 23] | www.notsogood.site/malicious.dll |
#2
EXE- |
[00 00 00 00] | [00 00 00 02] | [00 00 00 00] | [00 00 00 23] | www.notsogood.site/malicious.exe |
#8
(HDB file) |
[00 00 00 00] | [00 00 00 08] | [00 00 00 00] | [00 00 00 00] | - |
#9
|
[00 00 00 00] | [00 00 00 09] | [00 00 00 00] | [00 00 00 00] | - |
#10
|
[00 00 00 00] | [00 00 00 0A] | [00 00 00 00] | [00 00 00 00] | - |
#14
Loki |
[00 00 00 00] | [00 00 00 0E] | [00 00 00 00] | [00 00 00 00] | - |
#15
Loki |
[00 00 00 00] | [00 00 00 0F] | [00 00 00 00] | [00 00 00 23] | www.notsogood.site/malicious.exe |
# 16
Changer la fréquence de vérification de la réponse du serveur |
[00 00 00 00] | [00 00 00 10] | [00 00 00 00] | [00 00 00 01] | cinq |
# 17
Supprimer Loki et quitter |
[00 00 00 00] | [00 00 00 11] | [00 00 00 00] | [00 00 00 00] | - |
Analyseur de trafic réseau
Grâce à cette analyse, nous avons toutes les informations dont nous avons besoin pour analyser les interactions réseau de Loki.
L'analyseur est implémenté en Python, reçoit un fichier pcap en entrée et y trouve toutes les communications appartenant à Loki.
Tout d'abord, utilisons la bibliothèque dkpt pour trouver tous les paquets TCP. Pour ne recevoir que des paquets http, mettons un filtre sur le port utilisé. Parmi les paquets http reçus, nous sélectionnons ceux qui contiennent les en-têtes Loki bien connus, et obtenons les communications qui doivent être analysées afin d'en extraire des informations sous une forme lisible.
for ts, buf in pcap:
eth = dpkt.ethernet.Ethernet(buf)
if not isinstance(eth.data, dpkt.ip.IP):
ip = dpkt.ip.IP(buf)
else:
ip = eth.data
if isinstance(ip.data, dpkt.tcp.TCP):
tcp = ip.data
try:
if tcp.dport == 80 and len(tcp.data) > 0: # HTTP REQUEST
if str(tcp.data).find('POST') != -1:
http += 1
httpheader = tcp.data
continue
else:
if httpheader != "":
print('Request information:')
pkt = httpheader + tcp.data
httpheader = ""
if debug:
print(pkt)
req += 1
request = dpkt.http.Request(pkt)
uri = request.headers['host'] + request.uri
parsed_payload['Network']['Source IP'] = socket.inet_ntoa(ip.src)
parsed_payload['Network']['Destination IP'] = socket.inet_ntoa(ip.dst)
parsed_payload_same['Network']['CnC'] = uri
parsed_payload['Network']['HTTP Method'] = request.method
if uri.find("fre.php"):
print("Loki detected!")
pt = parseLokicontent(tcp.data, debug)
parsed_payload_same['Malware Artifacts/IOCs']['User-Agent String'] = request.headers['user-agent']
print(json.dumps(parsed_payload, ensure_ascii=False, sort_keys=False, indent=4))
parsed_payload['Network'].clear()
parsed_payload['Compromised Host/User Data'].clear()
parsed_payload['Malware Artifacts/IOCs'].clear()
print("----------------------")
if tcp.sport == 80 and len(tcp.data) > 0: # HTTP RESPONCE
resp += 1
if pt == 40:
print('Responce information:')
parseC2commands(tcp.data, debug)
print("----------------------")
pt = 0
except(dpkt.dpkt.NeedData, dpkt.dpkt.UnpackError):
continue
Dans toutes les requêtes Loki, les 4 premiers octets sont responsables de la version du bot et du type de requête. En utilisant ces deux paramètres, nous déterminons comment nous traiterons les données.
def parseLokicontent(data, debug):
index = 0
botV = int.from_bytes(data[0:2], byteorder=sys.byteorder)
parsed_payload_same['Malware Artifacts/IOCs']['Loki-Bot Version'] = botV
payloadtype = int.from_bytes(data[2:4], byteorder=sys.byteorder)
index = 4
print("Payload type: : %s" % payloadtype)
if payloadtype == 39:
parsed_payload['Network']['Traffic Purpose'] = "Exfiltrate Application/Credential Data"
parse_type27(data, debug)
elif payloadtype == 40:
parsed_payload['Network']['Traffic Purpose'] = "Get C2 Commands"
parse_type28(data, debug)
elif payloadtype == 43:
parsed_payload['Network']['Traffic Purpose'] = "Exfiltrate Keylogger Data"
parse_type2b(lb_payload)
elif payloadtype == 38:
parsed_payload['Network']['Traffic Purpose'] = "Exfiltrate Cryptocurrency Wallet"
elif payloadtype == 41:
parsed_payload['Network']['Traffic Purpose'] = "Exfiltrate Files"
elif payloadtype == 42:
parsed_payload['Network'].['Traffic Purpose'] = "Exfiltrate POS Data"
elif payloadtype == 44:
parsed_payload['Network']['Traffic Purpose'] = "Exfiltrate Screenshots"
return payloadtype
La prochaine ligne sera d'analyser la réponse du serveur. Pour lire uniquement les informations utiles, recherchez la séquence \ r \ n \ r \ n , qui définit la fin des en-têtes de paquet et le début des commandes du serveur.
def parseC2commands(data, debug):
word = 2
dword = 4
end = data.find(b'\r\n\r\n')
if end != -1:
index = end + 4
if (str(data).find('<html>')) == -1:
if debug:
print(data)
fullsize = getDWord(data, index)
print("Body size: : %s" % fullsize)
index += dword
count = getDWord(data, index)
print("Commands: : %s" % count)
if count == 0:
print('No commands received')
else:
index += dword
for i in range(count):
print("Command: %s" % (i + 1))
id = getDWord(data, index)
print("Command ID: %s" % id)
index += dword
type = getDWord(data, index)
print("Command type: %s" % type)
index += dword
timelimit = getDWord(data, index)
print("Command timelimit: %s" % timelimit)
index += dword
datalen = getDWord(data, index)
index += dword
command_data = getString(data, index, datalen)
print("Command data: %s" % command_data)
index += datalen
else:
print('No commands received')
return None
Ceci conclut l'analyse de la partie principale de l'algorithme de l'analyseur et passe au résultat que nous obtenons en sortie. Toutes les informations sont affichées au format json.
Vous trouverez ci-dessous des images du résultat du travail de l'analyseur, obtenues à partir des communications de divers robots, avec différents CnC et enregistrées dans différents environnements.
Request information:
Loki detected!
Payload type: 39
Decompressed data:
{'Module': {'Mozilla Firefox'}, 'Version': {0}, 'Data': {'domain': {'https://accounts.google.com'}, 'username': {'none@gmail.com'}, 'password': {'test'}}}
{'Module': {'NppFTP'}, 'Version': {0}, 'Data': {b'<?xml version="1.0" encoding="UTF-8" ?>\r\n<NppFTP defaultCache="%CONFIGDIR%\\Cache\\%USERNAME%@%HOSTNAME%" outputShown="0" windowRatio="0.5" clearCache="0" clearCachePermanent="0">\r\n <Profiles />\r\n</NppFTP>\r\n'}}
{
"Network": {
"Source IP": "-",
"Destination IP": "185.141.27.187",
"HTTP Method": "POST",
"Traffic Purpose": "Exfiltrate Application/Credential Data",
"First Transmission": true
},
"Compromised Host/User Data": {},
"Malware Artifacts/IOCs": {}
}
Ci-dessus, un exemple de requête au serveur 0x27 (téléchargement des données d'application). Pour les tests, des comptes ont été créés dans trois applications: Mozilla Firefox, NppFTP et FileZilla. Loki propose trois options pour enregistrer les données d'application:
- Sous la forme d'une base de données SQL (l'analyseur sauvegarde la base de données et y affiche toutes les lignes disponibles).
- Sous forme ouverte, comme dans Firefox dans l'exemple.
- En tant que fichier xml comme NppFTP et FileZilla.
Request information:
Loki detected!
Payload type: 39
No data stolen
{
"Network": {
"Source IP": "-",
"Destination IP": "185.141.27.187",
"HTTP Method": "POST",
"Traffic Purpose": "Exfiltrate Application/Credential Data",
"First Transmission": false
},
"Compromised Host/User Data": {},
"Malware Artifacts/IOCs": {}
}
La deuxième requête est de type 0x28 et demande des commandes au serveur.
Responce information:
Body size: 26
Commands: 1
Command: 1
Command ID: 0
Command type: 9
Command timelimit: 0
Command data: 35
Un exemple de réponse de CnC, qui a envoyé une commande en réponse pour démarrer le keylogger. Et le déchargement ultérieur des données de keylogger.
Request information:
Loki detected!
Payload type: : 43
{
"Network": {
"Source IP": "-",
"Destination IP": "185.141.27.187",
"HTTP Method": "POST",
"Traffic Purpose": "Exfiltrate Keylogger Data"
},
"Compromised Host/User Data": {},
"Malware Artifacts/IOCs": {}
}
A la fin du travail, l'analyseur sort les informations contenues dans chaque requête du bot (informations sur le bot et le système), et le nombre de requêtes et réponses associées à Loki dans le fichier pcap.
General information:
{
"Network": {
"CnC": "nganyin-my.com/chief6/five/fre.php"
},
"Compromised Host/User Description": {
"User Name": "-",
"Hostname": "-",
"Domain Hostname": "-",
"Screen Resolution": "1024x768",
"Local Admin": true,
"Built-In Admin": true,
"64bit OS": false,
"Operating System": "Windows 7 Workstation"
},
"Malware Artifacts/IOCs": {
"Loki-Bot Version": 18,
"Binary ID": "ckav.ru",
"MD5 from GUID": "-",
"User-Agent String": "Mozilla/4.08 (Charon; Inferno)"
}
}
Requests: 3
Responces: 3
Le code d'analyseur complet est disponible sur: github.com/Group-IB/LokiParser
Conclusion
Dans cet article, nous avons examiné de plus près le malware Loki, démonté ses fonctionnalités et implémenté un analyseur de trafic réseau qui simplifiera considérablement le processus d'analyse des incidents et nous aidera à comprendre exactement ce qui a été volé sur l'ordinateur infecté. Alors que le développement de Loki est toujours en cours, seule la version 1.8 (et antérieure) a été divulguée, ce qui est la version que les professionnels de la sécurité rencontrent chaque jour.
Dans le prochain article, nous analyserons un autre voleur de données populaire, Pony, et comparerons ces logiciels malveillants.
Indicateur de compromis (IOC):
URL:
- nganyin-my.com/chief6/five/fre.php
- wardia.com.pe/wp-includes/texts/five/fre.php
- broken2.cf/Work2/fre.php
- 185.141.27.187/danielsden/ver.php
- Hachage MD5: B0C33B1EF30110C424BABD66126017E5
- User-Agent String: «Mozilla/4.08 (Charon; Inferno)»
- Binary ID: «ckav.ru»