Communitygithub.com

analyse-forensique-pst-outlook

Analyser les fichiers PST et OST Microsoft Outlook avec libpff et pst-utils pour extraire le contenu des messages, en-têtes, pièces jointes, éléments supprimés et métadonnées MAPI, y compris la récupération d'éléments du dossier Éléments récupérables. Utile lors d'enquêtes judiciaires de courrier électronique, d'e-discovery ou de réponse à incident nécessitant la reconstruction des schémas de communication ou le traçage du routage des messages depuis des archives Outlook.

Qu'est-ce que analyse-forensique-pst-outlook ?

Cette compétence permet d'analyser les fichiers PST et OST d'Outlook dans un cadre forensique. Elle utilise des outils open source comme libpff et pypff pour extraire les emails, les pièces jointes, les en-têtes de transport, et les éléments supprimés, y compris ceux du dossier Éléments récupérables. Elle fournit des scripts Python complets pour automatiser l'analyse, générer des rapports JSON détaillés et exporter les pièces jointes. Idéale pour les enquêtes de sécurité, l'e-discovery et la réponse à incident, elle prend en charge les formats Unicode et ANSI et produit des indicateurs de compromission comme les en-têtes d'email frauduleux et les indicateurs d'exfiltration de données.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/mukul975/Anthropic-Cybersecurity-Skills/tree/main/skills/analyzing-outlook-pst-for-email-forensics

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Analyse des fichiers PST Outlook pour la forensique des courriels

Vue d'ensemble

Les fichiers PST (Personal Storage Table) et OST (Offline Storage Table) de Microsoft Outlook sont des sources de preuves critiques dans les enquêtes de criminalistique numérique. Les fichiers PST stockent les messages électroniques, les événements de calendrier, les contacts, les tâches et les notes dans un format binaire propriétaire basé sur le système de propriétés MAPI (Messaging Application Programming Interface). L'analyse forensique de ces fichiers permet de récupérer les courriels supprimés (à partir du dossier Éléments récupérables), d'extraire les en-têtes des courriels pour tracer les routes des messages, d'analyser les pièces jointes pour détecter des logiciels malveillants ou des données exfiltrées, et de reconstruire les schémas de communication. Les fichiers PST modernes utilisent le format Unicode avec des pages de 4 Ko et peuvent atteindre 50 Go, tandis que le format ANSI hérité est limité à 2 Go.

Quand l'utiliser

  • Lors d'enquêtes sur des incidents de sécurité nécessitant l'analyse forensique de fichiers PST Outlook
  • Lors de l'élaboration de règles de détection ou de requêtes de chasse aux menaces pour ce domaine
  • Lorsque les analystes SOC ont besoin de procédures structurées pour ce type d'analyse
  • Lors de la validation de la couverture de surveillance de sécurité pour les techniques d'attaque associées

Prérequis

  • libpff/pffexport (analyseur PST open source)
  • Python 3.8+ avec les bibliothèques pypff ou libratom
  • MailXaminer, Forensic Email Collector, ou SysTools PST Forensics (commercial)
  • Microsoft Outlook (optionnel, pour un accès PST natif)
  • Espace disque suffisant pour le contenu extrait

Emplacements des fichiers PST

SourceChemin
Outlook 2016+ par défaut%USERPROFILE%\Documents\Outlook Files*.pst
Outlook hérité%LOCALAPPDATA%\Microsoft\Outlook*.pst
Cache OST%LOCALAPPDATA%\Microsoft\Outlook*.ost
Archive%USERPROFILE%\Documents\Outlook Files\archive.pst

Analyse avec des outils open source

libpff / pffexport

# Exporter tous les éléments d'un fichier PST
pffexport -m all evidence.pst -t exported_pst

# Exporter uniquement les messages électroniques
pffexport -m items evidence.pst -t exported_emails

# Exporter les éléments récupérés/supprimés
pffexport -m recovered evidence.pst -t recovered_items

# Obtenir les informations du fichier PST
pffinfo evidence.pst

Analyse PST avec Python

import pypff
import os
import json
import hashlib
import email
import sys
from datetime import datetime
from collections import defaultdict


