Malwares : étude des codes malveillants

Introduction

Il est illusoire de penser qu’un chapitre suffirait pour couvrir l’étude de codes malveillants. 

La multiplicité des langages de programmation, des systèmes d’exploitation, des architectures de processeurs, l’utilisation de programmes légitimes de façon détournée et la très grande variété de vulnérabilités font qu’il existe une quasi-infinité de combinaisons qui rendent une approche systématique peu efficace, voire impossible.

De plus, il est courant de penser, à tort, qu’un antivirus est une solution de protection.

En effet, un antivirus n’est pas un bouclier qui vous empêche toute contamination, il remplit plutôt une fonction de vaccin : il vous empêche d’exécuter des malwares connus.

L’année 2020 fut une brillante démonstration de la limite de la vaccination : aucun vaccin ne protégeait de la Covid-19, malgré l’existence de nombreux vaccins, et être vacciné contre le tétanos ne vous protégeant pas d’une infection par un coronavirus.

Deux questions se posent donc :

« Dans quel cas est-il impossible d’élaborer un vaccin efficace ? » et « À quoi suis-je toujours vulnérable ? »

Pour répondre, il faut...

Qu’est-ce qu’un malware ?

Un code malveillant (en anglais malicious software, souvent abrégé en malware) est un programme conçu pour effectuer des actions malveillantes.

Une définition qui n’aide pas vraiment à avancer.

Le contenu et le comportement d’un malware dépendent grandement du but de son auteur.

L’ensemble des outils, programmes, processus, techniques, tactiques d’un attaquant ou groupe d’attaquants est abrégé TTP (en anglais : Tactics, Techniques, and Procedures).

Les codes malveillants peuvent être classés de différentes manières et plusieurs de ces classifications se retrouvent dans le langage courant.

Il n’est pas rare d’entendre parler de vers (imageant la propagation d’une machine à une autre), ce qui correspond à l’approche épidémiologique ; de credential stealers (programmes de vol d’identifiants), une approche centrée sur le but de l’attaquant ; ou encore de backdoors (portes dérobées), ce qui correspond à la description technique de la modification apportée au système pour en garder le contrôle.

La meilleure classification

C’est une question complexe et la meilleure classification est souvent celle qui répond le mieux à vos besoins.

Cependant, les classifications existantes ont bien entendu toutes leur intérêt.

Une approche épidémiologique prend en compte les facteurs favorisant la propagation d’une infection et met en scène l’agent pathogène, l’hôte, le milieu, les vecteurs de transmission, etc.

On peut ainsi réaliser un classement, une taxonomie pour les puristes. On retrouve d’ailleurs dans notre quotidien les appellations virus, vers, vecteurs de propagation, pour parler de la menace informatique.

L’avantage de cette approche, c’est qu’elle permet d’anticiper la façon de contenir la menace en prenant en compte l’éventuelle progression de la menace dans le parc informatique. 

Des approches techniques, comme MITRE Att&ck ou la CKC (Cyber Kill Chain) de Lockheed Martin, permettent de classer les malwares selon les traces qu’ils laissent sur le système et selon la phase de l’attaque dans laquelle ils s’inscrivent.

Ces étapes sont les mêmes que celles régissant un pentest : reconnaissance, énumération, exploitation, installation, mouvements latéraux, etc.

La CKC reste à un niveau macro, la matrice Att&ck zoomant jusqu’à l’artefact...

La détection par base de connaissance

Spoiler : cela ne fonctionne pas.

Une des approches les plus simples est de maintenir une liste contenant tous les codes malveillants passés, présents et futurs.

Grâce à une fonction dite de somme de contrôle (ou hash en anglais), il est possible de vérifier l’intégrité d’un fichier. Une telle fonction, par exemple SHA256, respecte un cahier des charges strict en trois points :

  • Deux fichiers différents ne peuvent pas avoir la même somme de contrôle.

  • Un fichier ne peut avoir qu’une unique somme de contrôle.

  • On ne peut pas, à partir de la somme de contrôle, retrouver le contenu du fichier d’origine.

Ce qui est vérifiable empiriquement avec le test ci-dessous :

$ cat fichier1 
Le contenu du fichier 1. 
 
# sans majuscule au début 
$ cat fichier1.bis  
le contenu du fichier 1. 
 
# avec aussi une majuscule à Fichier ; après tout, pourquoi pas 
$cat fichier1.ter 
Le contenu du Fichier 1. 
 
# autre chose rien à voir 
$ cat fichier2 
Le contenu du fichier 2, c'est à peu près la même soupe. 
A 2kPi près, dira-t-on. 
 
