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.

Options

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.


Kernel Defenses, Detection, and Exploitation

Written by TurboBorland

Intro: Nothing Good Lasts Forever

As mainstream shifts their attention towards the kernel landscape its sponsored defenses have made their way into our everyday hardware and officially supported kernel images. With any new defense the implementation and adoption is slow, but utilization on target systems will only increase in the years to come. Some exploit developers have had lots of time to play with these new defenses (KERNEXEC/UDEREF), but the newer generation have yet had the need to take aim against these hardened kernels. While the obvious(ly hilarious) KASLR (aka noob-killer) is gaining wide support in public circles there are two other cpu-supported defenses to be aware of. These being SMAP (Supervisor Mode Access Prevention) and SMEP (Supervisor Mode Execution Protection).

What is SM[AE]P?

Supervisor Mode Execution Protection (SMEP) is easy to understand if youre familiar with control flow and/or userland memory protection techniques. A generic kernel exploit back in the days of old allowed you to move execution control (IP/PC/etc.) to a userland controlled page with your buffer in it. This allowed kernel context to execute code from a userland mmap(, PROT_EXEC); controlled buffer. SMEP is here to ruin that party and deny kernel context to execute code from userland address space. Its basically NX for userland/kernel page boundaries. If anyone has ever played with KERNEXEC, here we have it supported hardware.

Supervisor Mode Access Prevention (SMAP) is more of an oddity which has aided to interesting implementation. This technique denies READ/WRITE access from kernel context to userland data. This allows both defenses combined to filter privilege control over the RWX spectrum. The problem is that telling the kernel what it can or cannot access is difficult. Sometimes data structures in userland need to be read or modified by kernel context and, obviously, userland data needs to be pulled for communication channels such as get_user() and put_user(). Due to this need we get a hilariously easy to bypass defense that is documented, not talked about in the loudest whitehat circles, and so seemingly odd that kernel developers accidentally marked huge code regions to not use the protection.

What is CPUID?

CPUID is an instruction implemented on modern cpu architectures. A large assortment of interesting information can be retrieved with CPUID by setting two arguments/registers and ANDing the returned result with a proper mask. These arguments are defined as the leaf node and the sub-leaf. The leaf node is the main category of information youre requesting cpuid for and it is controlled via the EAX register. The sub-leaf is barely used, but calls into a section of the main section via the ECX register. Its highly suggested that the interested reader take a look at the references in cpuid(4), at their own cpuid output, and a table of leafs/sub-leafs and associated returns.

Of interest in the above link is the Extended Features section (eax/leaf = 7 and ecx/subleaf = 0). This allows the caller to execute an unprivileged instruction that validates security features enabled on the victim system.

Detecting SM[AE]P via CPUID Instruction Code

        /* 
         * unprivileged cr4 value detection with cpuid
         * cpu's that support cpuid instruction will work (if not, cpu likely doesn't support SM[AE]P anyway)
         * problem is, although unlikly, bits can move and mask may be incorrect for specific cpu's
         * you can double validate by grep -oE "sm[ae]p" /proc/cpuinfo
        */
        int op = 0x07;    /* leaf */
        int smep_mask = 0x00000080;
        int smap_mask = 0x00100000;
        uint32_t regs[4] = { 0 };

        // no error detection, this will fault you if cpu doesn't support this instruction 
        asm volatile("cpuid" : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3]) \
                : "0" (op), "2" (0));

        // SMEP
        if ( (smep_mask & regs[1]) != 0) {
	...
        // SMAP
        if ( (smap_mask & regs[1]) != 0) {

Implementation of and Bypassing SM[AE]P

With all the pre-requisite information out of the way, lets get to the reason you all came here today. How to get around these new kernel defenses? Say, again, we have a vulnerability that gives a WRITE-WHAT-WHERE primitive and we know the KASLR sliding window via the millions and one ways possible to due so.

SMEP does not have a straightforward method to disable itself. Without being able to move execution to your own userland buffer, how do we start control flow? The SMEP bit exists in the 7th bit of the CR4 register, so it is possible to manipulate the cr4 register with logical bit-wise instructions (AND, OR, XOR), shifts, or even bitmask writes. However, the most likely path to be taken here is to do as you would in userland, which is to utilize borrowed code gadgets. Thankfully the kernel has a large surface to generate gadgets from. Grab the targets vmlinuz, search for gadgets, then KASLR_SLIDE+offset. If you are having a hard time getting the KASLR slider, chances are youll end up OOPSing the system in the first place.

SMAP, on the other hand, is much easier to work with. SMAP exists in the 20th bit in the cr4 register, but well just ignore the shit out of this protection mechanism. Remember that the kernel must be able to access userland data for a large assortment of tasks, such as taking arguments and data from userland. So they decided to utilize a documented “fuck you” bypass flag called Alignment Check/EFLAGS.AC. Regardless if that fancy new kernel protection mechanism is enabled and being the bitch bit on your userland page, we can simply call STAC and set the AC flag and completely bypass it. Not only that but this instruction is all of 3 bytes (0f 01 CB). Thats right, if you can manage to find this sequence of 3 bytes inside of the kernel .text range, you win and SMAP cries a shameful death and your function pointer ovewrite, IDT entry overwrite, or whatever fanciness you want can continue.