
Desenganche adecuado de la sección .text de ntdll mediante API nativa. A diferencia de otros desenganchadores, esto no deja 2 ntdlls cargados. Compatible con x86/x64/wow64.
Desenganche adecuado de la sección .text de ntdll mediante API nativa. Compatible con x86/x64/wow64.
El programa recorre el PEB para localizar la dirección base de ntdll.dll y analiza manualmente la tabla de exportación PE para resolver las funciones de la API NT sin tocar la Tabla de Direcciones de Importación. Luego usa NtOpenFile para abrir el ntdll.dll limpio desde el disco, crea un objeto de sección con NtCreateSection, y lo asigna en el proceso con NtMapViewOfSection para obtener una fuente de desenganche sin cargar realmente un segundo dll mediante LoadLibrary. La sección .text enganchada se cambia a PAGE_EXECUTE_READWRITE mediante NtProtectVirtualMemory, el .text limpio se copia sobre el enganchado con un memcpy personalizado, y luego se restaura la protección a los indicadores originales. Después de una verificación byte a byte de que el desenganche funcionó, la copia limpia se desasigna correctamente con NtUnmapViewOfSection para que no quede un segundo ntdll cargado en memoria.
La mayoría del código de desenganche público está literalmente copiado y pegado de la misma fuente basura (como el ejemplo de ired.team y prácticamente todos los desenganchadores de código abierto en github) y tiene problemas masivos que lo hacen inútil contra cualquier EDR real. Usan VirtualProtect en lugar de API nativas, lo que anula todo el propósito porque estás llamando a funciones enganchadas para desenganchar funciones; establecen permisos RWX en la sección .text, lo cual es un IOC masivo que los EDR marcan inmediatamente; y no desasignan realmente la copia limpia porque CloseHandle en una asignación de sección no libera la memoria. Necesitas UnmapViewOfFile o NtUnmapViewOfSection, pero todos olvidan esta parte, por lo que dejan dos copias de ntdll cargadas en el proceso, lo cual es básicamente un letrero de neón gigante que dice "soy malware". También intentan usar FreeLibrary en el ntdll principal, lo que ni siquiera funciona y causa fugas de identificadores, además cambian la protección a RWX dos veces innecesariamente cuando una vez es suficiente si la restauras correctamente.
Esta implementación corrige los errores comunes en el código de desenganche público mediante el uso de API nativas en todo momento (NtOpenFile, NtCreateSection, NtMapViewOfSection, NtProtectVirtualMemory), desasignando correctamente la copia limpia con NtUnmapViewOfSection para evitar dejar dos copias de ntdll cargadas, no usando FreeLibrary en el ntdll principal, y verificando el éxito mediante comparación de memoria. Sin embargo, NO evita los IOC fundamentales que detectan los EDR modernos. Usar NtOpenFile en C:\Windows\System32\ntdll.dll es un IOC que se registra; NtCreateSection con SEC_IMAGE apuntando a ntdll.dll se rastrea mediante ETW; modificar la protección de memoria en la sección .text de ntdll es una gran bandera roja incluso con API nativas; y escribir en .text es detectable mediante callbacks de escritura de memoria. Esta técnica es bien conocida y los EDR modernos como CrowdStrike y SentinelOne tienen firmas para todo el patrón. Los EDR avanzados como Microsoft Defender for Endpoint y Elastic ya ni siquiera usan ganchos en modo usuario, ya que dependen de callbacks del kernel y telemetría ETW, por lo que desenganchar no hace literalmente nada contra ellos. Esto funciona contra EDR básicos que solo usan ganchos en línea y productos de seguridad más antiguos, pero falla contra cualquier cosa con componentes de modo kernel o análisis de comportamiento. Mejores alternativas incluyen syscalls directos donde nunca llamas a funciones enganchadas en primer lugar, heaven's gate para cruce de límite wow64, extracción manual de syscalls de .text de ntdll en tiempo de ejecución, o simplemente evitar APIs sospechosas por completo, ya que desenganchar en 2024/2025 es generalmente una técnica muerta contra EDR empresarial real.
Funciona en procesos nativos x64, procesos nativos x86 y procesos wow64 (x86 en Windows x64). Detecta automáticamente wow64 y usa el directorio del sistema correcto (System32 vs SysWOW64) para que no tengas que pensar en ello.
Solo se toca la sección .text de ntdll.dll porque ahí es donde reside todo el código de función real y donde se colocan los ganchos EDR como ganchos de función en línea (instrucciones jmp en los prólogos de funciones). Otras secciones como .data y .rdata se dejan intactas porque no hay razón para tocarlas y solo crea más IOCs sin beneficio.
cl /EHsc /std:c++17 main.cpp /Fe:unhook.exe
o lo que sea, cualquier compilador moderno de C++ funciona. necesita windows.h y winternl.h.
El acceso no autorizado a sistemas informáticos es ilegal. Úselo en sistemas que posea o para los que tenga autorización de prueba. La prisión federal es real.
El código usa la macro CONTAINING_RECORD para recorrer las listas LDR correctamente, accede al PEB mediante registros de segmento (gs en x64, fs en x86), realiza una búsqueda codificada de la sección .text mediante comparación de nombres que podría ser más elegante pero funciona, maneja errores mediante códigos NTSTATUS y la macro NT_SUCCESS, y envuelve las operaciones de memoria en SEH try/except por seguridad. Si no puedes leer C++ y entender los internos del formato PE, probablemente no deberías estar usando esto de todos modos.