$ sha256sum fichier* 
a464400a766b072fb122c6d950b605442b375a18458b6be23c9b1c89c80f4a27  fichier1 
27d978894819ae58cd33d556157766773ab53933c84b161aec5d4486fbb09895...

Correspondances partielles

La principale faiblesse des fonctions de hachage, lorsqu’elles sont utilisées comme base de connaissances, est que la moindre modification du fichier entraîne un changement complet de la valeur de hash. C’est parfait pour en garantir l’intégrité, mais ce n’est pas pratique pour ce qu’on voudrait faire : savoir si deux fichiers sont partiellement ou totalement similaires.

De tels algorithmes existent et sont notamment utilisés dans les correcteurs orthographiques pour applications de messagerie ou autres traitements de texte, le plus connu étant la distance de Levenshtein : https://en.wikipedia.org/wiki/Levenshtein_distance#Computing_Levenshtein_distance

Les regex (Regular Expressions) peuvent également permettre d’identifier une correspondance partielle.

De tels algorithmes peuvent s’appliquer au calcul des hashs, on parle alors de fuzzy-hashing.

L’algorithme le plus utilisé est celui des context-triggered piecewise hashes (CTPH), dont l’implémentation la plus connue est SSDeep : https://ssdeep-project.github.io/ssdeep/index.html

Explication complète, présentation et « Paper » en anglais sont disponibles ici : https://dfrws.org/presentation/identifying-almost-identical-files-using-context-triggered-piecewise-hashing/

En simple, ou si vous n’avez pas lu le « Paper »...

Structure d’un PE et imphash

Pour comprendre le principe de l’imphash, il est nécessaire d’examiner la structure du format PE des exécutables Windows.

Nul besoin d’entrer dans les détails, la version simplifiée du schéma ci-dessous devrait suffire :

images/12EP03.png

Vous trouverez la documentation complète ici : https://docs.microsoft.com/en-us/windows/win32/debug/pe-format?redirectedfrom=MSDN

Les exécutables Windows utilisent le format PE (Portable Executable). Ils commencent par un en-tête DOS marqué par les lettres « MZ », suivi de l’en-tête PE proprement dit. PE est le format propriétaire Windows pour les fichiers exécutables, bibliothèques de développement et autres objets exécutables liés. On le reconnaît facilement via l’extension de fichier .exe ou .dll.

Le binaire est découpé en sections où sont rangés les différents contenus. La section .text est la section principale, la section .data contient les variables, .rdata contient les contenus annexes (en readonly), et la section .rsrc les ressources additionnelles (par exemple, les images).

Si vous avez déjà fait du C, du PHP, du Java ou du Python, vous savez certainement que la première chose à faire dans votre code est d’importer les librairies nécessaires au programme, ce afin...

Entropie et packing

Puisqu’il est difficile d’échapper aux méthodes combinées de l’impfuzzy + fuzzy hash, un attaquant désirant ne pas être détecté devra modifier le binaire dans son intégralité pour atteindre son but.

Une approche est de réaliser un second binaire appelé wrapper. Ce dernier n’a qu’une mission : servir de caisse de transport opaque pour notre binaire. Un binaire dans un binaire ? Binaire-ception ! On peut traduire les verbes « to pack » et « to wrap » par « emballer », on vient recouvrir le binaire de notre « papier cadeau spécial » : un autre binaire.

À ce stade, il nous faut parler d’entropie, un concept mathématique et physique.

L’entropie de Shannon mesure la quantité d’information contenue dans un fichier. Dans notre contexte, elle varie entre 0 et 8. Plus les contenus sont variés, plus l’entropie augmente.

En simplifiant, le score représente le nombre de bits qu’il faut pour pouvoir écrire toutes les valeurs contenues dans un fichier.

Par exemple, la phrase « Portez ce vieux whisky au juge blond qui fume » utilise toutes les lettres de l’alphabet ainsi que le caractère espace.

Il faut donc 27 caractères pour écrire ce message. Si on leur donne à chacun un numéro entre 0 et 26, on peut écrire le message au format binaire.

On n’a pas besoin des 8 bits pour coder les valeurs de 0 à 27, seuls 5 sont nécessaires :

0000 0000 = 0

0001 1011 = 27

Si on utilise 4 bits, on ne peut écrire que 16 valeurs (1111 = 15), 5 bits permettent d’écrire...

Analyses et outillage

Chaque type de fichier demande un outillage spécifique, sauf chez certains qui font tout avec hexdump et leurs scripts C ou Python.

