Leveraging Application Verifier for Function Hooking and Persistence

Written by actae0n

Introduction to Application Verifier

Function hooking is a powerful tool for attackers. The ability to inspect and modify data structures as they’re passed between functions within a program gives an attacker lots of options for session riding, credential theft, parameter modification, etc. We’re going to take a look at an excellent tool that is provided to us by Microsoft called Application Verifier, which can be leveraged to perform hooking(and persistence) in a trivial, yet powerful manner by letting us run code in the context of an arbitrary unmanaged(native) application.

The MSDN page describes AppVerifier as such:

Application Verifier assists developers in quickly finding subtle programming errors that can be extremely difficult to identify with normal application testing. Using Application Verifier in Visual Studio makes it easier to create reliable applications by identifying errors caused by heap corruption, incorrect handle and critical section usage.

Application Verifier loads a particular Verification Provider into a process as it starts up. This provider, which comes in the form of a DLL, should contain the tests that are to be run in the context of the application being tested. These “tests” can be arbitrary. The provider is loaded at application startup, right after NTDLL.dll; Because of this, we won’t have access to managed code segments in our attack code because we cannot load the CLR (Common Language Runtime, AKA .Net’s execution environment) this early. For most things, this isn’t an actual problem, but it’s good to know.

So, we can load code into any application as it starts using a mechanism provided by the operating system? LD_PRELOAD anyone? Let’s see how we can leverage this.

Overall, the process of getting our code launched is as follows:

  • We create a DLL which serves as the Verification Provider. This DLL is supposed to run routines that verify the application that it is loaded into. It will contain our function hooks and other code. We will drop this into %windir%\System32\ or %windir%\SysWoW64\ (depending on the bitness of the target application).
  • We create a registry key with a few subvalues which sets a few flags (to enable Application Verifier in the right mode) and detailing the name of the library which will serve as the verification provider (our malicious DLL).
  • When the application starts (before other libraries are loaded, with the exception of NTDLL) our Verification Provider will be loaded and execute its code. The load reason will not be THREAD_ATTACH or PROCESS_ATTACH as it typically is when a DLL is loaded. The value of fdwReason in this case is 4, which an existing symbol does not exist for. We will just define as VERIFIER_LOADED ourselves for readability and convenience.

Note that this method requires administrator privileges (a UAC bypass should happen before installing the verification provider and its accompanying registry entries), as we’re writing to HKLM and performing a privileged copy into System32 or SysWow64.


For the demonstration of these capabilities, we’re going to inspect and log POST requests made by Firefox by hooking the PR_WRITE function. This will give us access to the data as it’s being sent, just before it becomes encrypted with TLS and sent over the network.

Details on PR_WRITE and other functions in the Netscape Portable Runtime can be found here.

You can parse these requests with regular expressions to extract usernames and passwords from POST requests sent to login pages, for example. These siphoned passwords or sensitive requests can be loggedto a 3rd party server. I won’t go over writing the regular expressions or reporting aspect, as this article is meant to focus on the deployment and implementation of the hook. When the function is called, our code will execute before the real function and we will be able to inspect or modify the data before forwarding it to the real function. For PR_WRITE, the data being written to the specified file descriptor(fd) is stored in the buf parameter.

The Code

Sometimes you’ll be working with mostly opaque code (no source available) and have to deal with reverse engineering to determine structure types and contents, function prototypes, etc. This can suck. In this case howerver, the code we’re looking for (the Netscape Portable Runtime headers) is available for inspection and copypasta. We’ll be using their headers to define the structures we’re accessing.

Note that when compiling this DLL, its bitness must match the target application. You must also disable the CLR and set the entrypoint to DllMain. Not doing so will cause the verifier to fail to load. If you decide to implement any assembly routines to be run, you should also then disable optimizations. Visual Studio makes doing these things fairly easy via tweaking project settings.

With our DLL compiled, we just copy it into the correct directory like so:

DLL Dropped

Then create the key firefox.exe under HKLM\SOFTWARE\Microsoft\Windows NT\Current Version\Image File Execution Options\. Add the following values:

Registry Values

Then launch Firefox from WinDbg.

Firefox Before Debug Resume

Press g to release the breakpoint and let Firefox continue execution, then navigate to a website. I’ll go to Google.com; We can see in the window that our traffic that is passing through PR_WRITE is being logged successfully.

A Test Request

Now let’s do a test to see if we really do have access to sensitive traffic. I’ll try to log into Twitter (with fake credentials of course).

Logging into Twitter

Now let’s inspect our traffic log file and search for these values:

Found It!

Awesome. The selection in question is also trivial to write a regular expression for, so you could write a version of this hook that excludes all of the “junk” traffic and only reports the username and password values with a regular expression filter.

With Respect To Persistence

Instead of installing a function hook, you could simply use this code execution point as a springboard to launch some other component of your malware. You can still use the DLL_PROCESS_ATTACH event as normal, and it’s subject to all the same restrictions as it typically is.


Post Exploitation Persistence With Application Shims (Intro)

Written by actae0n

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.

InjectDLL Demo

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.

The Initial Interface

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.

Shim Information Dialog

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.

Skip This Step

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.

The Initial Interface

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.

Installing The Fix

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.

Installing The Fix

Installing The Fix

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.

A Caveat

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.