Procedimiento de Inyección Clásica de DLL en Procesos de Windows

Introducción a la Inyección de DLL

La inyección de DLL es una técnica que permite cargar una biblioteca de vínculos dinámicos (DLL) externa en el espacio de memoria de otro proceso en ejecución. Esto se logrra mapeando el contenido de la DLL dentro de la dirección virtual del proceso objetivo, permitiendo así la ejecución de su código dentro de ese contexto. Esta técnica tiene múltiples aplicaciones, tanto legítimas (depuración, extensión de funcionalidades de software) como maliciosas (espionaje, persistencia de malware).

Creación de una DLL Simple

Para este ejemplo, se crea una DLL que muestra un cuadro de diálogo cuando se carga en un proceso. A continuación se presenta el código modificado.

Archivo de encabezado (dll.h):

#ifndef DLL_HEADER_GUARD
#define DLL_HEADER_GUARD

#ifdef BUILDING_DLL_EXPORT
#define API_EXPORT __declspec(dllexport)
#else
#define API_EXPORT __declspec(dllimport)
#endif

class API_EXPORT DemoClass {};

#endif

Archivo de implementación (dllmain.cpp):

#include "dll.h"
#include <windows.h>

BOOL WINAPI DllMain(HINSTANCE hModule, DWORD reason, LPVOID reserved)
{
    if (reason == DLL_PROCESS_ATTACH)
    {
        DisableThreadLibraryCalls(hModule);
        MessageBoxA(NULL, "¡Carga exitosa de la DLL!", "Demo de Inyección", MB_OK | MB_ICONINFORMATION);
    }
    else if (reason == DLL_PROCESS_DETACH)
    {
        // Limpieza si es necesaria
    }
    return TRUE;
}

Se compila este proyecto para obtener demo.dll.

Implementación del Inyector

El proceso de inyección clásico se divide en cuatro fases principales, que se implementan mediante funciones específicas de la API de Windows.

  1. Apertura del proceso objetivo: Se obtiene un identificador con permisos adecuados usando OpenProcess.
  2. Asignación de memoria en el proceso remoto: Se reserva un espacio contiguo con VirtualAllocEx.
  3. Escritura de la ruta de la DLL en la memoria remota: Se transfiere la cadena de caracteres mediante WriteProcessMemory.
  4. Creación de un hilo remoto: Se ejecuta LoadLibraryA como punto de entrada del nuevo hilo, pasando la dirección donde se escribió la ruta de la DLL.

Esquema del código del inyector:

#include <windows.h>
#include <tlhelp32.h>
#include <cstdio>

// Función auxiliar para buscar un proceso por nombre
DWORD FindProcessId(const char* processName)
{
    PROCESSENTRY32 entry;
    entry.dwSize = sizeof(PROCESSENTRY32);

    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
    if (Process32First(snapshot, &entry))
    {
        do
        {
            if (!_stricmp(entry.szExeFile, processName))
            {
                CloseHandle(snapshot);
                return entry.th32ProcessID;
            }
        } while (Process32Next(snapshot, &entry));
    }
    CloseHandle(snapshot);
    return 0;
}

int main(int argc, char* argv[])
{
    const char* dllPath = "C:\\Ruta\\demo.dll"; // Ruta completa a la DLL
    DWORD pathLen = strlen(dllPath) + 1;

    // 1. Obtener el PID del objetivo (ej. "notepad.exe")
    DWORD targetPid = FindProcessId("notepad.exe");
    if (!targetPid)
    {
        printf("Proceso objetivo no encontrado.\n");
        return 1;
    }

    // 2. Abrir el proceso
    HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, targetPid);
    if (!hProcess)
    {
        printf("Error al abrir el proceso (Código: %lu).\n", GetLastError());
        return 1;
    }

    // 3. Asignar memoria en el proceso remoto
    LPVOID remoteBuffer = VirtualAllocEx(hProcess, NULL, pathLen, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    if (!remoteBuffer)
    {
        printf("Error al asignar memoria remota.\n");
        CloseHandle(hProcess);
        return 1;
    }

    // 4. Escribir la ruta de la DLL en la memoria asignada
    WriteProcessMemory(hProcess, remoteBuffer, dllPath, pathLen, NULL);

    // 5. Obtener la dirección de LoadLibraryA
    HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
    LPTHREAD_START_ROUTINE loadLibAddr = (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "LoadLibraryA");

    // 6. Crear el hilo remoto que ejecutará LoadLibraryA
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, loadLibAddr, remoteBuffer, 0, NULL);
    if (hThread)
    {
        WaitForSingleObject(hThread, INFINITE);
        printf("Inyección completada.\n");
        CloseHandle(hThread);
    }
    else
    {
        printf("Error al crear el hilo remoto.\n");
    }

    // 7. Liberar recursos
    VirtualFreeEx(hProcess, remoteBuffer, 0, MEM_RELEASE);
    CloseHandle(hProcess);

    return 0;
}

Verificación de la Inyección

Tras ejecutar el inyector, se puede usar una herramienta como Process Explorer o listDLLs para inspeccionar los módulos cargados en el proceso notepad.exe. La presencia de demo.dll en la lista confirma que la técnica ha funcionado correctamente.

Etiquetas: inyección de DLL Windows API procesos Multithreading memoria remota

Publicado el 7-13 21:15