Il existe des distributions Linux dédiées telles que REMNux (la distribution orientée reverse engineering, disponible sur https://remnux.org/) ou Tsurugi (la distribution orientée DFIR - Digital Forensic and Incident Response, https://tsurugi-linux.org/).

Une distribution Debian correctement configurée fonctionne tout aussi bien, à condition d’y ajouter les outils nécessaires.

La plupart sont disponibles dans les dépôts Debian (apt) ou dans les dépôts pip, voici un extrait de notre sélection personnelle :

bless

https://github.com/afrantzis/bless

Éditeur hexadécimal avec interface graphique

ssdeep

https://github.com/ssdeep-project/ssdeep

Fuzzy-hashing de fichiers

EVi

https://github.com/twpZero/EVi

Visualisation graphique d’entropie

impfuzzy

https://github.com/JPCERTCC/impfuzzy

Fuzzy-hashing des tables d’import PE

Gdb + peda

https://github.com/longld/peda

Débugueur + extension utile

pdfid

https://github.com/Rafiot/pdfid

Étude des PDF

radare2

https://github.com/radareorg/radare2

Étude des shellcodes

oletools

https://github.com/decalage2/oletools

Étude des documents Office

OfficeMalScanner

https://github.com/fboldewin/reconstructer.org/blob/master/OfficeMalScanner.zip

Étude auto des documents Office

peframe

https://github.com/guelfoweb/peframe

Étude des PE

pefile

https://github.com/erocarrera/pefile

Étude des PE

yara

https://github.com/VirusTotal/yara

Comme un grep en hexa

vt-cli

https://github.com/VirusTotal/vt-cli

Le client pour VirusTotal

CAPE

https://github.com/kevoreilly/CAPEv2

Extraction des fichiers de config...

Simulations et profilage

Une fois l’analyse de notre malware terminée, la phase de classification commence. Pour déterminer la malveillance d’un code, il est possible de corréler son activité avec les étapes d’une attaque.

La réalisation d’une attaque, que ce soit dans le cadre d’un audit de sécurité ou d’une attaque réelle, se fait par étapes. Par exemple :

  • Reconnaissance

  • Énumération

  • Exploitation

  • Post-exploitation

  • Élévation de Privilège

  • Persistance  

  • C2 : Command and Control (Canal de communication pour piloter les machines infectées)

  • Action sur objectif

Ces étapes peuvent varier légèrement selon les modèles, mais l’idée reste généralement la même. Il existe donc des points communs entre le PTES, l’OSSTMM, la CKC et la MITRE Att&ck.

La CKC est plutôt générique et s’applique très bien de façon agnostique et sur tout type de menace : Mac, Linux, Windows, réseau, OT, IoT, mobile…

https://www.lockheedmartin.com/en-us/capabilities/cyber/cyber-kill-chain.html

Le niveau de détail peut cependant varier. Ainsi, pour la matrice MITRE Att&ck, le nombre d’étapes augmente et chacune est détaillée.

Cependant, cette spécialisation se fait à un prix, car pour...

Astuces

Grace aux retours de nos lecteurs, nous enrichissons ce chapitre d’une section supplémentaire pour présenter des astuces permettant d’associer les techniques d’analyse et les résultats qu’elles permettent d’atteindre.

Hash

Permet de vérifier si un fichier correspond exactement à un fichier connu, qu’il s’agisse d’un malware ou d’un programme légitime.

DeepHash

Permet d’identifier des similarités partielles entre deux fichiers, utile pour détecter des variantes appartenant à une même famille (forks ou mutations).

Import Table Hash

Les logiciels important les mêmes fonctions, dans le même ordre, peuvent partager un comportement similaire, ce qui peut révéler une tentative d’obfuscation.

Techniques MITRE

Permettent d’identifier les objectifs de l’attaquant (tactiques) et les artefacts associés, afin de reconstruire la progression de la compromission.

Sites de classifications et sandboxes

Pour aider à établir une classification, de nombreux outils sont disponibles.

  • Bases MISP

  • Sandboxes publiques

  • Solutions de triage/comparatifs

  • Règles YARA

Tous les liens de ce chapitre sont disponibles en format texte pour faciliter le copier-coller : https://gist.github.com/twpZero ou https://bit.ly/3vr467c

Vous trouverez publié par les Éditions ENI, un livre parfaitement adapté pour faire suite à ce chapitre : « Sécurité informatique et Malwares » écrit par Paul Rascagnères. Ce livre a le mérite d’être en français, initialement intitulé « Malwares » il m’a guidé efficacement à mes débuts et l’édition 2013 siège encore sur mon bureau.

De nombreux ouvrages sont disponibles pour en apprendre plus sur le reverse engineering et l’analyse de malwares. De simples recherches Google devraient donner de bons résultats : « malware analysis books »...