About Application Shims
As new versions of Windows get released, and system APIs get updated, older applications develop problems. Some wont install/run because theyre only coded to check for compatibility with Windows 95 for example, and have no idea what to do with the version strings supplied by Windows 7 except call it incompatible. Some rely on legacy paths which are no longer present in newer version of Windows, such as the difference between the path to the users home directory when comparing Windows XP and Windows 7. While some vendors may provide extended support to these older products to companies on a case-by-case basis, a large number turn into abandonware. Then companies are faced with the decision of either running a super legacy system on their network and getting #rekt, or patching the application to work on newer systems. Some applications fill a very niche role in environments and cannot be easily replaced, or have no modern replacement. In this case, workarounds are needed.
Microsoft recognized this issue, and created the ACT (Application Compatibility Toolkit), which you can install to create fix packages targeting specific applications. You create a database of one or more application fixes. The fixes are then read out of the database, and installed on the target machine. The fixes do a wide variety of things, from lying about the OS version to the application, to redirecting accessed paths, to using legacy API functions over the newer ones, and even denying it read/write to resources that it really does have access to (which can lead to some fun application sandboxing scenarios). This all happens transparently to the application. Naturally, the ability to lie to applications and the execution environment can, and will, be abused.
First, download the appropriate packaged version for your Windows target. You can grab the Windows 10 version here. It (at least the Windows 10 version) is being bundled with the ADK, and you can check/uncheck different components. The only one we need for this will be the ACT, so check that.
For the first (and probably most useful) example, well be utilizing a useful fix that allows us to preload a DLL into an application. Yes, Microsoft provided a signed implementation of DLL injection just for us! We’ll be creating a fix for Putty that injects a DLL at application startup to run some of our own code. This fix just scratches the surface of what you can do with shims, and I plan to expand more on this as a post-exploitation kit in later posts. But for now, lets get down to it.
After installation, the compatibility toolkit will be located in
%ProgramFiles(x86)\Windows Kits\10\Assessment and Deployment Kit\Application Compatibility Toolkit\Compatibility Administrator (xx-bit)\Compatadmin.exe. There will be separate management applications for 32 and 64 bit shims. Its worth noting that you must create a 32 bit shim for a 32 bit application, and likewise a 64 bit shim for a 64 bit application.
When launching the application compatibility toolkit, youll initially have access to a very limited set of application fixes. These are the most commonly used ones, and cover the majority of needs for legitimate fixes. However, there is an undocumented command line option (
/x)that unlocks the rest of the fixes, yielding just under 900 available choices for the 32 bit compatibility toolkit at the time of writing. You may as well launch with that option right away.
After launching, youll be presented with the management interface. This will let you create, update, and manage shim databases.
With New Database selected (the default, unsaved shim database), click the Fix button near the top of the window. This will open the dialog to create a new application fix. Here, youll fill in some basic fields with information about the fix youre creating. They can be filled in with bogus information, with the exception of the path to the executable to be shimmed.
The next screen involves compatibility modes. These offer options to make older applications work on newer systems by lying about the environment (OS Version, graphics modes, etc). These arent relevant for this example, so you can skip them by hitting next.
This next screen, however, offers some interesting options to play with. The one were concerned with here is named InjectDLL. Select it by checking the box next to it, then click the Parameters button to configure how we want it to behave. These fixes dont have customized parameter dialogs, so youll have to mouse over the fix name to get a basic description of what parameters it takes. The InjectDLL fix takes a list of paths to DLLs to be loaded during application startup. For this example, I just dropped it on the root of the drive. Dont do this with real malware. That would be dumb.
The code I used for this InjectDLL example is the following:
It just pops a message box for the sake of visual demonstration. A real payload you might use for Putty would be PuttyRider, or some keylogger.
The final screen lets you specify which properties will trigger an application match for the shim. If you were shimming an application that may update in the future, youd probably want to uncheck or modify some of these to be a looser match. An internet browser would be a good example. If your shim matching information doesnt align with the program, the shim wont apply. You can play around with these, most will be dependent on the app being shimmed. For this example, we’ll leave them all in their default state.
Once all that is finished, you can click Save to save and name your shim database, which will be a .sdb file. This shim is portable, and can be dropped and installed on new systems, so long as you fulfill the parameters that you set for it yourself. For this example, Id want to drop my DLL in the correct location, and ensure that the target application is installed at the path I expect it to be. Anyway, lets install the shim. You can use a utility that ships with Windows (the ACT does not need to be installed) to install your shim database, and the command is pleasantly simple.
Note that for this to work, you will need administrative privileges, and have bypassed UAC. UAC bypasses arent particularly hard to come by, so I wouldnt consider that a restriction really. If you land yourself in an unprivileged user account, though, youll have to escalate first.
Now, all we have to do is start up Putty to demonstrate the DLL preload. Our code should run (popping the message box). After the DLLMain method returns, normal program execution will resume.
This is a useful method to add to your persistence toolkit. You can shim applications that are part of daily routine for your target (parts of the Microsoft Office Suite, web browsers, etc) for reliable callbacks. This method does have a strong caveat however, which youll need to account for. Your shim name will show up in the list of installed applications on the target system if you use the default shim installation utility.
It is possible to avoid this, however. The sdbinst.exe utility simply copies the shim database file to
%WINDIR%\AppPatch\Custom\ (with the GUID as the filename), and creates a few registry keys under
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags to inform AppCompat of the installed shim, and finally adds it to the installed applications list. However, you could create a shim installer to perform these actions yourself, minus the addition to the installed applications list. Your custom installer would still be subject to the restrictions of a UAC bypass and administrative rights.
The next shims post will cover some advanced usage, including custom x64 fixes (we dont get access to InjectDLL for 64 bit fixes, so we have to roll our own custom generated fix) and custom shim installers, as well as functionality for some rootkit-esque functionality.