After seeing our red team bypass logging via IAT patching and light ETW tampering, I’m reworking protections on a Windows C++17 service built with clang-cl, CFG, and CET. What combinations have held up for you — e.g., RASP-style syscall allowlists with keyed integrity checks, or per-build function layout randomization with runtime self-verification — and how do you keep it debuggable in CI without leaking symbols or keys?
But we ended up ditching syscall allowlists and doing a ‘sampled’ integrity check: at random intervals we HMAC a rotating slice of the IAT and a couple hot.text pages, and if something drifts we quietly degrade features instead of crashing. It only sticks if you also shrink injection surface — WDAC plus the Microsoft vulnerable driver blocklist cut our hook attempts a lot: Microsoft recommended driver block rules | Microsoft Learn. Think smoke alarm, not vault.
@csmith203 We paired WDAC with CET/CFG and a sibling watchdog; stopped IAT patching, deployment’s finicky.
Quick example: flipping on CIG/ACG and Win32k lockdown (plus DisableExtensionPoints) via SetProcessMitigationPolicy did more for us than syscall allowlists. It shut down most “IAT patching” attempts by blocking non‑signed DLL loads and making code‑gen pages a non‑starter; with clang-cl + CFG/CET it’s been solid, though debugging is — so we gate it with a dev-only registry switch; ref: https://learn.microsoft.com/windows/win32/api/winbase/nf-winbase-setprocessmitigationpolicy.