Microsoft Office offers several extension points that run code when an application starts or a trigger fires: global templates like Normal.dotm, STARTUP folders, COM and VSTO add-ins, native XLL and WLL add-ins, and Outlook rules, forms and home pages. Attackers use them to persist inside a trusted process, often after an initial macro or phishing foothold. Detection rests on file writes to the extension folders, add-in registry keys and unusual child processes of Office applications.
Signals at a Glance
| Signal | Where | ATT&CK |
|---|---|---|
| Normal.dotm or a file in Word STARTUP / Excel XLSTART written by a non-Office process | Sysmon 11, EDR file events | T1137.001 |
| New .wll or .xll file in an Office add-in or startup location | Sysmon 11 | T1137.006 |
| New COM add-in key under Office\<app>\Addins with LoadBehavior 3 | Sysmon 13 | T1137.006 |
| Outlook rule with a start-application action, or EnableUnsafeClientMailRules enabled | Registry, mailbox audit | T1137.005 |
| Outlook form or home-page registry changes, VbaProject.OTM present | Sysmon 11/13 | T1137.004 |
| WINWORD.EXE, EXCEL.EXE or OUTLOOK.EXE spawning shells, script hosts or loading unsigned DLLs | Sysmon 1, 7 | T1566.001 |
Templates, Startup Folders and Add-in Keys
A modified Normal.dotm executes its macros every time Word starts. Word legitimately rewrites that file when a user changes defaults, so the signal is a write by a process other than Word, or a macro-enabled template appearing in the STARTUP folders. Add-ins register under per-user keys that need no admin rights. This KQL covers both:
// KQL: Office extension files and add-in registrations
let extFiles = DeviceFileEvents
| where ActionType in ("FileCreated", "FileModified")
| where FolderPath has_any (@"\Microsoft\Templates", @"\Microsoft\Word\STARTUP",
@"\Microsoft\Excel\XLSTART", @"\Microsoft\AddIns")
| where FileName endswith ".dotm" or FileName endswith ".wll" or FileName endswith ".xll"
or FileName endswith ".xlam" or FileName endswith ".xla"
| where InitiatingProcessFileName !in~ ("WINWORD.EXE", "EXCEL.EXE")
| project Timestamp, DeviceName, Signal = "office_ext_file", Detail = FolderPath, FileName,
InitiatingProcessFileName, InitiatingProcessCommandLine;
let addinKeys = DeviceRegistryEvents
| where ActionType == "RegistryValueSet"
| where RegistryKey has @"\Microsoft\Office" and RegistryKey has @"\Addins\"
| where RegistryValueName in~ ("LoadBehavior", "Manifest")
| project Timestamp, DeviceName, Signal = "addin_key", Detail = RegistryKey, FileName = RegistryValueName,
InitiatingProcessFileName, InitiatingProcessCommandLine;
union extFiles, addinKeys
| order by Timestamp desc
// tune/validate: enterprise add-ins (PDF, CRM, Teams) register here; allowlist by ProgID and writer.
Outlook Rules, Forms and Fleet Inventory
Outlook persistence typically relies on a mailbox rule or custom form that runs when a message arrives. Microsoft disabled the start-application rule action and form scripting by default after public tooling made them practical, so attackers must re-enable them through registry settings. That makes the configuration changes a precise signal. Inventory add-ins directly to catch anything that predates your telemetry:
# PowerShell: inventory Office add-ins (per-user and per-machine) and key Outlook policy values
$roots = 'HKCU:\Software\Microsoft\Office',
'HKLM:\SOFTWARE\Microsoft\Office',
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Office'
foreach ($r in $roots) {
Get-ChildItem $r -Recurse -ErrorAction SilentlyContinue |
Where-Object { $_.PSPath -match '\\Addins\\[^\\]+$' } |
ForEach-Object {
$p = Get-ItemProperty $_.PSPath
[pscustomobject]@{ Key = $_.Name; LoadBehavior = $p.LoadBehavior; Manifest = $p.Manifest
FriendlyName = $p.FriendlyName }
}
}
Get-ChildItem 'HKCU:\Software\Microsoft\Office\*\Outlook\Security' -ErrorAction SilentlyContinue |
Get-ItemProperty | Select-Object PSPath, EnableUnsafeClientMailRules
# tune/validate: compare to a gold image; unknown ProgIDs with LoadBehavior 3 are the interesting set.
- Alert on
OUTLOOK.EXE,WINWORD.EXEorEXCEL.EXEspawningcmd.exe,powershell.exe,mshta.exeorwscript.exe, which covers rule, form and macro triggers alike. - Detect
EnableUnsafeClientMailRulesand Outlook form-security policy values being set outside Group Policy. - Review mailbox rules centrally with Exchange or Microsoft 365 audit logs and flag new rules that forward, delete or run an application.
- Reduce exposure with Group Policy: block macros from the internet, disable VBA in templates where unneeded, and restrict trusted locations and add-in installation.
Use the SigmaHQ Office persistence and Office child-process rules, Elastic’s Office template and Outlook detections, Splunk ESCU content, MITRE CAR analytics and Atomic Red Team tests for T1137, plus Microsoft’s documentation on Office policy settings. Baseline your own environment, because business add-ins and approved templates register legitimately.
Build Detections That Fire
Mjolnir Security helps blue teams turn threat intelligence into high-fidelity detections across endpoint, network, identity and cloud telemetry.
- Detection Engineering We build and tune detections mapped to ATT&CK from your own telemetry.
- Threat Hunting as a Service Hypothesis-driven hunts for the behaviours on this page.
- 24/7 Incident Response Containment when a detection fires. Call +1 833 403 5875.
Stay ahead of emerging threats. Get notified when we publish new intelligence reports and advisories.
Subscribe to Alerts