class PSTForensicAnalyzer:
    """Analyse forensique des fichiers PST/OST Outlook."""

    def __init__(self, pst_path: str, output_dir: str):
        self.pst_path = pst_path
        self.output_dir = output_dir
        os.makedirs(output_dir, exist_ok=True)
        self.pst = pypff.file()
        self.pst.open(pst_path)
        self.messages = []
        self.attachments = []
        self.stats = defaultdict(int)

    def process_folder(self, folder, folder_path: str = ""):
        """Parcourt récursivement les dossiers PST et extrait les messages."""
        folder_name = folder.name or "Racine"
        current_path = f"{folder_path}/{folder_name}" if folder_path else folder_name

        for i in range(folder.number_of_sub_messages):
            try:
                message = folder.get_sub_message(i)
                msg_data = self.extract_message(message, current_path)
                if msg_data:
                    self.messages.append(msg_data)
                    self.stats["total_messages"] += 1
            except Exception as e:
                self.stats["parse_errors"] += 1

        for i in range(folder.number_of_sub_folders):
            try:
                subfolder = folder.get_sub_folder(i)
                self.process_folder(subfolder, current_path)
            except Exception:
                continue

    def extract_message(self, message, folder_path: str) -> dict:
        """Extrait les métadonnées forensiques d'un seul message électronique."""
        msg_data = {
            "folder": folder_path,
            "subject": message.subject or "",
            "sender": message.sender_name or "",
            "sender_email": "",
            "creation_time": str(message.creation_time) if message.creation_time else None,
            "delivery_time": str(message.delivery_time) if message.delivery_time else None,
            "modification_time": str(message.modification_time) if message.modification_time else None,
            "has_attachments": message.number_of_attachments > 0,
            "attachment_count": message.number_of_attachments,
            "body_size": len(message.plain_text_body or b""),
            "html_size": len(message.html_body or b""),
        }

        # Extraire les en-têtes de transport pour l'analyse du routage
        headers = message.transport_headers
        if headers:
            msg_data["headers_present"] = True
            msg_data["headers_size"] = len(headers)
            # Analyser les en-têtes clés
            parsed = email.message_from_string(headers)
            msg_data["from_header"] = parsed.get("From", "")
            msg_data["to_header"] = parsed.get("To", "")
            msg_data["date_header"] = parsed.get("Date", "")
            msg_data["message_id"] = parsed.get("Message-ID", "")
            msg_data["x_originating_ip"] = parsed.get("X-Originating-IP", "")
            msg_data["received_headers"] = parsed.get_all("Received", [])

        # Traiter les pièces jointes
        for j in range(message.number_of_attachments):
            try:
                attachment = message.get_attachment(j)
                att_data = {
                    "message_subject": msg_data["subject"],
                    "name": attachment.name or f"attachment_{j}",
                    "size": attachment.size,
                    "content_type": "",
                }
                self.attachments.append(att_data)
                self.stats["total_attachments"] += 1
            except Exception:
                continue

        return msg_data

    def save_attachments(self, max_size_mb: int = 100):
        """Exporte les pièces jointes sur le disque pour analyse."""
        att_dir = os.path.join(self.output_dir, "attachments")
        os.makedirs(att_dir, exist_ok=True)

        root = self.pst.get_root_folder()
        self._save_attachments_recursive(root, att_dir, max_size_mb)

    def _save_attachments_recursive(self, folder, att_dir, max_size_mb):
        for i in range(folder.number_of_sub_messages):
            try:
                message = folder.get_sub_message(i)
                for j in range(message.number_of_attachments):
                    att = message.get_attachment(j)
                    if att.size and att.size < max_size_mb * 1024 * 1024:
                        name = att.name or f"inconnu_{i}_{j}"
                        safe_name = "".join(c if c.isalnum() or c in ".-_" else "_" for c in name)
                        path = os.path.join(att_dir, safe_name)
                        try:
                            data = att.read_buffer(att.size)
                            with open(path, "wb") as f:
                                f.write(data)
                        except Exception:
                            continue
            except Exception:
                continue

        for i in range(folder.number_of_sub_folders):
            try:
                self._save_attachments_recursive(folder.get_sub_folder(i), att_dir, max_size_mb)
            except Exception:
                continue

    def generate_report(self) -> str:
        """Génère un rapport complet d'analyse forensique PST."""
        root = self.pst.get_root_folder()
        self.process_folder(root)

        report = {
            "analysis_timestamp": datetime.now().isoformat(),
            "pst_file": self.pst_path,
            "pst_size_bytes": os.path.getsize(self.pst_path),
            "statistics": dict(self.stats),
            "messages": self.messages[:500],
            "attachments": self.attachments[:200],
        }

        report_path = os.path.join(self.output_dir, "pst_forensic_report.json")
        with open(report_path, "w") as f:
            json.dump(report, f, indent=2, default=str)

        print(f"[*] Nombre total de messages : {self.stats['total_messages']}")
        print(f"[*] Nombre total de pièces jointes : {self.stats['total_attachments']}")
        print(f"[*] Erreurs d'analyse : {self.stats['parse_errors']}")
        return report_path

    def close(self):
        self.pst.close()


