MENASEC

The macro that never spawns a child of Word: detecting WMI and COM launches from Office

The standard malicious-macro rule watches for winword.exe spawning cmd or PowerShell. A macro that launches its payload through WMI or a shell COM object breaks that parent-child link on purpose. Here is how to detect it without depending on Office being the parent.

MENASEC Published 9 Jun 2026

The first detection almost everyone writes for malicious documents is a parent-child rule: winword.exe, excel.exe, or powerpnt.exe spawning cmd.exe, powershell.exe, wscript.exe, mshta.exe, or one of the usual living-off-the-land binaries. It is a good rule. It catches a lot. It also has a bypass that has been in tradecraft for years, and I still meet teams whose only macro detection is that single parent-child rule, so it is worth writing up again with current telemetry. The trick is simple to state: do not let Office be the parent.

I tested these against Office 2021 on Windows 11 23H2, Sysmon 15, and Defender for Endpoint, with the ASR rules in audit mode so I could watch what would have been blocked.

The detection this walks around

The standard rule assumes the payload process descends from the Office process, because when a VBA macro calls Shell() or WScript.Shell.Run, it does. Ancestry is winword.exe to cmd.exe, clean and easy to catch. The macro author’s problem is that this exact chain is what everyone alerts on, so the interesting variants hand the process creation to a different Windows component and let that component be the parent instead. Two routes do this well, and neither one produces a child of Office.

Route one: WMI, where the parent is WmiPrvSE.exe

VBA can reach WMI directly. A macro doing the equivalent of GetObject("winmgmts:").Get("Win32_Process").Create("cmd.exe /c ...") asks the WMI service to create the process, and WMI’s provider host does the spawning. So the new process descends from C:\Windows\System32\wbem\WmiPrvSE.exe, not from Word. Your parent-child rule sees nothing, because Word never spawned anything.

The catch is that WmiPrvSE.exe spawning cmd.exe or powershell.exe on a workstation is itself abnormal. WMI is management plumbing; on a normal user endpoint the provider host has no reason to launch an interactive shell. So the detection inverts: instead of Office-as-parent, you hunt WmiPrvSE.exe-as-parent for the same set of child images, via Sysmon Event ID 1. Correlate that with a WINWORD.EXE process that opened in the same window and you have reconstructed the macro without ever seeing Word spawn a child. This maps to T1047, and the Microsoft-Windows-WMI-Activity/Operational log (Event IDs 5857 and 5860) gives you a second angle on which provider ran and what it did.

Route two: shell COM objects, where the parent is explorer.exe

The second route uses COM. A couple of shell objects, ShellWindows and ShellBrowserWindow, can be instantiated from a macro and then used to call ShellExecute. The process that actually launches the payload in that case is explorer.exe, because that is what hosts those objects. Same outcome as the WMI route, different unexpected parent: now it is explorer.exe spawning your shell, and Word is nowhere in the tree. This is inter-process communication abuse, T1559.001, and it is the same family of shell-COM objects that also turns up in DCOM lateral movement, so a rule here earns its keep in two places.

I had this one wrong for a while, honestly. I assumed explorer.exe spawning cmd.exe was too noisy to alert on, because users do launch things from Explorer. It is not, if you scope it: users launch GUI applications and installers from Explorer, they very rarely launch cmd.exe or powershell.exe with a command line that includes an encoded blob or a download cradle. Scope on the child’s command line, not just its image, and the false-positive rate collapses.

Detections that don’t care who the parent is

The durable approach is to stop keying on the parent at all. Two things help. First, an Office process that runs a macro loads the VBA runtime, VBE7.DLL; a Sysmon Event ID 7 image-load rule for VBE7.dll into an Office process tells you a macro ran, independent of what it then did, and that becomes your correlation anchor. Second, hunt the child by behavior: any cmd.exe or powershell.exe whose command line carries a download cradle, an encoded command, or a call out to a LOLBin, regardless of parent, sitting close in time to a macro-active Office process. Ancestry becomes corroboration instead of the whole rule. That is the same idea behind designing detections around abnormal child processes generally, which pairs well with this one.

There is a timing detail that makes the correlation reliable. Whichever route the macro takes, the unexpected parent, WmiPrvSE.exe or explorer.exe, spawns the child within a second or two of the Office process going macro-active, because the whole point is a single automated chain from document-open to payload. So the anchor is not just “a macro ran” and “a weird parent spawned a shell” existing somewhere in the logs; it is those two events landing on the same host inside a tight window. That window is what separates the malicious chain from the genuinely coincidental case of WMI or Explorer doing normal work minutes apart, and it is the single knob I tune the most when a new environment produces noise.

This whole class is user execution of a malicious file, T1204.002, with VBA as the execution mechanism (T1059.005). Knowing that the initial-access artifact is the document while the execution is hidden one hop away is the mental model that keeps you from trusting the parent field, and it lines up with how I think about initial-access and execution evidence more broadly.

Belt and suspenders

Detection is half of it. The attack surface reduction rules in Defender give you prevention that covers these routes, but you have to pick the right ones. “Block all Office applications from creating child processes” does not stop the WMI or COM variants, because the child is not a child of Office; that is the entire point of the technique. The rules that do bite are “Block Win32 API calls from Office macros” and “Block process creations originating from PSExec and WMI commands,” the second one catching route one specifically. Turn them on in audit first, watch what they would have blocked for a couple of weeks, then enforce. The audit data on its own sometimes surfaces a macro nobody knew was running inside a legitimate business process, which you want to find before you enforce, not after.

Stop trusting the parent field. The interesting macros make sure it lies to you.

detection-engineeringthreat-huntingmalicious-macrowmiinitial-access