CLR profiler environment variable set in the registry
Matches the registry half of AN1319: a value written to one of the CLR profiling environment variables under an `Environment` key, which is how a system-wide or user-wide COR_PROFILER is made persistent. Setting COR_ENABLE_PROFILING to 1 and pointing COR_PROFILER at a CLSID (or, from .NET Framework 4 onward, pointing COR_PROFILER_PATH straight at a DLL on disk) causes the runtime to load that unmanaged DLL into every process that starts the CLR, which is the hijack this technique performs. Only the registry-backed scopes are visible here by definition — a process-scope COR_PROFILER set in memory by the parent that spawns the target never touches the registry and leaves no matching event. The value names are anchored with `endswith` beneath `\Environment\`, which covers the two scopes where `Environment` is a registry *key* and the COR_ name is a value beneath it: the machine-wide `HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment`, and the per-user `Environment` key that Sysmon writes as HKU followed by the account SID. The per-service scope is deliberately not covered and cannot be: under a Services key, `Environment` is itself a single REG_MULTI_SZ *value* whose data holds `COR_ENABLE_PROFILING=1` and friends, so `TargetObject` ends at `\Environment` with no COR_ name in it at all, and Sysmon renders multi-string data as binary rather than as readable text in `Details`. Catching that scope needs a separate rule against the value data, not another term here. MITRE names COR_ENABLE_PROFILING, COR_PROFILER and COR_PROFILER_PATH; the bitness-suffixed COR_PROFILER_PATH_32/_64 forms and the CORECLR_ equivalents that .NET Core and .NET 5+ read instead were added here, not taken from the analytic, because a modern host runs the CoreCLR names and a rule listing only the Framework ones would miss it entirely. Vocabulary, scope and prerequisites. The brief maps Security EventID 4657 onto the Sigma `registry_set` category, but that category is Sysmon-shaped: this rule is written in the Sysmon vocabulary, where `TargetObject` carries the full key-plus-value path in one field. Security 4657 splits the same information across `ObjectName` and `ObjectValueName`, so that feed needs a field mapping before this rule can match on it and enabling Audit Registry with a SACL on the Environment keys will not by itself make this rule fire. The analytic's other two halves are out of reach: correlating the registry write with the profiler DLL then loading into a .NET process, within MITRE's `TimeWindow` knob, is a Sysmon EventID 7 record and a cross-event join, and MITRE's `AllowedProfilers` and `ProfilerDllPaths` knobs would have to be applied against the `Details` field, which is left unconstrained here so a profiler DLL in any location is caught. Prerequisite: registry monitoring in a Sysmon configuration is an explicit allowlist of paths, and the Session Manager Environment key and the per-user Environment keys are not in every shipped configuration, so confirm they are in scope before reading an empty result as an absence of this technique. UNVERIFIED AS AUTHORED — derived from MITRE ATT&CK DET0479, not hand-written and not tested by its author. Any lab result is on this rule's own page.Full descriptionShow less
The detection
The 4 SIEM queries below are previews produced by Siemphony’s own translator, not pySigma, and none has been executed against a real backend — review before you deploy.
detection.yml
title: CLR profiler environment variable set in the registryid: 29c9f303-2b12-46b8-8a26-19806545969astatus: experimentaldescription: | Matches the registry half of AN1319: a value written to one of the CLR profiling environment variables under an `Environment` key, which is how a system-wide or user-wide COR_PROFILER is made persistent. Setting COR_ENABLE_PROFILING to 1 and pointing COR_PROFILER at a CLSID (or, from .NET Framework 4 onward, pointing COR_PROFILER_PATH straight at a DLL on disk) causes the runtime to load that unmanaged DLL into every process that starts the CLR, which is the hijack this technique performs. Only the registry-backed scopes are visible here by definition — a process-scope COR_PROFILER set in memory by the parent that spawns the target never touches the registry and leaves no matching event. The value names are anchored with `endswith` beneath `\Environment\`, which covers the two scopes where `Environment` is a registry *key* and the COR_ name is a value beneath it: the machine-wide `HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment`, and the per-user `Environment` key that Sysmon writes as HKU followed by the account SID. The per-service scope is deliberately not covered and cannot be: under a Services key, `Environment` is itself a single REG_MULTI_SZ *value* whose data holds `COR_ENABLE_PROFILING=1` and friends, so `TargetObject` ends at `\Environment` with no COR_ name in it at all, and Sysmon renders multi-string data as binary rather than as readable text in `Details`. Catching that scope needs a separate rule against the value data, not another term here. MITRE names COR_ENABLE_PROFILING, COR_PROFILER and COR_PROFILER_PATH; the bitness-suffixed COR_PROFILER_PATH_32/_64 forms and the CORECLR_ equivalents that .NET Core and .NET 5+ read instead were added here, not taken from the analytic, because a modern host runs the CoreCLR names and a rule listing only the Framework ones would miss it entirely. Vocabulary, scope and prerequisites. The brief maps Security EventID 4657 onto the Sigma `registry_set` category, but that category is Sysmon-shaped: this rule is written in the Sysmon vocabulary, where `TargetObject` carries the full key-plus-value path in one field. Security 4657 splits the same information across `ObjectName` and `ObjectValueName`, so that feed needs a field mapping before this rule can match on it and enabling Audit Registry with a SACL on the Environment keys will not by itself make this rule fire. The analytic's other two halves are out of reach: correlating the registry write with the profiler DLL then loading into a .NET process, within MITRE's `TimeWindow` knob, is a Sysmon EventID 7 record and a cross-event join, and MITRE's `AllowedProfilers` and `ProfilerDllPaths` knobs would have to be applied against the `Details` field, which is left unconstrained here so a profiler DLL in any location is caught. Prerequisite: registry monitoring in a Sysmon configuration is an explicit allowlist of paths, and the Session Manager Environment key and the per-user Environment keys are not in every shipped configuration, so confirm they are in scope before reading an empty result as an absence of this technique. UNVERIFIED AS AUTHORED — derived from MITRE ATT&CK DET0479, not hand-written and not tested by its author. Any lab result is on this rule's own page.references: - https://attack.mitre.org/techniques/T1574/012 - https://attack.mitre.org/detectionstrategies/DET0479author: Siemphony pipeline (machine-derived from MITRE ATT&CK v19.2)date: 2026-08-17tags: - attack.defense-evasion - attack.execution - attack.t1574.012logsource: category: registry_set product: windowsdetection: selection_profiler_env: TargetObject|endswith: - '\Environment\COR_ENABLE_PROFILING' - '\Environment\COR_PROFILER' - '\Environment\COR_PROFILER_PATH' - '\Environment\COR_PROFILER_PATH_32' - '\Environment\COR_PROFILER_PATH_64' - '\Environment\CORECLR_ENABLE_PROFILING' - '\Environment\CORECLR_PROFILER' - '\Environment\CORECLR_PROFILER_PATH' - '\Environment\CORECLR_PROFILER_PATH_32' - '\Environment\CORECLR_PROFILER_PATH_64' condition: selection_profiler_envfalsepositives: - "Application performance monitoring agents, which use this exact mechanism as their supported installation method and set the same values machine-wide at install time. Dynatrace OneAgent, the AppDynamics and New Relic .NET agents, the Datadog .NET tracer and Elastic APM all do this. On an estate rolling an APM agent out, this is the highest-volume source by a wide margin — one or more matches on every server in the wave — and is why the level is medium rather than high; allowlisting the agents' CLSIDs against MITRE's AllowedProfilers knob is what would justify raising it." - "Developer workstations running profiling and diagnostic tools that write a user-scope profiler: Visual Studio's performance profiler, JetBrains dotTrace and dotMemory, the Application Insights Profiler and the IIS diagnostics tooling. These fire under the interactive user's own SID whenever a profiling session is configured." - "Build agents running .NET code coverage, where OpenCover, altcover and the legacy Coverlet collector set CORECLR_ENABLE_PROFILING and CORECLR_PROFILER for the test run. On a shared agent this repeats on every pipeline execution." - "Uninstall and repair of any of the above, which rewrites the same values to clear them. A COR_ENABLE_PROFILING set back to 0 is a normal teardown and matches this rule identically to the enabling write."level: mediumSentinel · KQL
Run this as a search.
DeviceRegistryEvents| where (RegistryKey endswith "\\Environment\\COR_ENABLE_PROFILING" or RegistryKey endswith "\\Environment\\COR_PROFILER" or RegistryKey endswith "\\Environment\\COR_PROFILER_PATH" or RegistryKey endswith "\\Environment\\COR_PROFILER_PATH_32" or RegistryKey endswith "\\Environment\\COR_PROFILER_PATH_64" or RegistryKey endswith "\\Environment\\CORECLR_ENABLE_PROFILING" or RegistryKey endswith "\\Environment\\CORECLR_PROFILER" or RegistryKey endswith "\\Environment\\CORECLR_PROFILER_PATH" or RegistryKey endswith "\\Environment\\CORECLR_PROFILER_PATH_32" or RegistryKey endswith "\\Environment\\CORECLR_PROFILER_PATH_64")
Splunk · SPL
Run this as a search.
index=* (TargetObject="*\\Environment\\COR_ENABLE_PROFILING" OR TargetObject="*\\Environment\\COR_PROFILER" OR TargetObject="*\\Environment\\COR_PROFILER_PATH" OR TargetObject="*\\Environment\\COR_PROFILER_PATH_32" OR TargetObject="*\\Environment\\COR_PROFILER_PATH_64" OR TargetObject="*\\Environment\\CORECLR_ENABLE_PROFILING" OR TargetObject="*\\Environment\\CORECLR_PROFILER" OR TargetObject="*\\Environment\\CORECLR_PROFILER_PATH" OR TargetObject="*\\Environment\\CORECLR_PROFILER_PATH_32" OR TargetObject="*\\Environment\\CORECLR_PROFILER_PATH_64")Elastic · ES|QL
Run this as a search.
FROM logs-*| WHERE (TO_LOWER(registry.path) LIKE "*\\\\environment\\\\cor_enable_profiling" OR TO_LOWER(registry.path) LIKE "*\\\\environment\\\\cor_profiler" OR TO_LOWER(registry.path) LIKE "*\\\\environment\\\\cor_profiler_path" OR TO_LOWER(registry.path) LIKE "*\\\\environment\\\\cor_profiler_path_32" OR TO_LOWER(registry.path) LIKE "*\\\\environment\\\\cor_profiler_path_64" OR TO_LOWER(registry.path) LIKE "*\\\\environment\\\\coreclr_enable_profiling" OR TO_LOWER(registry.path) LIKE "*\\\\environment\\\\coreclr_profiler" OR TO_LOWER(registry.path) LIKE "*\\\\environment\\\\coreclr_profiler_path" OR TO_LOWER(registry.path) LIKE "*\\\\environment\\\\coreclr_profiler_path_32" OR TO_LOWER(registry.path) LIKE "*\\\\environment\\\\coreclr_profiler_path_64")
Wazuh · XML rule
Deploy to your manager — this is a rule, not a search.
<group name="sigma,windows,registry_set,"> <!-- Rule ids must be unique on your manager; 100000+ is the user range. --> <rule id="100000" level="7"> <!-- Set <if_sid> to the decoder/base rule for windows so this only evaluates relevant events. --> <field name="TargetObject" type="pcre2">(?i)(\\Environment\\COR_ENABLE_PROFILING$|\\Environment\\COR_PROFILER$|\\Environment\\COR_PROFILER_PATH$|\\Environment\\COR_PROFILER_PATH_32$|\\Environment\\COR_PROFILER_PATH_64$|\\Environment\\CORECLR_ENABLE_PROFILING$|\\Environment\\CORECLR_PROFILER$|\\Environment\\CORECLR_PROFILER_PATH$|\\Environment\\CORECLR_PROFILER_PATH_32$|\\Environment\\CORECLR_PROFILER_PATH_64$)</field> <description>CLR profiler environment variable set in the registry</description> <mitre> <id>T1574.012</id> </mitre> </rule></group>
Verdicts · reactions · comments
Community
Verdicts from engineers who actually deployed it, and the conversation around it.
Nobody has run this in a real environment and said what happened.
Verdicts from engineers who deployed it
0 castNo verdicts reported yet. The first one is worth more than the tenth — say what you ran it against.
Log in to report a verdict.
Log in to join the discussion.
No comments yet. Someone who deploys this will have something to say about it.