Windows DLL Hijacking

Risus Sardonicus
Risus Sardonicus ITSec
11 min readDec 21, 2018

Welcome to another sardonic post about a well known pre-loading attack on Windows systems that have been around for quite a while. Don’t expect to read some significant new stuff on this post, it’s just a writeup of my very own experiments with a well known technique. Actually it’s more or less a page in the black grimoire I use to keep my mind busy day and night. So let me show you a little story out of that grimoire….

And God.exe said, “Let there be light! And the world tried to load light.dll from %PATH%” and there was a light.dll, but it’s not quite what he did expect… — Imaginary Windows Bible, Genesis 1:3

Still looks pretty damn dark after loading that light.dll, well guess i should just restart this crappy thing…. Nope didn’t help, but some other weird stuff happens after executing… A funny message pops out sayin “Hijacked your light.dll, sorry bro! Cheers Luci” — Hijacking a dll, what sorcery is this?

Well, to keep it rather short DLL Hijacking usually happens by placing a malicious DLL in some special places. This causes the OS to load the malicious dll instead of the legitimate one. It is basically a neat way to escalate your local privileges on a windows machine if you identfy a privileged process or a executable running in an privileged context, that carelessly loads its .dlls. If one can identify such an abomination, one possibly can place a malicious .dll that contains arbitrary code into those places. Once that vulnerable process/executable gets executed, the .dll runs within the privileged context and Voilá — Escalation!!11!

The following steps will guide you through this post:

  1. Identify your attack vector
    1.1. Find privileged processes
    1.2. Monitor identified processes for hijackable DLLs
  2. Check for write permissions in target folders
  3. Creating and compiling a “malicious” DLL
  4. Exploit it!!11!

Mind the fact that the example that is used to outline the practical exploitation here is NOT executed in a privileged context (cuz yeah, I was kinda lazy on this, sorry)

Now without further hesitation, let’s jump in.

Step 1. Identify your attack vector

The following subsections encapsulate a couple of checks that have to be done when initially checking for a DLL-Hijacking vulnerability. Furthermore we assume, that we have only unprivileged access (except for Procmon, I mean we could basically just try to mimic the target on a local VM and use Procmon there to analyze processes/executables).

Step 1.1. Find a privileged target

A very basic example on a local machine would be to utilize the Windows Task manager (go to “Processes”-Tab and add the “UAC Virtualization” Column to the View, for Windows 7 it is “View -> Select columns -> Check on User Account Control (UAS) Virtualization -> OK”).

If you are not on your local machine you’re a nasty boy, but you can still retrieve basic process lists. For example with:

* `wmic process > outfile`
* `tasklist /FO CSV > tasks.txt`

Furthermore several Enumeration-Tools can help you out on this. I guess you got the point and we can move on…

In the following example we will be using the BGinfo.exe-Executable that tries to load some DLLs that can be hijacked after executing the .exe file. This process is not running all the time and can only be started manually (or by a scheduled task).

By now we have located a set of interesting executables (or running processes) that may be our target. Let’s start poking around and picking out the cherries…

Step 1.2. Monitor identified processes for hijackable DLLs

Investigate identified processes with Procmon (https://docs.microsoft.com/de-de/sysinternals/downloads/procmon ) for hijackable DLLs. In order to do this apply a basic filter with the following properties:

  • Process Name is <[Value]>
  • Result is <[NAME NOT FOUND]>
  • Path ends with .dll*

The following GIF shows the process of filtering Systemevents with Procmon. In this case we filter all systemevents with the folowing properties:

  • Process Name is BGinfo.exe — This property selects only events that are tied to the BGinfo.exe
  • Result = NAME NOT FOUND — This property selects only events where the file with the corresponding name could not be found in the given location (path) (e.g. because the file does not exist)
  • Path ends with .dll — This property selects only events that are tied to .dll files loaded by the BGinfo.exe

A good approach would be to further analyze the given paths for user writeable locations, because the placement of a .dll with the corresponding name under the given paths will most probably result in a successfull DLL hijacking attack.

For the further example the given line is especially interesting, because it shows the chosen .dll that is going to be used in our example attack.

Time: 5:43:51.0002082 AM    
ProcessName: Bginfo.exe
PID: 2296
Operation: CreateFile
Path: C:\Users\risusUser\Desktop\tools\Bginfo\profapi.dll
Result: NAME NOT FOUND
Detail: Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a

As shown we will be creating a malicious `profapi.dll` and place it into the directory indicated by the path (which happens to be the path from which the application is loaded): C:\Users\risusUser\Desktop\tools\Bginfo\.

As indicated we located a potential hijackable .dll named ‘profapi.dll’ (User Profile Basic API DLL ). As indicated by Procmon the dll tries to load the dll from the same path from which the application is loaded. Since the .dll is not present there the call fails. The next step is to see which firectories can be leveraged to hijack the given .dll.

Step 1.3. Check if the target .dll is somewhere present on the system

As for DLL Hijacking a Windows application will use pre-defined search paths to find DLL’s and it will check these paths in a specific order.

In fact the system searches directories in the following order:

1. The directory from which the application ẃas loaded.
2. The system directory. (`C:\Windows\System32)`)
3. The 16-bit system directory. (`C:\Windows\System)`)
4. The Windows directory. (`C:\Windows)`)
5. The current directory.
6. The directories that are listed in the PATH environment variable.

Assume the target .dll is neither present in the directory from which the application was loaded, nor in the system directory but it is present in the 16-bit system directory. In this case only the first two directories can be abused for .dll hijacking (because in dir 3. the system will eventually find the valid .dll, load it and stop searching).

In order to move forward in our exploitation plan, we have to determine if the valid .dll is present at all on the system, and if yes where it is exactly.

I’d like to present 2 techniques to do so:

  • usage of meterpreter `> search -f hijackable.dll`
  • Adjust filters of Procmon, in order to print out successfull findings too (the first successfull finding of the .dll indicates the lcoation of the valid one.)

In our case of abusing the `profapi.dll`, the corresponding procmon line would be:

Time: 6:29:18.0762773 AM 
ProcessName: Bginfo.exe
PID: 3308
Operation. CreateFile
Path: C:\Windows\System32\profapi.dll
Result: SUCCESS
Details: Desired Access: Read Data/List Directory, Execute/Traverse, Read Attributes, Disposition: Open, Options: Non-Directory File, Complete If Oplocked, Attributes: N, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened

This means that the valid profapi.dll is present within the the system directory ( C:\Windows\System32 ). Therefore the Bginfo.exe is in fact vulnerable to DLL-Hijacking by using the profapi.dll IF an attacker is able to insert a malicious .dll into directory from which the application was loaded. The next step will be to check if we have this write permission

Step 2. Check for write-permissions in target folders

After location a potential juicy .dll we have to validate if we got the necessary permission to write it to the system. This can be achieved by using a built-in system command called `icacls`.

In our case, the target path happens to be the path from which the application is loaded: C:\Users\risusUser\Desktop\tools\Bginfo\ .

C:\Users\risusUser\Desktop\tools\Bginfo>icacls .
. NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F)
BUILTIN\Administrators:(I)(OI)(CI)(F)
risus-PC\risusUser:(I)(OI)(CI)(F)
Successfully processed 1 files; Failed processing 0 files

See also the following GIF:

As indicated the `risusUser` has the following permissions `(I)(OI)(CI)(F)` . Especially interesting for our purposes is the last parenthesis (`(F)` ) as it indicates the access rights within the directory.

The most important values indicating privileges in icacls output are:

 a sequence of simple rights:
