Application Compatibility¶
What Windows keeps¶
Besides the ShimCache (parse-registry shimcache) and Amcache (parse-registry amcache),
Windows' application compatibility features keep these under
Microsoft\Windows NT\CurrentVersion\AppCompatFlags:
| Source | Hive and key | What it shows |
|---|---|---|
layers |
SOFTWARE (and Wow6432Node) and NTUSER.DAT Layers |
Programs set to run with compatibility layers: RUNASADMIN (always as administrator), WIN7RTM, HIGHDPIAWARE, … |
pca_store |
NTUSER.DAT Compatibility Assistant\Store (Windows 8 and later) |
Programs the Program Compatibility Assistant saw the user run |
pca_persisted |
NTUSER.DAT Compatibility Assistant\Persisted (Windows 7) |
The same, on Windows 7 |
cit_module |
SOFTWARE CIT\Module\<module> |
Programs that loaded a tracked module, and when they last did |
cit_system |
SOFTWARE CIT\System (Windows 7 to early Windows 10) |
Program paths and command lines in the compressed CIT databases |
installed_sdb |
SOFTWARE InstalledSDB\{GUID} |
Custom shim databases installed with sdbinst: file, description, install time |
custom_sdb |
SOFTWARE Custom\<program> |
The custom shim databases applied to each program, with their install times |
Best conclusion: layers and shim databases are configuration that changes how a program runs; Program Compatibility Assistant and CIT entries show that a program ran (or loaded a module) as this user or on this system.
Custom shim databases are a persistence and injection technique (MITRE ATT&CK T1546.011): a shim can load a DLL into a program or start another one whenever the program runs.
Location¶
C:\Windows\System32\config\SOFTWARE
Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers <program> = <layers>
Microsoft\Windows NT\CurrentVersion\AppCompatFlags\CIT\Module\<module> <program> = FILETIME
Microsoft\Windows NT\CurrentVersion\AppCompatFlags\CIT\System <id> = compressed database
Microsoft\Windows NT\CurrentVersion\AppCompatFlags\InstalledSDB\{GUID} DatabasePath, …
Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Custom\<program.exe> {GUID}.sdb = FILETIME
C:\Users\<user>\NTUSER.DAT
Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers
Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Compatibility Assistant\Store
Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Compatibility Assistant\Persisted
Collect SOFTWARE, every NTUSER.DAT and their transaction logs, and the .sdb files a shim
database's path names (usually C:\Windows\AppPatch\Custom\).
Analyst cautions¶
-
CIT expansion is bounded. Values declaring more than 64 MiB uncompressed are retained as raw bytes with a diagnostic. Malformed compression and size mismatches are reported.
-
No run time for Program Compatibility Assistant entries. The
Storedata (SACP, kept inDataRaw) has one time, but on Windows 8.1, 10 and 11 it is the same for every program of a hive, and for other systems: it is not when the program ran. Only theStorekey's last write dates the most recent change. - Programs on removable media are named
SIGN.MEDIA=<id> <path>:Pathis the path on the media, andDetailshas the media id. - CIT databases are LZNT1-compressed and their structure isn't publicly documented: Juntei lists the program paths and command lines found in each, once per database, without counts or times. A command line is its own record, not tied to its program. Windows 10 and later keep little here.
- Shim databases. Check every
custom_sdbandinstalled_sdbrecord: legitimate software rarely installs one. The.sdbfile itself says what the shim does. - Layers set by a user apply only to that user;
SOFTWARE's to everyone.RUNASADMINmakes a program ask for elevation every time.
Parse with Juntei¶
Usage: juntei parse-registry app-compat <INPUT> [OPTIONS]
Input:
-d, --directory <DIR> Recursively find SOFTWARE and NTUSER.DAT hives
-f, --file <FILE> Parse one SOFTWARE or NTUSER.DAT hive
--log1/--log2 Supply transaction logs explicitly
--no-logs Do not replay logs
Output:
-o, --output <FILE> Save records
-t, --output-type <TYPE> csv, json, or jsonl
juntei parse-registry app-compat -d evidence/ -o appcompat.csv
juntei parse-registry app-compat -d evidence/ -t jsonl \
| jq 'select(.Source == "installed_sdb" or .Source == "custom_sdb")'
The summary lists the custom shim databases, the programs with layers, and the CIT modules' last uses.
Output fields¶
| Field | Interpretation |
|---|---|
Host, SourcePath, HiveType |
Host, hive file, and SOFTWARE or NTUSER.DAT. |
User, UserSID |
A user hive's profile folder name, and its SID from the system's ProfileList. |
Source, Scope |
layers, pca_store, pca_persisted, cit_module, cit_system, installed_sdb, custom_sdb; machine or user. |
Path |
The program (the value's name), a path or command line in a CIT database, or the program a shim database applies to. |
Layers |
The compatibility layers, as written (~ RUNASADMIN). |
LastSeenUTC |
When a program last loaded a CIT module. |
SdbGUID, SdbPath, SdbInstalledUTC |
A shim database's GUID, file and install time. |
Details |
A CIT module's name, a CIT database's value name, a program's removable media id (SignMedia), a shim database's DatabaseDescription and DatabaseType. |
KeyPath, KeyLastWrittenUTC, ValueName, WOW64 |
Where the record comes from, when that key last changed, and whether it is under Wow6432Node. |
DataRaw |
The Store value's SACP data, or data that isn't what it should be (hex). |
TransactionLogStatus, LogsApplied |
Registry recovery context. |
Problems |
Data that couldn't be decoded or read. |
Investigation strategy¶
- Review every custom shim database: its
.sdbfile, install time, and the programs it applies to; correlate withsdbinst.exein Prefetch, Amcache and process creation events. - Look for programs in user-writable folders among Program Compatibility Assistant entries, and for programs from removable media.
- Check
RUNASADMINand other layers on unusual programs. - Correlate with ShimCache, Amcache, BAM, Prefetch and UserAssist for execution times.