Demystifying Shims - or - Using the App Compat Toolkit to make your old stuff work with your new stuff

Published Mar 16 2019 04:18 AM 18.3K Views
First published on TECHNET on Jun 17, 2011

com·pat·i·ble       adjective       \kəm-ˈpa-tə-bəl\ : capable of existing together in harmony

What is a Shim?

A shim is one of the very few four-letter words in use by Microsoft that isn’t an acronym of some sort. It’s a metaphor based on the English language word shim, which is an engineering term used to describe a piece of wood or metal that is inserted between two objects to make them fit together better. In computer programming, a shim is a small library which transparently intercepts an API, changes the parameters passed, handles the operation itself, or redirects the operation elsewhere. Shims can also be used for running programs on different software platforms than they were developed for.

How Shims work.

The Shim Infrastructure implements a form of Application Programming Interface (API) hooking. The Windows API is implemented using a collection of DLLs. Each application built for Windows imports these DLLs, and maintains a table of the address of each of these functions in memory. Because the address of the Windows functionality is sitting in a table, it is straightforward for the shim engine to replace this address with the address of the shim DLL instead. The application is generally unaware that the request is going to a shim DLL instead of to Windows itself, and Windows is unaware that the request is coming from a source other than the application (because the shim DLL is just another DLL inside the application’s process).

In this particular case, the two objects are the application program and Windows, and the shim is additional code that causes the two to behave better together, as shown below:

Figure 1 Before the shim is applied, the application interacts directly with Windows.

Figure 2 After the shim is applied, the application interacts with Windows indirectly; the shim code is injected and can modify the request to Windows, the response from Windows, or both.

Specifically, it leverages the nature of linking to redirect API calls from Windows to alternative code—the Shim. Calls to external binary files take place through the Import Address Table (IAT). Consequently, a call into Windows looks like:

Figure 1 Application calling into Windows through the IAT

Specifically, you can modify the address of the Windows function resolved in the import table, and then replace it with a pointer to a function in the alternate shim code, as shown in Figure 2 .

Figure 2 Application redirected to the shim prior to calling Windows

This redirection happens for statically linked .dll files when the application is loaded. You can also shim dynamically linked .dll files by hooking the GetProcAddress API.

Why Should we be using Shims

This is the cost-saving route—help the application by modifying calls to the operating system before they get there. You can fix applications without access to the source code, or without changing them at all. You incur a minimal amount of additional management overhead (for the shim database), and you can fix a reasonable number of applications this way. The downside is support as most vendors don't support shimmed applications. You can't fix every application using shims. Most people typically consider shims for applications where the vendor is out of business, the software isn't strategic enough to necessitate support, or they just want to buy some time.

For example, a very commonly used shim is a version-lie shim. To implement this shim, we intercept several APIs that are used to determine which version of Windows the application is running on. Normally, this information is passed on to Windows itself, and it answers truthfully. With the shim applied, however, these APIs are intercepted. Instead of passing on the request to Windows, a different version of Windows is returned (for example, Windows XP instead of Windows 7). If the application is programmed to run only on Windows XP, this is a way to trick the application into believing it’s running on the correct OS. (Frequently this is all that is necessary to resolve an application compatibility problem!)

There are a huge number of tricks you can play with shims. For example:

  • The ForceAdminAccess shim tries to trick the application into believing that the current user is a member of the local Administrator group, even if he is not. (Many applications outright fail if you are not a local administrator, though you may be able to use other tricks, such as UAC File and Registry Virtualization, to resolve the issues that caused the check in the first place.) How it implements this check can be fairly straightforward. For example, this shim intercepts the API IsUserAnAdmin from shell32.dll. The complete source code of the shimmed function (which has wonderful performance characteristics compared to the actual API) is simply return TRUE.
  • The WrpMitigation shim tricks application installers into believing they can write to files that are protected by Windows Resource Protection (WRP). If you try to write to a file that’s protected, the shim first creates a new temporary file, marks it to be deleted once the handle is closed, and then returns the handle to the temporary file as if it were the actual protected file. The application installs the crusty old version of kernel32.dll or shell32.dll (or whichever other file it picked up while it was being packaged) into a temp file, but then that temp file goes away and the matching, patched, up-to-date version of the protected file remains on the file system. So, WRP can still ensure that you don’t end up with an ancient copy of shell32.dll from Windows 95 on your computer, but the installer won’t fail with ACCESS_DENIED when you use this shim.
  • The CorrectFilePaths shim can redirect files from one location to another. So, if you have an application that is trying to write to c:\myprogramdir (which isn’t automatically fixed using UAC File and Registry Virtualization), you can redirect the files that are modified at runtime to a per-user location. This allows you to run as a standard user without having to loosen access control lists (ACLs), because you know your security folks hate it when you loosen ACLs.

NOTE: As shims run as user-mode code inside a user-mode application process, you cannot use a shim to fix kernel-mode code. For example, you cannot use shims to resolve compatibility issues with device drivers or with other kernel-mode code. (For example, some antivirus, firewall, and antispyware code runs in kernel mode.)

When can we use a Shim:

  • You acquired the application from a vendor that is no longer in business . Several applications are from vendors that have since gone out of business; so clearly, support is no longer a concern. However, because the source code is not available, shimming is the only option for compatibility mitigation.
  • You developed the application internally . While most customers would prefer to fix all their applications to be natively compatible, there are some scenarios in which the timing does not allow for this. The team may not be able to fix all of them prior to the planned deployment of new version of Windows, so they may choose to shim the applications that can be shimmed and modify the code on the ones where shims are insufficient to resolve the compatibility issue.
  • You acquired the application from a vendor that will eventually be releasing a compatible version, but support is not critical . When an off-the-shelf application is neither business critical nor important, some customers use shims as a stopgap solution. Users could theoretically wait until a compatible version is available, and its absence would not block the deployment, but being able to provide users with a shimmed and functional version can bridge that gap until a compatible version is available.

Creating an Application Compatibility Shim

If you are trying to run an application that was created for 2000 or XP and had problems running in Windows 7, you could always turn on compatibility mode for the executable on your machine. However if you are trying to create a shim that could be used on other machines as well, you could use the following instructions to create the shim and send it. It is a very small size and once executed, will always be associated with that executable on that machine.

ACT is the Application Compatibility Toolkit. Download it from here:

Once we launch the Compatibility Administrator Tool , from Start Menu – Microsoft Application Compatibility Toolkit :

Right-click on New Database:

Choose Application Fix here. In this below dialog, give the application details and the executable you would want to fix:

  1. Type the name of the program to fix
  2. Type the vendor name
  3. Browse to location of executable

When you press the next button, you will get to see the list of the compatibility modes listed by default. If you have an issue with just version incompatibility then choose the version in which the application was working earlier.

At this point I have already determined that Windows 2000 compatibility mode will work for this program.

In the list box, scroll down and select  “Windows 2000”

In the next window (when you have combination of shims to be chosen). As shown below, you have lots of shims to choose from. Select all the shims which would fix your application.

Click on Finish . This will give you the complete summary of the application and the fixes applied.

Now you need to save this shim database file (A small database including the shim information is created), and install it. You can either install it by right-clicking on the shim and pressing the install button, or by using a command-line option, sdbinst.exe <database.sdb>.

NOTE : “ sdbinst.exe” is already located by default in c:\windows\system32

Once the Application Compatibility Database is installed, we can run the program from the location specified earlier (in the first window). Now the program should be running in the Compatibility mode that you specified during the process.


Deepinder Singh

Version history
Last update:
‎Mar 16 2019 04:18 AM
Updated by: