Comment les logiciels malveillants échappent aux sandbox avec Visual Basic

Chaque jour au JSOC CERT, nous rencontrons des événements de différents bacs à sable qui fonctionnent dans le cadre des solutions AntiAPT de nos clients et laissons passer des milliers de fichiers provenant du trafic Web et e-mail. Il convient de noter que les systèmes Sandbox modernes dans leur développement sont allés beaucoup plus loin que la simple interception des appels système en mode noyau et des fonctions API en mode utilisateur. De plus en plus, ils utilisent leur propre hyperviseur, un système pour émuler l'activité des utilisateurs, une instrumentation dynamique, le hachage et le clustering sur des sections de code, l'analyse de la couverture du code, etc. Une telle variété de technologies crée l'illusion que si un fichier ne fonctionne pas dans le bac à sable et ne montre pas son «vrai visage», il s'agit probablement d'APT ou d'une technologie innovante pour détecter un environnement virtuel, dont la communauté de l'IB n'est pas encore au courant. Mais ...


Comme nous ne connaissons pas les caractéristiques internes du travail des bacs à sable commerciaux, nous vérifions dans certains cas - analysons manuellement les échantillons qui ont réussi le test. Récemment, nous avons constaté à plusieurs reprises que certains sandbox commerciaux (pour des raisons objectives, nous ne pouvons pas dire lesquels) n'ont pas détecté certains fichiers malveillants lors de l'analyse dynamique, et si l'analyseur statique était également silencieux, le fichier a été ignoré.

L'analyse du bac à sable a réussi à contourner des familles de logiciels malveillants bien connus comme Pony, Loki et Hawkeye. Une seule chose les a unis - ils étaient couverts par un packer écrit en Visual Basic.

Étant donné que ces familles HPE n'ont depuis longtemps rien de nouveau, le verdict «positif» du bac à sable est très déprimant. Par conséquent, nous avons décidé de décrire le principe général de fonctionnement de ce packer et les observations que nous avons faites au fil du temps.
Le schéma général du travail de l’emballeur est conditionnellement divisé en 4 étapes et est illustré dans le diagramme ci-dessous.



Le point d'entrée d'un fichier malveillant semble typique des applications Visual Basic:



Nous avons rencontré différentes options pour ce packer, et le code VB Wrapper a changé fréquemment, mais la tâche effectuée est restée la même: transférer le contrôle vers le code Stage 1. Dans les exemples précédents, le contrôle était transféré à l'aide des fonctions API de la classe Enum * (par exemple, EnumWindows, EnumCalendarInfo, etc.). e) pour lequel l'adresse Étape 1 du code a été indiquée comme paramètre. Récemment, nous observons que le contrôle est transféré directement.

Étape 1


La direction reçoit le code Étape 1. Ce code n'est pas chiffré, mais est obscurci. Les méthodes d'obfuscation varient d'un échantillon à l'autre, mais l'algorithme de fonctionnement général ne change pas:

  1. Un cycle avec de nombreuses instructions (y compris les ordures) qui génère la clé nécessaire pour décoder le code de l'étape 2. La particularité de ce morceau de code est qu'il n'y a pas de fonctions Sleep, mais en raison du grand nombre d'itérations, son exécution prend en moyenne 1-2 minutes.
  2. Déchiffrement (XOR régulier) et transfert de contrôle au code Stage 2.

La capture d'écran ci-dessous montre des exemples de méthodes d'obscurcissement utilisées:



2 étages


La tâche principale du code de l'étape 2 est de vérifier l'environnement et de mettre en œuvre des méthodes anti-débogage. Certaines parties du code sont chiffrées (déchiffrées avant exécution, puis chiffrées à nouveau avec le même algorithme XOR), ce qui rend la détection difficile par signatures. Après déchiffrement, les caractéristiques sont visibles, selon lesquelles le code de l'étape 2 peut être reconnu par une analyse manuelle.



La liste des vérifications est assez grande et diffère selon les différentes versions du packer, nous allons donc donner plusieurs méthodes qui ont été trouvées dans toutes les versions, avec des captures d'écran, et à la fin, nous listons la liste entière dans le tableau.

1) GetTickCount + Sleep


L'horodatage actuel est pris, Sleep est appelé pendant 2 secondes, après quoi un autre horodatage est immédiatement pris.

Après cela, la différence entre les notes est vérifiée (si 2 secondes se sont réellement écoulées).



2) SetErrorMode


