Skip to content

WDAC and Code Integrity events: 3076 and 3077

Reading the CodeIntegrity Operational log for application-control and driver-blocking evidence — audit blocks (3076) vs enforced blocks (3077), what they reveal about unsigned and untrusted code, and how they fit alongside AppLocker.

By Florian AmettePublished 3 {n} min read

Windows Defender Application Control (WDAC) and the underlying Code Integrity subsystem decide whether a binary or driver is allowed to load at all based on signing and policy. Its log is narrower than AppLocker's but deeper: it speaks to kernel-level trust, which makes it especially useful for catching unsigned drivers and BYOVD ("bring your own vulnerable driver") activity. This rounds out the endpoint-controls coverage.

Where it lives

The channel is Microsoft-Windows-CodeIntegrity/Operational. It logs regardless of whether a formal WDAC policy is deployed — base Code Integrity (and rules like the Microsoft vulnerable-driver blocklist) still record load decisions here.

The event IDs

IDMeaning
3076Code Integrity audit block — the file would have been blocked
3077Code Integrity enforced block — the file was blocked from loading
3033A file did not meet integrity requirements (load failed)
3089Signing information for a blocked/audited file

As with AppLocker, 3076 (audit) vs 3077 (enforce) mirrors "would block" vs "did block." The 3089 events carry the signature details for the file referenced by a 3076/3077 — so a block plus its 3089 tells you the file path, hash, and why trust failed (unsigned, revoked, not in policy).

Why it matters for DFIR

  • Unsigned / untrusted drivers. Code Integrity gates kernel drivers. A 3077 (or 3076 in audit) on a driver is high-signal — attackers load vulnerable or malicious drivers to disable EDR or gain kernel execution (BYOVD). A driver being blocked, or audited-but-allowed, tells you someone tried.
  • Unsigned user-mode code under WDAC. Where WDAC enforces user-mode rules, 3077 records blocked executables/DLLs that AppLocker policy might not cover.
  • Audit-mode reconnaissance value. Like AppLocker, WDAC is frequently deployed in audit mode first. In that mode 3076 logs everything that violates policy without stopping it — a ready list of untrusted code that ran.

What to hunt

  • 3076/3077 on drivers (.sys, paths under \Windows\System32\drivers\ or user-writable locations) — the BYOVD signal.
  • 3077 enforced blocks during the incident window — read the file path/hash via the paired 3089.
  • Repeated blocks of the same file — an attacker retrying a load.
  • Unsigned/revoked signature status in 3089 for files from user-writable paths.
  • A 3076 (audited, allowed) for a known-vulnerable driver — it loaded because enforcement was off; treat as a hit, not a non-event.

The interplay with AppLocker and Defender

These controls overlap but aren't redundant:

  • WDAC/Code Integrity = signing/kernel trust (drivers + code integrity).
  • AppLocker = path/publisher/hash rules for user-mode apps and scripts.
  • Defender = malware detection + ASR.

A capable intruder may evade one and trip another — so read all three logs together. A driver that sails past AppLocker can still light up CodeIntegrity 3077.

Correlate

4624 (+4672)   privileged logon
Sysmon 11      a .sys driver dropped to disk
3076 / 3077    CodeIntegrity audits/blocks the unsigned driver load  (BYOVD)
Sysmon 10      (if it loaded) a process opens lsass / EDR is blinded

The Code Integrity event is the moment the kernel-trust boundary was tested. Place it on a timeline with the drop and any follow-on injection.

Hunt checklist

  • Pull …CodeIntegrity%4Operational.evtx.
  • Filter to 3076 / 3077 (and 3033); read the paired 3089 for path/hash/signature.
  • Prioritise driver (.sys) blocks and unsigned/revoked files from user-writable paths.
  • Treat audited-but-allowed vulnerable drivers (3076 in audit mode) as hits.
  • Cross-read with AppLocker and Defender.

Open the CodeIntegrity log in the browser parser; full ID set in the cheat sheet.

Related posts

Using AppLocker's event logs for DFIR — allowed vs audited vs blocked (8002/8003/8004), the script and MSI channels, and how application-control logs double as an execution record even in audit mode.
Why attackers change the audit policy to go dark, and how Event ID 4719 catches it — reading the subcategory and the success/failure changes, and pairing it with log clearing as an anti-forensics signal.
Detecting AD persistence and credential-replication attacks in the directory-service logs — 5136 object modifications (ACLs, AdminSDHolder, GPO), the 5137/5141 lifecycle, and using 4662 to catch DCSync.