def main():
    if len(sys.argv) < 3:
        print("Utilisation : python process.py <fichier_pst> <répertoire_sortie>")
        sys.exit(1)
    analyzer = PSTForensicAnalyzer(sys.argv[1], sys.argv[2])
    analyzer.generate_report()
    analyzer.close()


if __name__ == "__main__":
    main()

Analyse des en-têtes de courrier électronique

En-têtes clés pour l'investigation forensique :

En-têteValeur forensique
ReceivedChaîne de routage des messages (lire de bas en haut)
X-Originating-IPAdresse IP réelle de l'expéditeur
Message-IDIdentifiant unique pour la corrélation
DateHorodatage d'envoi
Return-PathAdresse de rebond (peut différer de From)
DKIM-SignatureSignature d'authentification de domaine
Authentication-ResultsRésultats de vérification SPF, DKIM, DMARC
X-MailerClient de messagerie utilisé

Références

Exemple de sortie

$ pffexport /evidence/jsmith_archive.pst -t /analysis/pst_output

pffexport 20231205 - libpff Outil d'exportation PST/OST
=================================================
Entrée : /evidence/jsmith_archive.pst (2,3 Go)

Exportation du contenu PST...
  Dossiers :       45
  Messages :       12 456
  Pièces jointes : 3 234
  Contacts :       567
  Calendrier :     234
  Tâches :         89

Exportation terminée en 3 min 42 s.

$ python3 pst_analyzer.py /analysis/pst_output /analysis/email_report

Rapport d'analyse forensique PST
==============================
Source : jsmith_archive.pst ([email protected])
Plage de dates : 2023-06-01 à 2024-01-18

--- Statistiques de la boîte aux lettres ---
  Total des courriels :       12 456
  Envoyés :               4 567
  Reçus :                 7 889
  Avec pièces jointes :   3 234
  Supprimés (récupérés) : 234

--- Courriels de phishing / suspects ---
Courriel n°8923
  Date :        2024-01-15 14:30:22 UTC
  De :        "IT Support" <[email protected]>
  À :          [email protected]
  Objet :     Urgent : Réinitialisation de mot de passe requise
  En-têtes :
    Return-Path :    [email protected]
    X-Originating-IP : 203.0.113.55
    Received :       from mail-relay.c0rporate-help.com (203.0.113.55)
    SPF :            ÉCHEC (domaine c0rporate-help.com)
    DKIM :           AUCUN
    DMARC :          ÉCHEC
  Pièces jointes :
    - Password_Reset_Form.xlsm (245 Ko) SHA-256 : 7a3b8c9d...e1f2a3b4
  Aperçu du corps : "Cher employé, votre mot de passe expirera dans 24 heures.
                  Veuillez ouvrir le formulaire ci-joint pour réinitialiser vos identifiants..."

--- Indicateurs d'exfiltration de données ---
Courriel n°9102
  Date :        2024-01-16 03:15:45 UTC
  De :        [email protected]
  À :          [email protected]
  Objet :     (sans objet)
  Pièces jointes :
    - archive_part1.7z (24,5 Mo) - chiffré
    - archive_part2.7z (24,5 Mo) - chiffré

Courriel n°9103
  Date :        2024-01-16 03:18:22 UTC
  De :        [email protected]
  À :          [email protected]
  Objet :     Re :
  Pièces jointes :
    - archive_part3.7z (18,2 Mo) - chiffré

--- Correspondances de mots-clés ---
  "confidentiel" :     45 courriels
  "mot de passe" :      23 courriels
  "transfert" :         12 courriels
  "démission" :         3 courriels
  "supprimer les preuves" : 1 courriel (Courriel n°9200, 2024-01-17 22:30:00 UTC)

Résumé :
  Courriels de phishing détectés :    1 (vecteur de compromission initial)
  Courriels envoyés suspects :       5 (vers des comptes personnels avec pièces jointes)
  Pièces jointes chiffrées :         3 (67,2 Mo au total - exfiltration possible)
  Rapport : /analysis/email_report/pst_forensic_report.json

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

abusing-dpapi-for-credential-access

