← All posts

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:

Attackers can also register a shim without touching sdbinst.exe by writing the .sdb and the registry keys directly. Do not treat "no sdbinst execution" 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:

  1. Enforce least privilege. Registering a shim needs local admin. Removing standing admin rights removes the primitive.
  2. Block or alert on sdbinst.exe via WDAC/AppLocker where your environment has no legitimate use for custom shims.
  3. Baseline the Custom and InstalledSDB keys and alert on any new entry. In a stable fleet these change almost never.
  4. Watch for unsigned or user-writable .sdb files and treat InjectDll/RedirectEXE fixes 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.