← Back to SOC feed Coverage →

Anomalous .NET runtime loading for fileless payload

kql MEDIUM Azure-Sentinel
T1562.001T1055
DeviceImageLoadEvents
huntingmicrosoftofficial
This rule was pulled from an open-source repository and enriched with AI. Validate in a test environment before deploying to production.
View original rule at Azure-Sentinel →
Retrieved: 2026-05-21T23:00:01Z · Confidence: medium

Hunt Hypothesis

Adversaries may be leveraging anomalous .NET runtime loading in writable paths to execute fileless payloads and evade detection through in-memory code injection. SOC teams should proactively hunt for this behavior in Azure Sentinel to identify potential malware activity that bypasses traditional file-based detection mechanisms.

KQL Query

// -----------------------------------------------------------------------------
// DETECTION STRATEGY: ETW-Patching Resistant .NET In-Memory Execution
// 
// THE MECHANIC: Advanced malware (like Kazuar) often executes .NET payloads 
// entirely in memory to avoid disk-based antivirus scans. To hide this execution 
// from EDRs, the malware patches Event Tracing for Windows (ETW) in user-mode 
// (e.g., overwriting ntdll.dll!EtwEventWrite with a return instruction). This blinds 
// the EDR, preventing it from seeing the standard 'ClrUnbackedModuleLoaded' 
// events that usually trigger memory execution alerts.
//
// THE RESILIENCE: While user-mode ETW can be easily patched by malware running 
// with standard privileges, the malware CANNOT hide the physical loading of the 
// .NET runtime engine (CLR) DLLs themselves. DLL loads trigger kernel-level 
// callbacks (PsSetLoadImageNotifyRoutine) which user-mode malware cannot intercept. 
// This query relies exclusively on DeviceImageLoadEvents (kernel-driven telemetry) 
// to detect when native Windows tools (LOLBins) or untrusted binaries running from 
// user-writable paths unexpectedly load the .NET execution engine. By shifting 
// detection to the kernel-level prerequisite of the attack, we render the user-mode 
// ETW patch irrelevant.
// -----------------------------------------------------------------------------

// Define a list of native Windows binaries (LOLBins) that are written in C/C++.
// Under normal circumstances, these native tools have no legitimate reason to boot 
// up the .NET runtime. If they load 'clr.dll' or 'mscoree.dll', it is a highly reliable 
// indicator that they have been hijacked (e.g., via malicious COM object instantiation) 
// to host a fileless .NET payload.

// Note: Binaries like powershell.exe, csc.exe, or msbuild.exe are built on or deeply integrated with
// .NET, so loading clr.dll is perfectly normal for them.
let AnomalousLOLBins = dynamic([
  // Tier 1: Most Heavily Abused Processes
  "rundll32.exe", "regsvr32.exe", "mshta.exe", "dllhost.exe", "svchost.exe", "spoolsv.exe", "werfault.exe", "explorer.exe",
  // Tier 2: Scripting & Automation Hosts
  "wscript.exe", "cscript.exe", "wmic.exe", "msiexec.exe",
  // Tier 3: Admin & Setup Utilities
  "odbcconf.exe", "control.exe", "cmstp.exe", "certutil.exe"
]);

// Base Query: Look for the .NET Execution Engine DLLs being loaded into memory
DeviceImageLoadEvents
// STEP 1: Identify processes loading the .NET Common Language Runtime (CLR) engines.
// 'mscoree.dll'   -> The traditional .NET execution engine.
// 'clr.dll'       -> The core .NET framework runtime.
// 'mscorwks.dll'  -> Legacy .NET workstation runtime.
// 'coreclr.dll'   -> The modern .NET Core runtime.
| where FileName in~ ("clr.dll", "mscoree.dll", "mscorwks.dll", "coreclr.dll")


// STEP 2: Apply Behavioral Filters to isolate malicious injection/loading.
// We use a strict Whitelist approach for paths. We only trust strict, Admin-secured directories.
// By using regex anchored to the start of the string (^), we prevent attackers from 
// bypassing the rule by creating a fake "Program Files" folder inside a user-writable 
// directory (e.g., C:\Users\Public\Program Files\malware.exe).

| extend IsTrustedPath = InitiatingProcessFolderPath matches regex @"^[a-zA-Z]:\\(?:Program Files|Program Files \(x86\)|Windows)(?:\\|$)"


// STEP 2: Apply Behavioral Filters to isolate malicious injection/loading.
| where 
  // CONDITION A: A native Windows LOLBin is suddenly loading the .NET engine.
  (InitiatingProcessFileName in~ (AnomalousLOLBins))
  or 
  // CONDITION B: An executable running from ANY untrusted, user-writable directory 
  // (AppData, Temp, PerfLogs, etc.) is loading the .NET engine.
  (not(IsTrustedPath))

