Analyse des Malwares ELF Linux
Quand l'utiliser
- Un serveur ou conteneur Linux a été compromis et des binaires ELF suspects sont trouvés
- Analyse de botnets Linux (Mirai, Gafgyt, XorDDoS), mineurs de cryptomonnaies ou ransomwares
- Investigation de malwares ciblant l'infrastructure cloud, les conteneurs Docker ou les pods Kubernetes
- Rétro-ingénierie de rootkits et modules noyau Linux
- Analyse de malwares multiplateformes compilés pour les architectures Linux x86_64, ARM ou MIPS
Ne pas utiliser pour l'analyse de binaires PE Windows ; utiliser PEStudio, Ghidra ou IDA pour les malwares Windows.
Prérequis
- Ghidra ou IDA avec support ELF Linux pour le désassemblage et la décompilation
- VM d'analyse Linux (Ubuntu 22.04 recommandé) avec outils de développement installés
- strace, ltrace et GDB pour l'analyse dynamique et le débogage
- readelf, objdump et nm de GNU binutils pour l'inspection statique
- Radare2 pour le triage rapide de binaires et l'analyse scriptée
- Docker pour l'exécution isolée de malwares dans des conteneurs
Workflow
Étape 1 : Identifier les propriétés du binaire ELF
Examiner l'en-tête ELF et les propriétés de base :
# Identification du type de fichier
file suspect_binary
# Analyse détaillée de l'en-tête ELF
readelf -h suspect_binary
# En-têtes de sections
readelf -S suspect_binary
# En-têtes de segments (programmes)
readelf -l suspect_binary
# Table des symboles (si non strip)
readelf -s suspect_binary
nm suspect_binary 2>/dev/null
# Informations sur l'édition de liens dynamique
readelf -d suspect_binary
ldd suspect_binary 2>/dev/null # Uniquement sur l'architecture correspondante !
# Calcul des hash
md5sum suspect_binary
sha256sum suspect_binary
# Vérification du packing/UPX
upx -t suspect_binary
# Analyse ELF basée sur Python
from elftools.elf.elffile import ELFFile
import hashlib
with open("suspect_binary", "rb") as f:
data = f.read()
sha256 = hashlib.sha256(data).hexdigest()
with open("suspect_binary", "rb") as f:
elf = ELFFile(f)
print(f"SHA-256 : {sha256}")
print(f"Classe : {elf.elfclass}-bit")
print(f"Endian : {elf.little_endian and 'Petit' or 'Grand'}")
print(f"Machine : {elf.header.e_machine}")
print(f"Type : {elf.header.e_type}")
print(f"Point d'entrée : 0x{elf.header.e_entry:X}")
# Vérification si strip
symtab = elf.get_section_by_name('.symtab')
print(f"Strip : {'Oui' if symtab is None else 'Non'}")
# Analyse d'entropie des sections
import math
from collections import Counter
for section in elf.iter_sections():
data = section.data()
if len(data) > 0:
entropy = -sum((c/len(data)) * math.log2(c/len(data))
for c in Counter(data).values() if c > 0)
if entropy > 7.0:
print(f" [!] Section haute entropie : {section.name} ({entropy:.2f})")
Étape 2 : Extraire les chaînes et indicateurs
Rechercher les IOCs embarqués et les indices de fonctionnalité :
# Chaînes ASCII
strings suspect_binary > strings_output.txt
# Recherche d'indicateurs réseau
grep -iE "(http|https|ftp)://" strings_output.txt
grep -iE "([0-9]{1,3}\.){3}[0-9]{1,3}" strings_output.txt
grep -iE "[a-zA-Z0-9.-]+\.(com|net|org|io|ru|cn)" strings_output.txt
# Recherche de commandes shell
grep -iE "(bash|sh|wget|curl|chmod|/tmp/|/dev/)" strings_output.txt
# Recherche d'indicateurs de minage de cryptomonnaies
grep -iE "(stratum|xmr|monero|pool\.|mining)" strings_output.txt
# Recherche de vol SSH/credentials
grep -iE "(ssh|authorized_keys|id_rsa|shadow|passwd)" strings_output.txt
# Recherche de mécanismes de persistance
grep -iE "(crontab|systemd|init\.d|rc\.local|ld\.so\.preload)" strings_output.txt
# FLOSS pour les chaînes obfusquées (si disponible)
floss suspect_binary
Étape 3 : Analyser les appels système et l'utilisation des bibliothèques
Identifier les appels système et les bibliothèques utilisées par le malware :
# Liste des fonctions importées (liens dynamiques)
readelf -r suspect_binary | grep -E "socket|connect|exec|fork|open|write|bind|listen"
# Tracer les appels système pendant l'exécution (dans une VM isolée uniquement)
strace -f -e trace=network,process,file -o strace_output.txt ./suspect_binary
# Tracer les appels aux bibliothèques
ltrace -f -o ltrace_output.txt ./suspect_binary
# Appels système clés à surveiller :
# Réseau : socket, connect, bind, listen, accept, sendto, recvfrom
# Processus : fork, execve, clone, kill, ptrace
# Fichier : open, read, write, unlink, rename, chmod
# Persistance : inotify_add_watch (surveillance de fichiers)
Étape 4 : Analyse dynamique avec GDB
Déboguer le malware pour observer le comportement à l'exécution :
# Démarrer GDB avec le binaire
gdb ./suspect_binary
# Définir des points d'arrêt sur les fonctions clés
(gdb) break main
(gdb) break socket
(gdb) break connect
(gdb) break execve
(gdb) break fork
# Exécuter et analyser
(gdb) run
(gdb) info registers # Voir l'état des registres
(gdb) x/20s $rdi # Examiner un argument chaîne
(gdb) bt # Backtrace
(gdb) continue
# Pour les binaires strip, arrêter sur le point d'entrée
(gdb) break *0x400580 # Point d'entrée de readelf
(gdb) run
# Surveiller les connexions réseau pendant l'exécution
# Dans un autre terminal :
ss -tlnp # Lister les sockets en écoute
ss -tnp # Lister les connexions établies
Étape 5 : Rétro-ingénierie avec Ghidra
Effectuer une analyse approfondie du code du binaire ELF :
Analyse Ghidra pour ELF Linux :
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. Importer : File -> Import -> Sélectionner le binaire ELF
- Ghidra détecte automatiquement le format ELF et l'architecture
- Accepter les options d'analyse par défaut
2. Cibles d'analyse clés :
- Fonction main() (ou point d'entrée si strip)
- Fonctions de création de socket et de connexion
- Logique de répartition des commandes (switch/case sur les données reçues)
- Routines de chiffrement/cryptage
- Code d'installation de persistance
- Fonctions d'auto-propagation/scan
3. Pour les botnets comme Mirai, rechercher :
- Liste d'identifiants pour attaque par force brute (telnet/SSH)
- Sélection de module d'attaque (UDP flood, SYN flood, ACK flood)
- Module de scan (scan de ports pour appareils vulnérables)
- Module tueur (élimination des botnets concurrents)
4. Pour les mineurs de cryptomonnaies, rechercher :
- Connexion au pool de minage (protocole stratum)
- Chaînes d'adresse de portefeuille
- Fonctions d'utilisation CPU/GPU
- Techniques de masquage de processus
Étape 6 : Analyser la persistance spécifique à Linux
Vérifier les mécanismes de persistance :
# Vérifier la présence de rootkit LD_PRELOAD
strings suspect_binary | grep "ld.so.preload"
# Un malware écrivant dans /etc/ld.so.preload peut intercepter tous les appels aux bibliothèques dynamiques
# Vérifier la persistance via crontab
strings suspect_binary | grep -i "cron"
# Vérifier la création de service systemd
strings suspect_binary | grep -iE "systemd|\.service|systemctl"
# Vérifier la création de script init
strings suspect_binary | grep -iE "init\.d|rc\.local|update-rc"
# Vérifier l'injection de clé SSH
strings suspect_binary | grep -i "authorized_keys"
# Vérifier le chargement de module noyau (rootkit)
strings suspect_binary | grep -iE "insmod|modprobe|init_module"
# Vérifier le masquage de processus
strings suspect_binary | grep -iE "proc|readdir|getdents"
Concepts Clés
| Terme | Définition |
|---|---|
| ELF (Executable and Linkable Format) | Format binaire standard pour les exécutables Linux, les bibliothèques partagées et les core dumps contenant en-têtes, sections et segments |
| Binaire strip | Binaire ELF dont les symboles de débogage ont été supprimés, rendant la rétro-ingénierie plus difficile car les noms de fonctions sont perdus |
| LD_PRELOAD | Variable d'environnement Linux spécifiant les bibliothèques partagées à charger avant toutes les autres ; utilisée par les rootkits pour intercepter les appels aux bibliothèques système |
| strace | Traceur d'appels système Linux qui enregistre tous les appels système et signaux d'un processus, révélant les opérations sur fichiers, réseau et processus |
| GOT/PLT | Table des offsets globaux et Table de liaison de procédure ; structures ELF pour l'édition de liens dynamique pouvant être détournées pour le crochetage de fonctions |
| Lié statiquement | Binaire compilé avec tout le code des bibliothèques inclus ; courant dans les malwares IoT pour fonctionner sur des systèmes sans bibliothèques partagées correspondantes |
| Mirai | Botnet Linux prolifique ciblant les appareils IoT via force brute telnet ; code source divulgué, menant à de nombreuses variantes |
Outils et Systèmes
- Ghidra : Outil de rétro-ingénierie de la NSA avec support complet ELF pour x86, x86_64, ARM, MIPS et autres architectures Linux
- Radare2 : Framework de rétro-ingénierie open source avec interface en ligne de commande pour l'analyse rapide de binaires et le scripting
- strace : Outil de traçage des appels système Linux pour observer le comportement du binaire, y compris les opérations fichiers, réseau et processus
- GDB : Débogueur GNU pour définir des points d'arrêt, examiner la mémoire et exécuter pas à pas l'exécution de binaires Linux
- pyelftools : Bibliothèque Python pour analyser les fichiers ELF par programme pour des pipelines d'analyse automatisée
Scénarios Courants
Scénario : Analyse d'un mineur de cryptomonnaies trouvé sur un serveur Linux compromis
Contexte : Un serveur cloud affiche une utilisation CPU à 100%. L'investigation révèle un binaire inconnu s'exécutant depuis /tmp avec un nom suspect. Le binaire doit être analysé pour confirmer qu'il s'agit d'un mineur de cryptomonnaies et identifier le portefeuille de l'attaquant et le pool.
Approche :
- Copier le binaire sur une VM d'analyse et calculer le hash SHA-256
- Exécuter
fileetreadelfpour identifier l'architecture et le type de liaison - Extraire les chaînes et rechercher les adresses de pool de minage (stratum+tcp://) et les adresses de portefeuille
- Exécuter avec strace dans un sandbox pour observer les connexions réseau (connexion au pool de minage)
- Importer dans Ghidra pour identifier l'algorithme de minage et l'extraction de configuration
- Vérifier les mécanismes de persistance (crontab, service systemd, clés SSH)
- Documenter tous les IOCs, y compris l'adresse du pool, le portefeuille, le C2 pour les mises à jour et les artefacts de persistance
Pièges à éviter :
- Exécuter
lddsur un malware en dehors d'un sandbox (ldd peut exécuter du code dans le binaire) - Ne pas vérifier l'architecture ARM/MIPS avant de tenter une exécution x86_64
- Oublier les scripts compagnons (.sh files) qui peuvent gérer la persistance et le nettoyage
- Ignorer le vecteur d'accès initial (comment le mineur a été déployé : force brute SSH, exploitation web, évasion de conteneur)
Format de Sortie
RAPPORT D'ANALYSE DE MALWARE ELF LINUX
=========================================
Fichier : /tmp/.X11-unix/.rsync
SHA-256 : e3b0c44298fc1c149afbf4c8996fb924...
Type : ELF 64-bit LSB executable, x86-64
Liaison : Lié statiquement (toutes les bibliothèques embarquées)
Strip : Oui
Taille : 2,847,232 octets
Packer : UPX 3.96 (dépaqueté pour analyse)
CLASSIFICATION
Famille : XMRig Cryptominer (modifié)
Variante : Build personnalisé avec mécanisme de mise à jour C2
FONCTIONNALITÉ
[*] Minage XMR (Monero) via algorithme RandomX
[*] Connexion au pool Stratum pour soumission de travail
[*] Check-in C2 pour mises à jour de configuration
[*] Masquage du nom de processus (argv[0] = "[kworker/0:0]")
[*] Suppression des processus concurrents (tue les autres mineurs)
[*] Injection de clés SSH pour réaccès
INDICATEURS RÉSEAU
Pool de minage : stratum+tcp://pool.minexmr[.]com:4444
Serveur C2 : hxxp://update.malicious[.]com/config
Portefeuille : 49jZ5Q3b...Monero_Wallet_Address...
PERSISTANCE
[1] Entrée crontab : */5 * * * * /tmp/.X11-unix/.rsync
[2] Clé SSH ajoutée à /root/.ssh/authorized_keys
[3] Service systemd : /etc/systemd/system/rsync-daemon.service
[4] Modification de /etc/ld.so.preload pour masquage de processus
MASQUAGE DE PROCESSUS
LD_PRELOAD : /usr/lib/.libsystem.so
Crochetage : readdir() pour cacher /tmp/.X11-unix/.rsync de ls
Crochetage : fopen() pour cacher de la lecture de /proc/*/maps