Introducción a Detours
Detours es un framwork desarrollado por Microsoft para interceptar funciones de API, compatible con arquitecturas x86 y x64, y según la documentación, también soporta ARM y ARM64 en Windows. Esta guía explica cómo encapsular y utilizar Detours para aplicar hooks en funciones de x64 desde Python, abordando la compilación y el uso en C++.
Compilación de Detours
El repositorio de Detours en GitHub no incluye documentación detallada de compilación, solo se menciona en el README que se debe usar la línea de comandos de Visual Studio. Para compilar, se recomienda abrir la consola de herramientas adecuada (x86 o x64 desde el menú de inicio), navegar al directorio fuente y ejecutar nmake. Esto generará archivos en los directorios bin.X64 y lib.X64.
Resolución de errores comunes
Durante la compilación, puede aparecer el error 'sn' no se reconoce como un comando interno o externo. Esto se debe a que la herramienta sn (para gestión de claves y firmas) no está en la variable de entorno PATH. Se puede solucionar temporalmente con el comando set path para incluir la ruta del SDK de Windows, como se muestra a continuación:
set path=C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\x64;%path%
Luego, ejecutar nmake o nmake all para iniciar la compilación.
Compilación en modo Debug
Para generar una versión Debug con archivos PDB, se debe establecer la variable de entorno DETOURS_CONFIG a Debug antes de compilar:
set DETOURS_CONFIG=Debug
nmake
Esto creará un directorio lib.X64Debug con las bibliotecas correspondientes.
Creación de un DLL para hooks
Detours simplifica el hooking mediante funciones específicas. A continuación, se muestra un ejemplo de código C++ que encapsula las operaciones de hook y unhook. Se han renombrado variables y funciones para mayor claridad en español, manteniendo la lógica original:
#include "detours.h"
unsigned long EstablecerHook(void** punteroOriginal, void* nuevaFuncion) {
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(punteroOriginal, nuevaFuncion);
DetourTransactionCommit();
return 0;
}
unsigned long RemoverHook(void** punteroOriginal, void* nuevaFuncion) {
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(punteroOriginal, nuevaFuncion);
DetourTransactionCommit();
return 0;
}
Aquí, punteroOriginal es un puntero doble a la función objetivo, y nuevaFuncion es el puntero a la función de reemplazo. En C++, se puede pasar directamente el nombre de la función.
Integración de bibliotecas y encabezados
Para incluir Detours en un proyecto de Visual Studio, se deben configurar las rutas de encabezados y bibliotecas. Los encabezados se agregan en las propiedades del proyecto: Configuración de propiedades -> C/C++ -> General -> Directorios adicionales de inclusión, usando $(ProjectDir) para referenciar el directorio del proyecto.
Las bibliotecas se enlazan mediante directivas #pragma en el código, lo que permite seleccionar versiones Debug o Release según la configuración:
#ifdef _DEBUG
#pragma comment(lib, "detoursd.lib")
#else
#pragma comment(lib, "detours.lib")
#endif
#ifdef _WIN64
#pragma comment(lib, "detours64.lib")
#else
#pragma comment(lib, "detours32.lib")
#endif
Esto garantiza que se utilice la biblioteca correcta dependiendo de la arquitectura y el modo de compilación.
Explicación del puntero doble en el hooking
La función DetourAttach requiere un puntero doble porque modifica internamente la dirección de la función original. Al hooking, Detours redirige el puntero proporcionado a una nueva función intermedia, lo que evita recursiones infinitas al llamar a la función original desde el hook. Por ejemplo, después de aplicar el hook, el valor del puntero cambia, permitiendo invocar la versión original sin conflictos.
Uso en Python
Para integrar Detours con Python, se puede crear un DLL basado en el código C++ anterior y llamarlo desde Python mediante bibliotecas como ctypes. Esto permite aplicar hooks en funciones x64 dentro de procesos de Python, facilitando tareas como el registro de llamadas o la modificación de comportamientos en tiempo de ejecución.