// EXCLUSION: Filter out poorly behaved legitimate software (like user-context auto-updaters) 
// by ensuring the binary's internal version metadata does not belong to a trusted software vendor.
// Note: Schema recommends using SHA1 over SHA256 as it is more reliably populated.
// Insert legitimate internal tool hashes or signer here if they legitimately run .NET from Temp/AppData.
// | where InitiatingProcessSHA1 !in~ ("<Legit_SHA1_1>", "<Legit_SHA1_2>")
// | where InitiatingProcessVersionInfoCompanyName !in~ ( "Microsoft Corporation", "Google LLC", "Google Inc", "Cisco Systems, Inc.", "Intel Corporation" )

// STEP 3: Format the output for triage.
// We surface the Command Line, Folder Path, and SHA1 hash for immediate context.
| extend ProcessIdString = tostring(InitiatingProcessId)
| project 
  Timestamp,
  DeviceName, 
  ActionType,
  LoadedDll = FileName, 
  InitiatingProcessAccountDomain,
  InitiatingProcessAccountName,
  InitiatingProcessFileName, 
  InitiatingProcessFolderPath, 
  InitiatingProcessCommandLine, 
  ProcessIdString,
  InitiatingProcessParentFileName,
  InitiatingProcessVersionInfoCompanyName,
  InitiatingProcessSHA1
| project-reorder 
  Timestamp,
  DeviceName,
  InitiatingProcessAccountDomain,
  InitiatingProcessAccountName,
  InitiatingProcessFileName,
  InitiatingProcessCommandLine,
  LoadedDll,
  InitiatingProcessFolderPath,
  InitiatingProcessParentFileName

Analytic Rule Definition

id: 2df3fa1f-d573-4e0a-82f2-da62d3f2973f
name: Anomalous .NET runtime loading for fileless payload
description: |
  Identifies native processes or binaries in writable paths loading .NET runtimes. This suggests in-memory code injection and ETW patching used by malware to execute code while evading detection by security tools.

description-detailed: |
  Identifies native Windows binaries or processes in user-writable folders that unexpectedly load the .NET runtime engine. This activity is anomalous because these processes are not built on .NET and typically do not require these files to function. Malware uses this technique to execute malicious code entirely in memory, often while attempting to disable security logging (ETW patching) to remain invisible. Legitimate .NET applications usually run from secure directories like Program Files and are digitally signed by known vendors.
  References:
  https://www.microsoft.com/en-us/security/blog/2026/05/14/kazuar-anatomy-of-a-nation-state-botnet/
  https://r136a1.dev/2026/01/14/command-and-evade-turlas-kazuar-v3-loader/

requiredDataConnectors:
  - connectorId: MicrosoftThreatProtection
    dataTypes:
      - DeviceImageLoadEvents
tactics:
  - DefenseEvasion
  - Execution
relevantTechniques:
  - T1562.001
  - T1055
query: |
  // -----------------------------------------------------------------------------
  // DETECTION STRATEGY: ETW-Patching Resistant .NET In-Memory Execution
  // 
  // THE MECHANIC: Advanced malware (like Kazuar) often executes .NET payloads 
  // entirely in memory to avoid disk-based antivirus scans. To hide this execution 
  // from EDRs, the malware patches Event Tracing for Windows (ETW) in user-mode 
  // (e.g., overwriting ntdll.dll!EtwEventWrite with a return instruction). This blinds 
  // the EDR, preventing it from seeing the standard 'ClrUnbackedModuleLoaded' 
  // events that usually trigger memory execution alerts.
  //
  // THE RESILIENCE: While user-mode ETW can be easily patched by malware running 
  // with standard privileges, the malware CANNOT hide the physical loading of the 
  // .NET runtime engine (CLR) DLLs themselves. DLL loads trigger kernel-level 
  // callbacks (PsSetLoadImageNotifyRoutine) which user-mode malware cannot intercept. 
  // This query relies exclusively on DeviceImageLoadEvents (kernel-driven telemetry) 
  // to detect when native Windows tools (LOLBins) or untrusted binaries running from 
  // user-writable paths unexpectedly load the .NET execution engine. By shifting 
  // detection to the kernel-level prerequisite of the attack, we render the user-mode 
  // ETW patch irrelevant.
  // -----------------------------------------------------------------------------
  
  // Define a list of native Windows binaries (LOLBins) that are written in C/C++.
  // Under normal circumstances, these native tools have no legitimate reason to boot 
  // up the .NET runtime. If they load 'clr.dll' or 'mscoree.dll', it is a highly reliable 
  // indicator t

Required Data Sources

Sentinel TableNotes
DeviceImageLoadEventsEnsure this data connector is enabled

MITRE ATT&CK Context

References

False Positive Guidance

Original source: https://github.com/Azure/Azure-Sentinel/blob/main/Hunting Queries/Microsoft 365 Defender/Defense evasion/AnomalousNETRuntimeFilelessInjection.yaml