Techniques To Maintain Persistence
In this technical blog post, we’ll explain in-depth two uncommon and difficult-to-detect techniques that can be leveraged to maintain persistence. These techniques will be used from within user-space, meaning we can use these techniques without having to resort to the installation or manipulation of drivers or mini-filter drivers (rootkit techniques). Instead, we’ll abuse operating system features to give us our persistence.
Before we dive in, here are some prerequisites you’ll need to follow along.
- dllinjshim.cpp and moo.cpp code snippets
- Visual Studio 2019 Community Edition
- C/C++ tools with Visual Studio 2019 Community Edition; x64 Native Tools Command Prompt for VS2019 (added during the Visual Studio installation/setup)
- A non-Microsoft Binary. Easily compile a helloworld.exe using these steps:
1. Open Visual Studio 2019
2. Select Create a new project
3. Select Console App and Next
4. Choose a Project Name, Location, etc.
5. Select Create
6. In Visual Studio 2019 select Build, then Build Solution
7. The output should be an executable. You can find the Path in the Output Terminal
Application Shimming (ATT&CK Technique 1138)
Application shimming was initially designed by Windows to allow legacy Windows applications to execute within newer versions of Windows (Vista, 7, 8, 8.1, 10), even if that meant overriding certain application functions or features. This override mechanism occurs in some cases by forcibly loading a new Dynamic-link Library (DLL), which changes existing calls that would otherwise fail or break the application on up-to-date Windows versions. In earlier versions of application shimming, a system administrator would simply define this behavior in a shim database (SDB) file and register that shim with the system.
Eventually, Microsoft noticed that malware was explicitly abusing the DLL loading functionality. As a result, Microsoft severely restricted its use within Windows 10. Most resources regarding application shimming note that it can’t work within Windows 10, but this is not strictly true. In Windows 10, application shimming is restricted to force-loading the following DLLs from C:\Windows\System32\:
Interestingly, Microsoft allows EMET.dll and EMET64.dll to be loaded from C:\Windows\System32\ folder, but EMET has been End-of-Life since July 31st, 2018. The EMET.dll and EMET64.dll files are not present on modern Windows 10 installations, which means we can add our DLLs to the C:\Windows\System32\ folder and create a new application shim that successfully loads our malicious EMET.dll! Score! However, are some limitations, though:
- You can’t shim Microsoft-signed binaries
- You’ll need administrator privileges to add a file to C:\Windows\System32
Generating the SDB File
We’ll use the files mentioned above (moo.cpp and dllinjshim.cpp) to create our SDB file, which we’ll then export to our victim’s machine. We’ll take the first file, dllinjshim.cpp, and save it to a file of the same name on our victim’s computer.
- Modify the INJECTED_DLL_NAME to be EMET64.dll
- Modify the target EXECUTABLE_NAME to the name of a non-Microsoft binary (your helloworld.exe)
3. On line 165: Add (PBYTE) before \x42\x42\x42\…
4. On-Line 179: Add (PBYTE) before \x41\x41\x41\…
5. Save the dllinjshim.cpp file
6. Next, open x64 Native Tools Command Prompt for VS2019
7. Navigate to the location you stored dllinjshim.cpp and then run the following command: cl /Fe:dllinjshim.exe dllinjshim.cpp
Registering the Shim in Windows
We now have an application that will generate an SBD file and performs DLL Injection on a target 64-bit binary (64-bit software is specified on line 40). We must register the shim with Windows to get it to work:
- Run CMD.exe as an administrator on the victim machine
- Navigate to the directory in which you stored your files
- Run the following commands (one at a time):
Performing the DLL Injection and Testing It
Now, the moo.sdb shim will be looking for the moo.dll to load into the target executable as a part of the patch. We’ll compile one using the moo.cpp from earlier:
- Open the moo.cpp file in a text editor
- Add #include <Windows.h> to the first line
- Add #include <stdio.h> to the second line.
- Add printf(“Injection Success\n”); on line 31, above return TRUE;.
Note: This will later let us know when the injection was successful.
5. Run x64 Native Tools Command Prompt for VS2019
6. Navigate to the location of moo.cpp
7. Run the following command: cl /LD /Fe:EMET64.dll moo.cpp
Note: This will compile moo.cpp into a file named EMET64.dll.
8. Run CMD.exe as an administrator
9. Run the following command to copy the EMET64.DLL to the System32 Directory: copy EMET64.dll C:\Windows\System32\
10. Start the target executable, which in our case was the helloworld.exe! You’ll see Injection Success if you have successfully injected into an executable. The best way to see this is by targeting a command-line executable, even if it’s just a hello-world. That way, you can see the message produced by your injected DLL.
This tactic works best when targeting third-party software running, especially if that software is automatically started when the machine boots. We suggest targeting any non-Microsoft executables that are run as services by svchost.exe as good candidates for maintaining persistence with this technique.
It’s possible to detect installed shim databases by looking at the system with the Windows Application Compatibility Administrator Toolkit, which will list the installed shims.
Run the installer and be sure to select the Windows “Application Compatibility Administrator Toolkit” when it asks you what you’d like to install. Once installed, run the utility and view the list of installed databases as well as their properties, as illustrated in the screenshot:
If you prefer detecting or inspecting registry keys, check here:
You’ll still need to parse installed databases to determine their purpose. Several tools exist to convert the binary format of SDB into more human-readable output, and a popular option is sdb2xml. Some SDB files are legitimate and are used to patch incompatible binaries to run in recent versions of Windows. A corporate load running or supporting legacy applications is more likely to have legitimate SDBs, but these should be targeting specific applications.
While there are some hurdles and restrictions around deploying this technique, the difficulty of finding installed shim databases and parsing them for known bad behaviors makes this difficult to detect and, therefore, a good candidate for maintaining access. An organization running legacy applications may also have legitimate shim database entries installed, which means that they would need to be parsed to understand if any entries had been subverted. A better solution: Simply look for any non-Microsoft-signed binaries matching the approved DLL list inside of C:\Windows\System32\.
*** This was originally posted by Bryan Halfpap on the Booz Allen blog. To see the original post click this link.