Application Shimming (SDB) Persistence: Auditing the Windows Compatibility Backdoor
How attackers abuse Application Compatibility shim databases (sdbinst .sdb files) for stealthy persistence and injection, and how to audit for them on Windows.
The Windows Application Compatibility framework exists so that a program written for Windows XP still runs on Windows 11. It does this by injecting shims — small pieces of code that intercept API calls and patch their behavior — at process startup, before the application's own code runs. That injection primitive is exactly what makes it attractive to attackers. A malicious shim database (.sdb) gives you code execution inside a targeted process, DLL injection, and boot-surviving persistence, all through a signed, first-party Microsoft mechanism that most endpoint tools never inspect. MITRE ATT&CK tracks this as T1546.011 — Event Triggered Execution: Application Shimming.
How the shim engine works
Shims are packaged into a binary .sdb file and registered with the built-in sdbinst.exe tool. Registration writes two things: the .sdb file itself (canonically under C:\Windows\AppPatch\Custom\ or Custom64\) and a set of registry entries that tell the loader which executables the database applies to. When a matching process starts, apphelp.dll maps the shim in and applies its fixes.
Two shim fixes are heavily abused because they hand an attacker direct execution: InjectDll, which loads an arbitrary DLL into the target, and RedirectEXE, which silently reroutes launches of one binary to another. A shim scoped to a program that runs early and often — say a browser, a service host, or even services.exe — becomes reliable, low-noise persistence.
Where the evidence lives
Custom shim registrations leave a consistent registry footprint. These two keys are the primary hunting ground:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\InstalledSDB
Under Custom, each subkey is named after a targeted executable (e.g. chrome.exe) and points at a GUID-named .sdb. InstalledSDB maps each database GUID to its on-disk path and description. Legitimate vendor shims exist, but a custom database targeting a security-relevant binary — or one whose .sdb sits in a user-writable or oddly-named directory instead of AppPatch\Custom — deserves scrutiny.
Hunting for rogue shims
A quick triage pass on a single host:
# Enumerate custom shim registrations
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom" /s
# List installed custom databases and their descriptions
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\InstalledSDB" /s
# Any .sdb file on disk outside the expected default location is worth a second look
Get-ChildItem -Path C:\ -Recurse -Filter *.sdb -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -notlike 'C:\Windows\AppPatch\*' } |
Select-Object FullName, Length, LastWriteTime
On the telemetry side, the strongest signals are:
- Process creation of
sdbinst.exe(Sysmon Event ID 1 / Security 4688) — outside of documented software installs, this is rare and high-value. - File writes of
*.sdb(Sysmon Event ID 11), especially outsideAppPatch. - Registry writes to the
Custom/InstalledSDBkeys (Sysmon Event IDs 12/13).
Attackers can also register a shim without touchingsdbinst.exeby writing the.sdband the registry keys directly. Do not treat "nosdbinstexecution" as proof of a clean host — hunt the registry keys and on-disk files independently.
Reducing the attack surface
Custom shimming is rarely needed in a modern estate, and it requires administrative rights to register — so the strongest control is denying that path in the first place:
- Enforce least privilege. Registering a shim needs local admin. Removing standing admin rights removes the primitive.
- Block or alert on
sdbinst.exevia WDAC/AppLocker where your environment has no legitimate use for custom shims. - Baseline the
CustomandInstalledSDBkeys and alert on any new entry. In a stable fleet these change almost never. - Watch for unsigned or user-writable
.sdbfiles and treatInjectDll/RedirectEXEfixes as inherently suspicious.
Where WinSentinel fits
WinSentinel audits the shim database surface as part of its persistence-hunting checks: it enumerates the Custom and InstalledSDB registry keys, cross-references the registered .sdb paths against the default AppPatch location, and flags custom databases that target sensitive binaries or live in unexpected directories. On a single machine the free tier gives you the full audit with no limits — every persistence and injection check, including this one, runs locally and reports findings you can act on immediately.
Across an organization, WinSentinel Pro rolls those same per-host findings up through a central node: a shim registered on one laptop shows up in fleet drift alerts, and you can compare the AppCompat baseline across every managed endpoint to catch the one machine where a rogue .sdb appeared. Application shimming is a quiet technique that thrives on nobody looking — auditing it continuously, on every box, is how you make sure someone always is.