Extract and decrypt Windows DPAPI-protected secrets (Credential Manager, browser logins/cookies, Wi-Fi credentials, KeePass keys) online or offline using SharpDPAPI, SharpChrome, Mimikatz, or Impacket

abusing-shadow-credentials-for-privesc

Take over Active Directory accounts by writing attacker-controlled public keys to msDS-KeyCredentialLink (Shadow Credentials) with pyWhisker, Whisker, or Certipy, then authenticate via PKINIT to recover the target

achieving-cmmc-level-2-compliance

>-

acquiring-disk-image-with-dd-and-dcfldd

Create forensically sound bit-for-bit disk images with dd or dcfldd on a Linux forensic workstation, preserving evidence integrity through hash verification (MD5/SHA) during acquisition. Use when imaging a suspect drive, USB device, or memory card for investigation, preserving volatile disk evidence during incident response, or producing a verified copy for legal or law-enforcement proceedings before any destructive analysis.

analyzing-active-directory-acl-abuse

Detect dangerous ACL misconfigurations in Active Directory using ldap3

analyzing-android-malware-with-apktool

Perform static analysis of Android APK malware using apktool for resource decompilation, jadx for Java source recovery, and androguard for manifest inspection, dangerous permission-combination detection, and identification of obfuscated code, dynamic code loading, and reflection-based API calls. Use to statically triage a suspicious APK without executing it or to build mobile malware detection rules.

analyzing-api-gateway-access-logs

Parses API Gateway access logs (AWS API Gateway, Kong, Nginx) to detect

analyzing-apt-group-with-mitre-navigator

Query ATT&CK data with attackcti, mitreattack-python, and stix2, then build MITRE ATT&CK Navigator layers and multi-layer heatmap overlays mapping one or more APT groups

analyzing-azure-activity-logs-for-threats

Queries Azure Monitor activity logs and sign-in logs via azure-monitor-query

analyzing-bootkit-and-rootkit-samples

Analyzes bootkit and advanced rootkit malware infecting the Master

analyzing-browser-forensics-with-hindsight

Parse Chromium-based browser databases with Hindsight to extract and correlate browsing history, downloads, cookies, cached content, autofill data, saved passwords, and extensions from Chrome, Edge, Brave, Opera, and Vivaldi into a unified timeline (XLSX, JSON, or SQLite output). Use during incident response, insider-threat investigations, or criminal cases when you need to reconstruct a user

analyzing-campaign-attribution-evidence

Systematically evaluate cyber-campaign evidence to attribute an operation to a threat actor, using the Diamond Model and Analysis of Competing Hypotheses (ACH) to weigh infrastructure overlaps, TTP consistency, malware code similarity, and timing/language artifacts into confidence-weighted attribution assessments. Use when an incident investigation needs a defensible attribution confidence level.

analyzing-certificate-transparency-for-phishing

Monitor Certificate Transparency logs using crt.sh and Certstream to

analyzing-cloud-storage-access-patterns

Detect abnormal access in AWS S3, GCS, and Azure Blob Storage by analyzing CloudTrail Data Events, GCS audit logs, and Azure Storage Analytics for after-hours bulk downloads, new-IP access, and API-call spikes (e.g. GetObject) via statistical baselines and time-series anomaly detection. Use when investigating suspected cloud data exfiltration or building related detection rules.

analyzing-cobalt-strike-beacon-configuration

Extract and analyze Cobalt Strike beacon configuration from PE files

analyzing-cobaltstrike-malleable-c2-profiles

Parse and analyze Cobalt Strike Malleable C2 profiles with dissect.cobaltstrike (profiles and beacon-payload configs) and pyMalleableC2 (AST parsing) to extract HTTP/DNS transforms, URIs, headers, sleep/jitter, and injection behavior, then generate network detection signatures. Use when reverse-engineering a captured malleable profile or building detections against Cobalt Strike Beacon traffic.

analyzing-command-and-control-communication

Analyzes malware C2 communication over HTTP, HTTPS, DNS, and custom

analyzing-cyber-kill-chain

Analyzes intrusion activity against the Lockheed Martin Cyber Kill Chain

analyzing-disk-image-with-autopsy

Perform comprehensive forensic analysis of raw (dd), E01, or AFF disk images with Autopsy and The Sleuth Kit, recovering deleted files, examining metadata and embedded artifacts, keyword searching, and building investigation timelines with visual reports. Use for structured analysis of a forensic disk image or when stakeholders need visual reports from evidence.

analyzing-dns-logs-for-exfiltration

Analyzes DNS query logs to detect data exfiltration via DNS tunneling,

Skills associés