Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
UnhookMe — Resolvedor y desenganchador dinámico de la API de Windows que detecta y restaura funciones enganchadas (IAT, EAT, parches en línea) para invocar llamadas al sistema no monitoreadas desde malware de Red Team. | Kitploit
Herramientas/GitHubGitHub/mgeeky/unhookme
Herramientas DefensivasRed TeamingDesarrollo de Payloads
GitHubmgeeky/unhookme

UnhookMe

Resolvedor y desenganchador dinámico de la API de Windows que detecta y restaura funciones enganchadas (IAT, EAT, parches en línea) para invocar llamadas al sistema no monitoreadas desde malware de Red Team.

Ver Repositorio
348488hace 4 añosRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

UnhookMe - Resolvedor de imports que se desengancha dinámicamente

En la era de los AVs y EDRs intrusivos que introducen parches en caliente a los procesos en ejecución para cumplir con sus requisitos de óptica mejorada, los adversarios modernos deben disponer de una herramienta robusta para sortear estos vigilantes. La implementación propuesta de un resolvedor de imports dinámico capaz de desenganchar funciones utilizadas sobre la marcha es un paso más hacia el fortalecimiento de los esfuerzos de resistencia del adversario.

La solución que propongo aquí es cambiar el uso de imports de WinAPI resueltos por el enlazador, que permanecen visibles en los encabezados PE del ejecutable compilado (específicamente en la Tabla de Direcciones de Importación), para favorecer un enfoque totalmente dinámico que insista en resolver los imports solo de forma dinámica. Dicho resolvedor dinámico puede equiparse con una lógica de desenganche que ocurre en segundo plano, sin ningún tipo de guía por parte del operador.


Ejemplo de uso más simple

Así es como puedes asegurarte de llamar a MessageBoxW desenganchada y sin monitorización:

    RESOLVE(user32, MessageBoxW);
    _MessageBoxW(0, L"Look Ma! I'm unhooked!", L"Third - Unhooked", 0);

Toda la magia ocurre dentro de la macrodefinición RESOLVE, que construye un objeto ImportResolver<T> llamado _MessageBoxW.


Demostración

Animación de demostración de Unhookme

Así es como funciona el ejemplo de UnhookMe:

  1. Primero nos presenta un MessageBoxW que no está sujeto a enganche.
  2. Luego enganchamos nosotros mismos el prólogo de MessageBoxW para que siempre devuelva 0 sin mostrar su mensaje.
  3. Finalmente, resolvemos MessageBoxW dinámicamente usando el resolvedor UnhookingImportResolver, que detectará los parches aplicados al prólogo y restaurará los bytes originales, desenganchando efectivamente la funcionalidad de MessageBoxW.

Mientras se muestran los cuadros de mensaje, estas son las líneas de registro impresas en la salida estándar de la consola:

[~] Resolved symbol kernel32.dll!CreateFileA
[~] Resolved symbol kernel32.dll!ReadProcessMemory
[~] Resolved symbol kernel32.dll!MapViewOfFile
[~] Resolved symbol kernel32.dll!VirtualProtectEx
[#] Found trampoline hook in symbol: MessageBoxW . Restored original bytes from file.
[~] Resolved symbol user32.dll!MessageBoxW

¿Cómo usarlo?

Hay un total de 5 archivos de código fuente/encabezados C++ que tu solución necesita incluir. Sin embargo, tu archivo principal del programa solo necesita incluir dos encabezados obligatorios, como se detalla a continuación.

  • resolver.h - encabezado que contiene la mayor parte de la implementación de UnhookingImportResolver y prácticas macrodefiniciones.
  • resolver.cpp - código fuente con las opciones globales definidas.
  • usings.h - un archivo de encabezado grande y engorroso que contiene decenas de definiciones de tipo using para WinAPIs de uso común.
  • PE.cpp - archivo de código fuente del analizador PE personalizado.
  • PE.h - archivo de encabezado del analizador PE personalizado.

Encabezados requeridos

Tu programa solo requerirá la inclusión de dos encabezados:

#include "usings.h"
#include "resolver.h"

Opciones globales

Hay un par de opciones globales que se pueden cambiar y que afectan la forma en que el Resolvedor funciona o informa su actividad. Estas se definen al principio del archivo resolver.cpp:

Opciones globales del Resolvedor:

  • globalQuietOption - establecer a true si no deseas ningún tipo de salida.
  • globalVerboseOption - establecer a true si deseas una salida detallada.
  • globalAntiSplicingOption - desenganchar las funciones resueltas si están enganchadas.
  • globalLogFilePath - dónde redirigir las líneas de registro de salida. Si está vacío, se usa stdout.
bool globalQuietOption = false;
bool globalVerboseOption = true;
bool globalAntiSplicingOption = true;

wchar_t globalLogFilePath[MAX_PATH] = L"";

Especificación de tipo de API personalizada

Para usar el Resolvedor, primero se debe declarar un tipo de puntero a función con una declaración using de forma estricta:

    using fn_FunctionName = ReturnType WINAPI (
        ParamType1 paramName1,
        ...,
        ParamTypeN paramNameN,
    );

Este repositorio viene con un archivo de encabezado usings.h que contiene definiciones de tipo using predefinidas para decenas de APIs populares de Windows.

El FunctionName corresponderá a la WinAPI que queremos que ImportResolver resuelva y ese puntero a función debe estar marcado con la convención de llamada WINAPI ( __stdcall en x86 y __fastcall en x64). El ReturnType debe preceder al modificador de tipo WINAPI.

Resolución y uso de funciones

Una vez que se haya definido el tipo de puntero a función como se especificó anteriormente, podremos usarlo de la siguiente manera:

    RESOLVE(libraryName, FunctionName);
    ReturnType output = _FunctionName(param1, ..., paramN);

La macro RESOLVE se encarga de instanciar el objeto plantilla ImportResolver y ajustar el nombre de la librería especificada.

El Resolvedor introduce varias macrodefiniciones más que ofrecen una invocación de constructor fácil de usar en diversas circunstancias:

#define RESOLVE(mod, func)                    RESOLVE_PARAMETERIZED(mod, func, ::globalVerboseOption, ::globalAntiSplicingOption)
#define RESOLVE_NO_UNHOOK(mod, func)          RESOLVE_PARAMETERIZED(mod, func, ::globalVerboseOption, false)

#define RESOLVE_VERBOSE_UNHOOK(mod, func)     RESOLVE_PARAMETERIZED(mod, func, true, true)
#define RESOLVE_VERBOSE_NOUNHOOK(mod, func)   RESOLVE_PARAMETERIZED(mod, func, true, false)
#define RESOLVE_NOVERBOSE_UNHOOK(mod, func)   RESOLVE_PARAMETERIZED(mod, func, false, true)
#define RESOLVE_NOVERBOSE_NOUNHOOK(mod, func) RESOLVE_PARAMETERIZED(mod, func, false, false)

Constructor del Resolvedor:

    template<typename Ret, typename ...Args>
    ImportResolver<Ret WINAPI(Args...)>(
            std::string dllName,
            std::string funcName,
            bool _verbose = false,
            bool _unhook = false,
            bool *_wasItHooked = nullptr
        )

¿Cómo funciona?

El resolvedor subyacente utiliza un analizador de encabezados PE personalizado que procesa cada módulo DLL referenciado para mapear sus exportaciones y verificar la integridad de los encabezados PE del módulo, así como la integridad de los bytes de código auxiliar de la función referenciada.

La idea es la siguiente:

Descargar herramienta