Vérifie le bon fonctionnement de l'appel de l'API SetErrorMode. La fonction est appelée deux fois de suite avec les paramètres 0x800 et 0x0, après quoi le résultat du deuxième appel est vérifié: il doit être égal à 0x800.



3) SetLastError


Tout d'abord, SetLastError est appelée avec le paramètre 0x5, après quoi il est vérifié que la valeur du dernier code d'erreur dans le TEB est correctement définie (c'est-à-dire qu'il s'agit de 0x5).



4) Vérification du mouvement du curseur


Le code entre dans une boucle sans fin en attendant que la souris bouge.



5) DbgBreakPoint et DbgUiRemoteBreakin


Ces fonctions sont modifiées pour empêcher le débogueur de se connecter au processus.


Technique


Commentaire


GetTickCount + Sleep


Vérification des horodatages


SetErrorMode


Vérification de la fonction correcte


SetLastError


Vérifier que la fonction fonctionne correctement


GetCursorPos


Vérifier le mouvement du curseur


Dbgbreakpoint


Modification de fonction pour empêcher la connexion du débogueur


DbgUiRemoteBreakin


Modification de fonction pour empêcher la connexion du débogueur


Suppression du crochet


Les 5 premiers octets de fonctions sont restaurés dans ntdll.dll en cas de hooks


NtSetInformationThread


Paramètre 0x11 (ThreadHideFromDebugger)


GetThreadContext + check DR


Les registres de débogage DR0-DR3, DR6, DR7 sont vérifiés.


Vérifier les points d'arrêt


Les instructions INT3 (0xCC), int 3 (0xCD 0x03) et ud2 (0x0F 0x0B) au début de certaines fonctions sont vérifiées


cpuid (EAX = 0x0)


Les registres EAX, ECX, EDX sont vérifiés


cpuid (EAX = 0x40000000)


Les registres EAX, ECX, EDX sont vérifiés


cpuid (EAX = 0x1)


31e bit ECX vérifié


PEB (BeingDebugged)


Vérifie la valeur 0x1


PEB (NtGlobalFlag)


Valeur vérifiée 0x70


NtQueryInformationProcess


Appelé avec des indicateurs ProcessDebugPort (0x7), ProcessDebugFlags (0x1F), ProcessDebugObjectHandle (0x1E)


Vérification du nom du processus


Les chaînes «sample», «sandbox», «virus», «malware», «self» sont vérifiées



Si toutes les techniques de l'étape 2 sont terminées, la ligne de commande est vérifiée pour la conformité avec le format spécial. Si la vérification échoue, les actions suivantes sont effectuées:

1) La fonction CreateProcess est appelée avec l'indicateur CREATE_SUSPENDED pour redémarrer le processus en cours. Dans ce cas, la ligne de commande a le format requis.
2) À l'aide des fonctions GetContextThread et SetContextThread, le point d'entrée est changé en un nouveau, qui se trouve dans le code de l'étape 1.
3) Répétez les étapes 1 et 2 (y compris un cycle long et toutes les vérifications). Cette fois, la vérification de la ligne de commande a réussi et le processus passe à l'étape suivante.

3 étages


À ce stade, le corps du virus principal est déchiffré et la technique de processus creux est exécutée sur le processus en cours, après quoi le contrôle est transféré au point d'entrée du virus principal.

Leçon apprise


Nous ne pouvons pas dire exactement ce qui cause tel ou tel bac à sable dans ce cas, mais je veux croire que la possibilité d'utiliser les techniques décrites dans l'article par des logiciels malveillants a été prévue depuis longtemps par les fournisseurs, et le problème réside uniquement dans le long délai de la première étape du travail de l'emballeur. .

Malgré le fait que les bacs à sable modernes sont pour la plupart positionnés dans le cadre de systèmes de protection contre les attaques APT, nos observations suggèrent que même des familles malveillantes bien connues de la communauté pénètrent dans l'infrastructure avec une constance enviable. Puisqu'il n'y a aucune garantie que l'échantillon qui a contourné le bac à sable n'aura pas quelques techniques de contournement antivirus dans son arsenal, vous ne pouvez pas compter uniquement sur ce tas de solutions de protection. Dans de tels cas, un processus de surveillance correctement construit, y compris les événements de sécurité des informations des hôtes finaux, peut garantir une réponse rapide et minimiser les dommages potentiels.

Source: https://habr.com/ru/post/fr473086/


All Articles