AppLocker Cache
As you likely know, AppLocker examines EXE and DLL files to determine whether they are allowed to run based on the rules set by an administrator. For simplicity, let’s assume we’re dealing only with hash-based rules.
This means that every time an EXE file is about to execute, AppLocker must read every byte of the file (an operation typically unnecessary), calculate its Authenticode hash, and then make a decision. Naturally, this process is time-consuming and would significantly slow down every program launch (or even DLL loading).
To address this inefficiency, AppLocker caches the calculated hash, allowing it to be reused without recalculating repeatedly. However, this cache is both sensitive and fragile. If a hacker manages to inject the hash of a malicious file, the system could inadvertently allow the file to execute. Conversely, if the cache is corrupted or destroyed, even legitimate files may fail to run until their cache entries are recreated.
Windows handles this challenge in a rather clever way: the cache is stored as NTFS Extended Attributes—a piece of binary data associated with a file. You can read these attributes using the fsutil.exe file queryea command or through the NtQueryInformationFile() function with FileEaInformation as the FileInformationClass. If the attribute name starts with $KERNEL.PURGE.APPID, it most likely pertains to the AppLocker cache. Attributes beginning with $KERNEL.PURGE hold special significance: only kernel-mode code can create them, and the ntfs.sys driver automatically removes these entries if the file content changes.
This ensures the cache behaves exactly as expected for sensitive data. The AppLocker kernel driver (appid.sys) writes this attribute after the first hash calculation, and if the file changes, the ntfs.sys driver promptly deletes the corresponding cache entry.
Manipulating these attributes is challenging because creating $KERNEL.* entries requires kernel-mode access. However, there is one intriguing scenario: offline access. By directly manipulating the drive content below the filesystem level (e.g., using binary editors), it’s possible to modify these attributes. If a cache entry matching an allowed AppLocker rule is created, the binary file can bypass actual content validation and execute, regardless of its real content. One quirk worth mentioning is a potential mismatch between cache and actual file content.
When you execute a file, AppLocker relies on the cached hash. However, when you use Test-AppLockerPolicy to check if the file is allowed to run, it evaluates the actual file content. In most cases, this discrepancy isn’t an issue as long as the cache remains synchronized. But if someone tampers with the cache, the results can appear inconsistent or "weird." For those interested in delving deeper, you can explore the code and sample files available at https://github.com/gtworek/PSBits/tree/master/CopyEAs