N — no access
F — full access
M — modify access
RX — read and execute access
R — read-only access
W — write-only access
D — delete access
Output cropped → a bunch of more permission indicators can be determined by typing ‘icacls’ into the windows cmd.
```

With this in mind the (F) can be translated to full access on the directory. This is about the best case that can happen — we have a potential vulnerable application that resides in a directory that is writeable by the current user!

In fact we seem to be lucky here (What a coincidence) — The only exploitable directory is writeable by our user. Since this is fairly uncommon, I’d like to give some additional infos how to proceed if the directory from which the application was loaded is not writeable:

Depending on the outcomes of Step 2.3., a fair amount of other directories could be juicy for Hijacking the DLL (We assume now that the target .dll s not present on the system at all)

  • `C:\Windows`
  • `C:\Windows\system`
  • `C:\Windows\system32`
  • `All dirs within the PATH var`

Additionally you can check any software that gets installed in the root directory (such as Python). Because if a folder is created in the root directory, it is writable for all authenticated users by default. And softwares like Python, Ruby, Perl etc. usually added to the PATH variable, which make their locations viable targets for DLL Hijacking if the DLL is not present at the system at all (PATH directories are the last ones that are consolidated while loading a .dll, see the Basic Principle section)

See also the GIF on the left side, which shows the process of analyzing some additional dirs with icacls

(SPOILER: sadly only `RX — read and execute access`-Permissions here … Nothing interesting for our purpose.

Step 3. Creating and compiling a “malicious” DLL

First of all we need to define the code of our very malicious DLL and save it to the `alert.cpp`-File:

#include <windows.h>BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpvReserved)
{
MessageBox(NULL, TEXT(“Greetings & Pwnings from risus :)”), TEXT(“Got ya!”), 0);
return 0;}

All this sneaky little thing does is raise an (alert)-message-box indicating that we are executing our arbitrary code.

alert.dll

The Box will look something like the box shown on the left.

After defining our DLL we need to compile the `alert.cpp`-File into a DLL. In order to do this we first need some additional libraries. I’m utilizing the following package for Ubuntu:

* `sudo apt install mingw-w64`

After installing we can head for compiling the .cpp into our .dll:

  • `i686-w64-mingw32-g++ -c -DBUILDING_EXAMPLE_DLL alert.cpp`
  • `i686-w64-mingw32-g++ -shared -o alert.dll alert.o -Wl, — out-implib,alert.a`

By now we have compiled our “malicious” DLL and are ready to place it on the target machine. I’ll leave that up to you. Once you’re done catch up with me in reading the next step:

Step 4. Exploit it!!11!

Once we have transmitted our malicious DLL we place it in the vulnerable path (in our case C:\Users\risusUser\Desktop\tools\Bginfo\ )

After playing around with the Bginfo-Application a bit we notice that according to the Procmon-Output, the `profapi.dll` is loaded directly after clicking the OK-Button on the right-lower corner of the UI. The following GIF shoudl hold any relevant information for you to comprehend what happens:

If you ask yourself what’s the exact difference in the DLL-loading process with and without our exploitation I have 2 additional images of the events captured by procmon during the loading procedure that should help to comprehend what goes on behind the scenes of that high-quality GIF:

Valid (non-exploiting) loading procedure of the `profapi.dll`. As you clearly see the system tries to load it first from the path C:\Users\risusUser\Desktop\tools\Bginfo\ and fails. After that the system loads the valid .dll from C:\Windows\System32\

Valid profapi.dll loading prcoedure

Malicious (exploiting) loading procedure of the `profapi.dll`. As you clearly see the system loads the malicious `profapi.dll` from the path C:\Users\risusUser\Desktop\tools\Bginfo\

By now we have successfully exploited a basic DLL Hijacking. (yeah, yeah — I admit it, it was a constructed example for this post, but hey technically it counts) Out in the wild these weaknesses do occur and can be exploited in a similar way. Especially the IKE and AuthIP IPsec Keyring Modules Service (IKEEXT) Missing DLL vulnerability gained some attention in the past.

Retrospective

Yeah I know, you successfully exploited your target, why am I still talking? Just a couple of things I wanted to add to the presented points:

  • One thing to mention (cuz it is easy to overlook) is that executables that need to be started manually aswell as running processes can be used to Hijack a DLL.
  • In case of a running process you probably will need to restart the process to kick off your Exploitation, if you’re exploiting a executable that needs to be started manually (or maybe by a scheduled task) you just have to wait till something/-one privileged starts that thing and kicks off your exploit.
  • Preparing a DLL Hijacking Attack means to fiddle quite a bit around with the processes/executables — I’d recommend to try and built up a local VM to test things out and then evaluate it on the target.

Thanks for sticky round with me through this not-so-short post that pretty much sums up constructed example to a long known vulnerability.

So basically no wikileaks action goin on here.

Cheers & cya next time,

Risus 0x3A 0x29

Resources

Shout out to the high-quality blogposts and information sources I used to comprehend this myself (I admit it it is basically a copy-paste of knowledge, sorry)

--

--