Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
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
EDRSandblast — Armamentiza controladores firmados vulnerables para evadir callbacks del kernel de EDR, callbacks de objetos, el proveedor ETW TI y ganchos de espacio de usuario para el volcado de memoria de LSASS y la extracción de credenciales. | Kitploit
Herramientas/GitHubGitHub/wavestone-cdt/edrsandblast
Herramientas DefensivasEscalada de PrivilegiosExplotaciónPruebas de PenetraciónRed Teaming
GitHubwavestone-cdt/edrsandblast

EDRSandblast

Armamentiza controladores firmados vulnerables para evadir callbacks del kernel de EDR, callbacks de objetos, el proveedor ETW TI y ganchos de espacio de usuario para el volcado de memoria de LSASS y la extracción de credenciales.

Ver Repositorio
1.8k320hace 2 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

EDRSandBlast

EDRSandBlast es una herramienta escrita en C que aprovecha un controlador firmado vulnerable para eludir las detecciones de EDR (devoluciones de llamada de rutina de notificación, devoluciones de llamada de objetos y el proveedor ETW TI) y las protecciones de LSASS. También se implementan múltiples técnicas de unhooking en el espacio de usuario para evadir la monitorización del espacio de usuario.

A la fecha del lanzamiento, se utilizó una combinación de técnicas de espacio de usuario (--usermode) y espacio de kernel (--kernelmode) para volcar la memoria de LSASS bajo el escrutinio de EDR, sin ser bloqueado ni generar eventos relacionados con "OS Credential Dumping" en la consola del producto (en la nube). Las pruebas se realizaron en 3 productos EDR distintos y fueron exitosas en cada caso.

Descripción

Bypass de EDR mediante eliminación de rutinas de notificación del kernel

Los productos EDR utilizan devoluciones de llamada de "Rutinas de Notificación" del kernel en Windows para ser notificados por el kernel de la actividad del sistema, como la creación de procesos y subprocesos y la carga de imágenes (exe / DLL).

Estas devoluciones de llamada del kernel se definen desde el espacio del kernel, generalmente desde el controlador que implementa las devoluciones de llamada, utilizando varias API documentadas (nt!PsSetCreateProcessNotifyRoutine, nt!PsSetCreateThreadNotifyRoutine, etc.). Estas API agregan rutinas de devolución de llamada proporcionadas por el controlador a arreglos no documentados de rutinas en el espacio del kernel:

  • PspCreateProcessNotifyRoutine para la creación de procesos
  • PspCreateThreadNotifyRoutine para la creación de subprocesos
  • PspLoadImageNotifyRoutine para la carga de imágenes

EDRSandBlast enumera las rutinas definidas en esos arreglos y elimina cualquier rutina de devolución de llamada vinculada a una lista predefinida de controladores EDR (más de 1000 controladores de productos de seguridad compatibles, consulte la sección de detección de controladores EDR). La enumeración y eliminación son posibles mediante la explotación de una primitiva arbitraria de lectura/escritura de memoria del kernel proporcionada por la explotación de un controlador vulnerable (consulte la sección de controladores vulnerables). Los desplazamientos de los arreglos mencionados se recuperan utilizando múltiples técnicas; consulte la sección de desplazamientos.

Bypass de EDR mediante eliminación de devoluciones de llamada de objetos

Los productos EDR (e incluso EPP) a menudo registran "devoluciones de llamada de objetos" mediante el uso de la API del kernel nt!ObRegisterCallbacks. Estas devoluciones de llamada permiten que el producto de seguridad sea notificado en cada generación de identificadores en tipos de objetos específicos (ahora Windows admite devoluciones de llamada de objetos relacionados con procesos, subprocesos y escritorios). Puede ocurrir una generación de identificadores al abrir un objeto (llamada a OpenProcess, OpenThread, etc.) así como al duplicar un identificador (llamada a DuplicateHandle, etc.).

Al ser notificado por el kernel en cada una de estas operaciones, un producto de seguridad puede analizar la legitimidad de la creación del identificador (por ejemplo, un proceso desconocido está tratando de abrir LSASS), e incluso bloquearlo si se detecta una amenaza.

En cada registro de devolución de llamada mediante ObRegisterCallbacks, se agrega un nuevo elemento a la lista doblemente enlazada CallbackList presente en el objeto _OBJECT_TYPE que describe el tipo de objeto afectado por la devolución de llamada (ya sea un Proceso, un Subproceso o un Escritorio). Desafortunadamente, estos elementos se describen mediante una estructura que no está documentada ni publicada en archivos de símbolos por Microsoft. Sin embargo, estudiarla a partir de varias versiones de ntoskrnl.exe parece indicar que la estructura no cambió entre (al menos) las compilaciones 10240 y 22000 de Windows 10 (de 2015 a 2022).

La estructura mencionada, que representa un registro de devolución de llamada de objeto, es la siguiente:```C typedef struct OB_CALLBACK_ENTRY_t { LIST_ENTRY CallbackList; // linked element tied to _OBJECT_TYPE.CallbackList OB_OPERATION Operations; // bitfield : 1 for Creations, 2 for Duplications BOOL Enabled; // self-explanatory OB_CALLBACK* Entry; // points to the structure in which it is included POBJECT_TYPE ObjectType; // points to the object type affected by the callback POB_PRE_OPERATION_CALLBACK PreOperation; // callback function called before each handle operation POB_POST_OPERATION_CALLBACK PostOperation; // callback function called after each handle operation KSPIN_LOCK Lock; // lock object used for synchronization } OB_CALLBACK_ENTRY;

root@kitploit:~
La estructura `OB_CALLBACK` mencionada anteriormente también está sin documentar, y se define de la siguiente manera:```C
typedef struct OB_CALLBACK_t {
    USHORT Version;                           // usually 0x100
    USHORT OperationRegistrationCount;        // number of registered callbacks
    PVOID RegistrationContext;                // arbitrary data passed at registration time
    UNICODE_STRING AltitudeString;            // used to determine callbacks order
    struct OB_CALLBACK_ENTRY_t EntryItems[1]; // array of OperationRegistrationCount items
    WCHAR AltitudeBuffer[1];                  // is AltitudeString.MaximumLength bytes long, and pointed by AltitudeString.Buffer
} OB_CALLBACK;

Para deshabilitar las devoluciones de llamada de objetos registradas por EDR, se implementan tres técnicas en EDRSandblast; sin embargo, solo una está habilitada por el momento.

Usando el campo Enabled de OB_CALLBACK_ENTRY

Esta es la técnica predeterminada habilitada en EDRSandblast. Para detectar y deshabilitar las devoluciones de llamada de objetos relacionadas con EDR, se examina la lista CallbackList ubicada en los objetos _OBJECT_TYPE vinculados a los tipos Process y Thread. Ambos _OBJECT_TYPEs son señalados por símbolos globales públicos en el kernel, PsProcessType y PsThreadType.

Se asume que cada elemento de la lista se ajusta a la estructura OB_CALLBACK_ENTRY descrita anteriormente (suposición que parece cumplirse al menos en todas las versiones de Windows 10 al momento de escribir esto). Las funciones definidas en los campos PreOperation y PostOperation se localizan para verificar si pertenecen a un controlador EDR y, de ser así, las devoluciones de llamada simplemente se deshabilitan alternando el indicador Enabled.

Aunque es una técnica bastante segura, tiene el inconveniente de basarse en una estructura no documentada; para reducir el riesgo de manipulación insegura de esta estructura, se realizan comprobaciones básicas para validar que algunos campos tengan los valores esperados:

  • Enabled es TRUE o FALSE (no te rías, un BOOL es un int, por lo que podría ser cualquier cosa que no sea 1 o 0);
  • Operations es OB_OPERATION_HANDLE_CREATE, OB_OPERATION_HANDLE_DUPLICATE o ambos;
  • ObjectType apunta a PsProcessType o PsThreadType.

Desvinculando la CallbackList de hilos y procesos

Otra estrategia que no depende de una estructura no documentada (y por lo tanto es teóricamente más robusta frente a cambios en el kernel NT) es la desvinculación de toda la CallbackList tanto para procesos como para hilos. El objeto _OBJECT_TYPE es el siguiente:```C struct _OBJECT_TYPE { LIST_ENTRY TypeList; UNICODE_STRING Name; [...] _OBJECT_TYPE_INITIALIZER TypeInfo; [...] LIST_ENTRY CallbackList; }

root@kitploit:~
Haciendo que los punteros `Flink` y `Blink` de la `LIST_ENTRY` del `CallbackList` apunten a
la `LIST_ENTRY` misma, se vacía efectivamente la lista. Dado que la estructura `_OBJECT_TYPE`
está publicada en los símbolos del kernel, la técnica no depende de desplazamientos/estructuras codificados.
Sin embargo, tiene algunos inconvenientes.

El primero es no poder deshabilitar solo las devoluciones de llamada del EDR; de hecho, la técnica afecta
a todas las devoluciones de llamada de objetos que pudieran haber sido registradas por software "legítimo". No obstante,
cabe señalar que las devoluciones de llamada de objetos no son utilizadas por ningún componente preinstalado
en Windows 10 (en el momento de escribir esto), por lo que deshabilitarlas no debería afectar la estabilidad
de la máquina (más aún si la desactivación es solo temporal).

El segundo inconveniente es que las operaciones de identificadores de procesos o hilos son realmente frecuentes (casi
continuas) en el funcionamiento normal del SO. Por lo tanto, si la primitiva de escritura en kernel utilizada
no puede realizar una escritura de `QWORD` de forma "atómica", existe una alta probabilidad de que el puntero
`_OBJECT_TYPE.CallbackList.Flink` sea accedido por el kernel en medio
de su sobrescritura. Por ejemplo, el controlador vulnerable MSI `RTCore64.sys` solo puede realizar
una escritura de `DWORD` a la vez, por lo que se necesitarán 2 IOCTL distintos para sobrescribir el puntero, entre
los cuales el kernel tiene una alta probabilidad de usarlo (lo que resulta en un bloqueo). Por otro lado,
el controlador vulnerable DELL `DBUtil_2_3.sys` puede realizar escrituras de tamaños arbitrarios en un solo
IOCTL, por lo que usar este método con él no corre el riesgo de causar un bloqueo.

#### Deshabilitar por completo las devoluciones de llamada de objetos
Una última técnica que encontramos fue deshabilitar por completo el soporte de devoluciones de llamada de objetos para hilos
y procesos. Dentro de la estructura `_OBJECT_TYPE` correspondiente a los tipos de proceso y
hilo reside un campo `TypeInfo`, que sigue la estructura documentada `_OBJECT_TYPE_INITIALIZER`.
Este último contiene un campo de bits `ObjectTypeFlags`, cuya bandera `SupportsObjectCallbacks`
determina si el tipo de objeto descrito (Proceso, Hilo, Escritorio, Token, Archivo, etc.)
admite o no el registro de devoluciones de llamada de objetos. Como se indicó anteriormente, solo los tipos de objeto Proceso, Hilo y
Escritorio admiten estas devoluciones de llamada en una instalación de Windows en el momento de escribir esto.

Dado que el bit `SupportsObjectCallbacks` es verificado por `ObpCreateHandle` o
`ObDuplicateObject` antes incluso de leer el `CallbackList` (y antes de ejecutar
las devoluciones de llamada, por supuesto), invertir el bit en tiempo de ejecución del kernel deshabilita efectivamente la ejecución
de todas las devoluciones de llamada de objetos.

El principal inconveniente del método es simplemente que *KPP* ("*PatchGuard*") monitorea la integridad
de algunas (¿todas?) las estructuras `_OBJECT_TYPE` y desencadena una [`comprobación de error 0x109`](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/bug-check-0x109---critical-structure-corruption)
con el parámetro 4 igual a `0x8`, lo que significa que se ha alterado una estructura de tipo de objeto.

Sin embargo, realizar la desactivación / reactivación (y la acción "maliciosa" intermedia) lo suficientemente
rápido debería ser suficiente para "adelantarse" a *PatchGuard* (a menos que tengas mala suerte y se realice una verificación
periódica justo en el momento equivocado).

### Bypass de EDR mediante desvinculación de devoluciones de llamada de minifiltros
El sistema Filter Manager de Windows permite que un EDR cargue un controlador "minifiltro" y
registre devoluciones de llamada para ser notificado de operaciones de E/S, como apertura de archivos,
lectura, escritura, etc.

Aquí hay un breve resumen de diferentes estructuras internas utilizadas por el filter manager:
- El Filter Manager establece un "marco" (`_FLTP_FRAME`) como su estructura raíz;
- Se crea una instancia de una estructura de "volumen" (`_FLT_VOLUME`) para cada "disco" gestionado por el
Filter Manager (pueden ser particiones, copias sombra, o especiales correspondientes a
named pipes o sistemas de archivos remotos);
- A cada controlador minifiltro registrado le corresponde una estructura de "filtro" (`_FLT_FILTER`),
que describe varias propiedades como sus operaciones compatibles;
- Estos minifiltros no están todos adjuntos a cada volumen; se crea una estructura de "instancia" (`_FLT_INSTANCE`)
para marcar cada una de las asociaciones filtro<->volumen;
- Los minifiltros registran funciones de devolución de llamada que se ejecutarán antes y/o después de
operaciones específicas (abrir archivo, escribir, leer, etc.). Estas devoluciones de llamada se describen en
estructuras `_CALLBACK_NODE`, y se puede acceder a ellas de diferentes maneras:
  - Una matriz de todos los `_CALLBACK_NODE` implementados por una instancia de un minifiltro
    se puede encontrar en la estructura `_FLT_INSTANCE`; la matriz está indexada por el código de "función mayor"
    del IRP, una constante que representa las operaciones manejadas por las
    devoluciones de llamada (`IRP_MJ_CREATE`, `IRP_MJ_READ`, etc.).
  - Además, todos los `_CALLBACK_NODE` implementados por instancias vinculadas a un volumen específico
    se agrupan en listas enlazadas, almacenadas en la matriz `_FLT_VOLUME.Callbacks.OperationLists`
    indexada por códigos de función mayor del IRP.

`EDRSandblast` recorre estas diferentes estructuras para detectar filtros que están
asociados con controladores relacionados con EDR, y se enumeran los nodos de devolución de llamada que contienen funciones
de monitoreo. Para deshabilitar su efecto, los nodos se desvinculan de sus
listas, haciéndolos temporalmente invisibles para el filter manager.

De esta manera, durante un período específico, el EDR puede ser completamente inconsciente de cualquier operación
de archivos. Un ejemplo básico sería la creación de un archivo de volcado de memoria de lsass en el disco,
que no desencadenaría ningún análisis del EDR y, por lo tanto, ninguna detección basada en el
archivo en sí.

### Bypass de EDR mediante desactivación del proveedor ETW Microsoft-Windows-Threat-Intelligence

El proveedor `ETW Microsoft-Windows-Threat-Intelligence` registra datos sobre los
usos de algunas API de Windows comúnmente utilizadas con fines maliciosos. Esto incluye la
API `nt!MiReadWriteVirtualMemory`, llamada por `nt!NtReadVirtualMemory` (que se
utiliza para volcar la memoria de `LSASS`) y monitoreada por la función `nt!EtwTiLogReadWriteVm`.

Los productos EDR pueden consumir los registros producidos por el proveedor `ETW TI` a través
de servicios o procesos que se ejecutan como, respectivamente,
`SERVICE_LAUNCH_PROTECTED_ANTIMALWARE_LIGHT` o
`PS_PROTECTED_ANTIMALWARE_LIGHT`, y asociados con un controlador `Early Launch Anti
Malware (ELAM)`.

Según lo publicado por
[`slaeryan` en una publicación de blog de `CNO Development Labs`](https://public.cnotools.studio/bring-your-own-vulnerable-kernel-driver-byovkd/exploits/data-only-attack-neutralizing-etwti-provider),
el proveedor `ETW TI` se puede deshabilitar por completo parcheando, en la memoria del kernel,
su atributo `ProviderEnableInfo` a `0x0`. Consulte la excelente publicación de blog mencionada anteriormente
para obtener más información sobre la técnica.

De manera similar a la eliminación de devoluciones de llamada del kernel, los desplazamientos necesarios de `ntoskrnl.exe`
(`nt!EtwThreatIntProvRegHandleOffset`, `GuidEntry` de `_ETW_REG_ENTRY`, y
`ProviderEnableInfo` de `_ETW_GUID_ENTRY`) se calculan en el
archivo `NtoskrnlOffsets.csv` para varias versiones del kernel de Windows.

### Bypass de EDR mediante bypass de hooking en el espacio de usuario
#### Cómo funciona el hooking en el espacio de usuario
Para monitorear fácilmente las acciones realizadas por los procesos, los productos EDR a menudo
implementan un mecanismo llamado *hooking en el espacio de usuario*. Primero, los productos EDR registran una devolución de llamada
del kernel (generalmente devoluciones de llamada de *carga de imagen* o *creación de proceso*, ver arriba) que les permite
ser notificados al inicio de cada proceso.

Cuando Windows carga un proceso, y antes de que realmente comience, el EDR puede
inyectar un DLL personalizado en el espacio de direcciones del proceso, que contiene su lógica
de monitoreo. Durante la carga, este DLL inyecta "*hooks*" al inicio de cada función que va a ser
monitoreada por el EDR. En tiempo de ejecución, cuando el proceso bajo vigilancia llama a las funciones monitoreadas,
estos hooks redirigen el flujo de control a algún código de supervisión
presente en el DLL del EDR, lo que le permite inspeccionar argumentos y valores de retorno de estas
llamadas.

La mayoría de las veces, las funciones monitoreadas son llamadas al sistema (como `NtReadVirtualMemory`,
`NtOpenProcess`, etc.), cuyas implementaciones residen en `ntdll.dll`. Interceptar llamadas a
funciones `Nt*` permite que los productos estén lo más cerca posible del límite entre el espacio de usuario y el
espacio del kernel (permaneciendo en el espacio de usuario), pero también se pueden monitorear funciones de algunos DLL de nivel superior.

A continuación se muestran ejemplos de la misma función, antes y después de ser enganchada por el producto EDR:```assembly
NtProtectVirtualMemory   proc near
	mov r10, rcx
	mov eax, 50h
	test byte ptr ds:7FFE0308h, 1
	jnz short loc_18009D1E5
	syscall
	retn
loc_18009D1E5:
	int 2Eh
	retn
NtProtectVirtualMemory   endp			
  • Soporte Comunitario: Únete a nuestra comunidad Raven en Discord para debatir, mejorar y contribuir al proyecto.
    • Donaciones: Si encuentras Raven útil para fines de reconocimiento o educativos, considera comprarnos un café para apoyar el desarrollo y la mejora continuos.```assembly NtProtectVirtualMemory proc near jmp sub_7FFC74490298 ; --> "hook", jump to EDR analysis function int 3 ; overwritten instructions int 3 ; overwritten instructions int 3 ; overwritten instructions test byte_7FFE0308, 1 ; <-- execution resumes here after analysis jnz short loc_7FFCB44AD1E5 syscall retn loc_7FFCB44AD1E5: int 2Eh retn NtProtectVirtualMemory endp
root@kitploit:~
#### Detección de hooks
Los hooks de espacio de usuario tienen la "debilidad" de estar ubicados en la memoria de espacio de usuario, lo que significa que son directamente observables y modificables por el proceso bajo escrutinio. Para detectar automáticamente los hooks en el espacio de direcciones del proceso, la idea principal es comparar las diferencias entre el DLL original en disco y la biblioteca residente en memoria, que ha sido potencialmente alterada por un EDR. Para realizar esta comparación, EDRSandblast sigue los siguientes pasos:
* La lista de todos los DLL cargados se enumera gracias a la `InLoadOrderModuleList` ubicada en el `PEB` (para evitar llamar a cualquier API que pudiera estar monitoreada y ser sospechosa)
* Para cada DLL cargado, su contenido en disco se lee y sus cabeceras se analizan. La biblioteca correspondiente, residente en memoria, también se analiza para identificar secciones, exportaciones, etc.
* Las reubicaciones del DLL se analizan y aplican, teniendo en cuenta la dirección base de la biblioteca cargada correspondiente. Esto permite que el contenido tanto de la biblioteca en memoria como del DLL del disco tengan exactamente el mismo contenido (en las secciones donde se aplican las reubicaciones), y así hacer que la comparación sea confiable.
* Se enumeran las funciones exportadas y se comparan los primeros bytes de las versiones "en memoria" y "en disco". Cualquier diferencia indica una alteración que se ha realizado después de que el DLL se cargó, y por lo tanto es muy probablemente un hook de EDR.

Nota: El proceso puede generalizarse para encontrar diferencias en cualquier lugar de las secciones no escribibles y no solo al inicio de las funciones exportadas, por ejemplo, si los productos EDR comienzan a aplicar hooks en medio de la función :) Por lo tanto, no es utilizado por la herramienta, esto se ha implementado en `findDiffsInNonWritableSections`.

Con el fin de evitar la monitorización realizada por estos hooks, múltiples técnicas son posibles, y cada una tiene beneficios y desventajas.

#### Bypass de hooks usando ... desenganche (unhooking)
El método más intuitivo para evitar la monitorización basada en hooks es eliminar los hooks. Dado que los hooks están presentes en la memoria a la que el propio proceso puede acceder, para eliminar un hook, el proceso puede simplemente:
* Cambiar los permisos en la página donde se encuentra el hook (RX -> RWX o RW)
* Escribir los bytes originales que se conocen gracias al contenido del DLL en disco
* Restaurar los permisos a RX

Este enfoque es bastante simple y se puede usar para eliminar todos los hooks detectados de una sola vez. Realizado por una herramienta ofensiva al inicio, esto permite que el resto del código sea completamente ajeno al mecanismo de hooking y funcione normalmente sin ser monitoreado.

Sin embargo, tiene dos desventajas principales. El EDR probablemente esté monitoreando el uso de `NtProtectVirtualMemory`, por lo que usarlo para cambiar los permisos de la página donde se han instalado los hooks es (al menos conceptualmente) una mala idea. Además, si un hilo es ejecutado por el EDR y verifica periódicamente la integridad de los hooks, esto también podría desencadenar alguna detección.

Para obtener detalles de implementación, consulte la ruta de código de la función `unhook()` cuando `unhook_method` es `UNHOOK_WITH_NTPROTECTVIRTUALMEMORY`.

**Nota importante: por simplicidad, esta técnica está implementada en EDRSandblast como la técnica base utilizada para *mostrar* las otras técnicas de bypass; cada una de ellas demuestra cómo obtener una versión no monitoreada de `NtProtectVirtualMemory`, pero realiza la misma operación después (desenganchar un hook específico).**

#### Bypass de hooks usando un trampolín personalizado
Para evitar un hook específico, es posible simplemente "saltar sobre" y ejecutar el resto de la función tal cual. Primero, los bytes originales de la función monitoreada, que han sido sobrescritos por el EDR para instalar el hook, deben recuperarse del archivo DLL. En nuestro ejemplo de código anterior, estos serían los bytes correspondientes a las siguientes instrucciones:```assembly
mov r10, rcx
mov eax, 50h

Identificar estos bytes es una tarea sencilla, ya que podemos realizar un diff limpio de las versiones en memoria y en disco de la biblioteca, como se describió anteriormente. Luego, ensamblamos una instrucción de salto diseñada para redirigir el flujo de control al código inmediatamente posterior al hook, en la dirección `NtProtectVirtualMemory + sizeof(overwritten_instructions)````assembly jmp NtProtectVirtualMemory+8

root@kitploit:~
Finalmente, concatenamos estos opcodes, los almacenamos en memoria (recién) ejecutable y mantenemos un puntero a ellos. Este objeto se llama un "*trampoline*" y puede usarse como un puntero a función, estrictamente equivalente a la función original `NtProtectVirtualMemory`.

El principal beneficio de esta técnica, como para todas las técnicas a continuación, es que el hook nunca se elimina, por lo que cualquier verificación de integridad realizada en los hooks por el EDR debería pasar. Sin embargo, requiere asignar memoria primero escribible y luego ejecutable, lo cual es típico de una asignación de shellcode, atrayendo así el escrutinio del EDR.

Para detalles de implementación, consulte la ruta de código de la función `unhook()` cuando `unhook_method` es `UNHOOK_WITH_INHOUSE_NTPROTECTVIRTUALMEMORY_TRAMPOLINE`. Recuerde que la técnica solo se muestra en nuestra implementación y, al final, se usa para **eliminar** hooks de la memoria, como todas las técnicas a continuación.

#### Bypass de hook usando el propio trampoline del EDR
El producto EDR, para que su hook funcione, debe guardar en algún lugar de la memoria los opcodes que ha eliminado. Peor aún (*o "mejor", desde el punto de vista del atacante*), para usar efectivamente las instrucciones originales, el EDR probablemente se ha asignado un *trampoline* en algún lugar para ejecutar la función original después de interceptar la llamada.

Este trampoline se puede buscar y utilizar como reemplazo de la función hookeada, sin necesidad de asignar memoria ejecutable, ni llamar a ninguna API excepto `VirtualQuery`, que muy probablemente no esté monitorizada por ser una función inocua.

Para encontrar el trampoline en memoria, recorremos todo el espacio de direcciones usando `VirtualQuery` buscando memoria confirmada y ejecutable. Para cada región de memoria de este tipo, la escaneamos buscando una instrucción de salto que apunte a la dirección siguiente a las instrucciones sobrescritas (`NtProtectVirtualMemory+8` en nuestro ejemplo anterior). El trampoline se puede usar entonces para llamar a la función hookeada sin activar el hook.

Esta técnica funciona sorprendentemente bien ya que recupera casi todos los trampolines en los EDR probados. Para detalles de implementación, consulte la ruta de código de la función `unhook()` cuando `unhook_method` es `UNHOOK_WITH_EDR_NTPROTECTVIRTUALMEMORY_TRAMPOLINE`.

#### Bypass de hook usando DLL duplicada
Otro método simple para obtener acceso a una versión no monitoreada de la función `NtProtectVirtualMemory` es cargar una versión duplicada de la librería `ntdll.dll` en el espacio de direcciones del proceso. Dado que dos DLL idénticas pueden cargarse en el mismo proceso, siempre que tengan nombres diferentes, simplemente podemos copiar el archivo legítimo `ntdll.dll` a otra ubicación, cargarlo usando `LoadLibrary` (o reimplementar el proceso de carga), y acceder a la función usando `GetProcAddress` por ejemplo.

Esta técnica es muy simple de entender e implementar, y tiene una posibilidad decente de éxito, ya que la mayoría de los productos EDR no reinstalan hooks en DLL recién cargadas una vez que el proceso está en ejecución. Sin embargo, el principal inconveniente es que copiar binarios firmados por Microsoft bajo un nombre diferente a menudo se considera sospechoso por los propios productos EDR.

Sin embargo, esta técnica está implementada en `EDRSandblast`. Para detalles de implementación, consulte la ruta de código de la función `unhook()` cuando `unhook_method` es `UNHOOK_WITH_DUPLICATE_NTPROTECTVIRTUALMEMORY`.

#### Bypass de hook usando syscalls directas
Para usar funciones relacionadas con llamadas al sistema, un programa puede reimplementar syscalls (en ensamblador) para llamar a las características correspondientes del SO sin tocar realmente el código en `ntdll.dll`, que podría estar monitoreado por el EDR. Esto evita completamente cualquier hooking en modo usuario realizado en funciones de syscall en `ntdll.dll`.

Esto, sin embargo, tiene algunos inconvenientes. Primero, implica poder conocer la lista de números de syscall de las funciones que el programa necesita, lo cual cambia para cada versión de Windows. Esto se mitiga implementando múltiples heurísticas que se sabe que funcionan en todas las versiones pasadas de Windows NT (ordenando las exportaciones `Zw*` de `ntdll`, buscando la instrucción `mov rax, #syscall_number` en la función `ntdll` asociada, etc.), y verificando que todas devuelvan el mismo resultado (consulte `Syscalls.c` para más detalles).

Además, las funciones que técnicamente no son syscalls (por ejemplo, `LoadLibraryX`/`LdrLoadDLL`) también podrían estar monitoreadas, y no pueden simplemente reimplementarse usando un syscall.

La técnica de syscalls directas está implementada en EDRSandblast. Como se dijo anteriormente, solo se usa para ejecutar `NtProtectVirtualMemory` de manera segura, y eliminar todos los hooks detectados.

Para detalles de implementación, consulte la ruta de código de la función `unhook()` cuando `unhook_method` es `UNHOOK_WITH_DIRECT_SYSCALL`.

### Explotación de drivers vulnerables
Como se dijo anteriormente, cada acción que necesita una lectura o escritura en memoria del kernel depende de un driver vulnerable para proporcionar esta primitiva. En EDRSanblast, agregar soporte para un nuevo driver que proporcione la primitiva de lectura/escritura se puede hacer "fácilmente", solo se deben implementar tres funciones:
* Una función `ReadMemoryPrimitive_DRIVERNAME(SIZE_T Size, DWORD64 Address, PVOID Buffer)`, que copia `Size` bytes desde la dirección del kernel `Address` al buffer de espacio de usuario `Buffer`;
* Una función `WriteMemoryPrimitive_DRIVERNAME(SIZE_T Size, DWORD64 Address, PVOID Buffer)`, que copia `Size` bytes desde el buffer de espacio de usuario `Buffer` a la dirección del kernel `Address`;
* Una función `CloseDriverHandle_DRIVERNAME()` que asegura que todos los handles al driver estén cerrados (necesario antes de la operación de desinstalación que es independiente del driver, por el momento).

Como ejemplo, dos drivers están actualmente soportados por EDRSandblast, `RTCore64.sys` (SHA256: `01AA278B07B58DC46C84BD0B1B5C8E9EE4E62EA0BF7A695862444AF32E87F1FD`) y `DBUtils_2_3.sys` (SHA256: `0296e2ce999e67c76352613a718e11516fe1b0efc3ffdb8918fc999dd76a73a5`). El siguiente código en `KernelMemoryPrimitives.h` debe ser actualizado si el driver vulnerable usado necesita ser cambiado, o si se implementa uno nuevo.```C
#define RTCore 0
#define DBUtil 1
// Select the driver to use with the following #define
#define VULN_DRIVER RTCore

#if VULN_DRIVER == RTCore
#define DEFAULT_DRIVER_FILE TEXT("RTCore64.sys")
#define CloseDriverHandle CloseDriverHandle_RTCore
#define ReadMemoryPrimitive ReadMemoryPrimitive_RTCore
#define WriteMemoryPrimitive WriteMemoryPrimitive_RTCore
#elif VULN_DRIVER == DBUtil
#define DEFAULT_DRIVER_FILE TEXT("DBUtil_2_3.sys")
#define CloseDriverHandle CloseDriverHandle_DBUtil
#define ReadMemoryPrimitive ReadMemoryPrimitive_DBUtil
#define WriteMemoryPrimitive WriteMemoryPrimitive_DBUtil
#endif

Detección de controladores y procesos EDR

Actualmente se utilizan múltiples técnicas para determinar si un controlador o proceso específico pertenece a un producto EDR o no.

Primero, el nombre del controlador puede simplemente usarse para ese propósito. De hecho, Microsoft asigna números específicos llamados "Altitudes" a todos los controladores que necesitan insertar callbacks en el kernel. Esto permite un orden determinista en la ejecución de los callbacks, independiente del orden de registro, pero basado únicamente en el uso del controlador. Se puede encontrar una lista de (fabricantes de) controladores que han reservado una altitude específica en MSDN. Como consecuencia, Microsoft ofrece una lista casi completa de nombres de controladores de seguridad vinculados a productos de seguridad, principalmente en las listas "FSFilter Anti-Virus" y "FSFilter Activity Monitor". Estas listas de nombres de controladores están incrustadas en EDRSandblast, así como contribuciones adicionales.

Además, los ejecutables y DLL de EDR suelen estar firmados digitalmente utilizando el certificado de firma del proveedor. Por lo tanto, verificar el firmante de un ejecutable o DLL asociado a un proceso puede permitir identificar rápidamente los productos EDR.

También, los controladores deben estar firmados directamente por Microsoft para poder cargarse en el espacio del kernel. Si bien el proveedor del controlador no es directamente el firmante del controlador en sí, parece que el nombre del proveedor aún se incluye dentro de un atributo de la firma; sin embargo, esta técnica de detección aún está por investigar e implementar.

Finalmente, al enfrentarse a un EDR desconocido para EDRSandblast, el mejor enfoque es ejecutar la herramienta en modo "audit" y revisar la lista de controladores que han registrado callbacks del kernel; luego, el nombre del controlador se puede agregar a la lista, la herramienta se recompila y se vuelve a ejecutar.

Bypass de RunAsPPL

El mecanismo Local Security Authority (LSA) Protection, presentado por primera vez en Windows 8.1 y Windows Server 2012 R2, utiliza la tecnología Protected Process Light (PPL) para restringir el acceso al proceso LSASS. La protección PPL regula y restringe operaciones, como la inyección de memoria o el volcado de memoria de procesos protegidos, incluso desde un proceso que tenga el privilegio SeDebugPrivilege. Bajo el modelo de protección de procesos, solo los procesos que se ejecutan con niveles de protección más altos pueden realizar operaciones en procesos protegidos.

La estructura _EPROCESS, utilizada por el kernel de Windows para representar un proceso en la memoria del kernel, incluye un campo _PS_PROTECTION que define el nivel de protección de un proceso a través de sus atributos Type (_PS_PROTECTED_TYPE) y Signer (_PS_PROTECTED_SIGNER).

Al escribir en la memoria del kernel, el proceso EDRSandblast puede actualizar su propio nivel de protección a PsProtectedSignerWinTcb-Light. Este nivel es suficiente para volcar la memoria del proceso LSASS, ya que "domina" a PsProtectedSignerLsa-Light, el nivel de protección del proceso LSASS que se ejecuta con el mecanismo RunAsPPL.

EDRSandBlast implementa la autoprotección de la siguiente manera:

  • abrir un handle al proceso actual
  • filtrar todos los handles del sistema usando NtQuerySystemInformation para encontrar el handle abierto del proceso actual, y la dirección de la estructura EPROCESS del proceso actual en la memoria del kernel.
  • usar la vulnerabilidad de lectura/escritura arbitraria del controlador vulnerable para sobrescribir el campo _PS_PROTECTION del proceso actual en la memoria del kernel. Los desplazamientos del campo _PS_PROTECTION relativos a la estructura EPROCESS (definidos por la versión de ntoskrnl en uso) se calculan en el archivo NtoskrnlOffsets.csv.

Bypass de Credential Guard

Microsoft Credential Guard es una tecnología de aislamiento basada en virtualización, introducida en Windows 10 (edición Enterprise) de Microsoft, que evita el acceso directo a las credenciales almacenadas en el proceso LSASS.

Cuando Credential Guard está activado, se crea un proceso LSAIso (LSA Isolated) en Virtual Secure Mode, una característica que aprovecha las extensiones de virtualización de la CPU para proporcionar seguridad adicional de los datos en memoria. El acceso al proceso LSAIso está restringido incluso para un acceso con el contexto de seguridad NT AUTHORITY\SYSTEM. Al procesar un hash, el proceso LSA realiza una llamada RPC al proceso LSAIso y espera el resultado de LSAIso para continuar. Por lo tanto, el proceso LSASS no contendrá ningún secreto y, en su lugar, almacenará LSA Isolated Data.

Como se indica en la investigación original realizada por N4kedTurtle: "Wdigest se puede habilitar en un sistema con Credential Guard parcheando los valores de g_fParameter_useLogonCredential y g_IsCredGuardEnabled en la memoria". La activación de Wdigest provocará que se almacenen credenciales en texto claro en la memoria de LSASS para cualquier nuevo inicio de sesión interactivo (sin requerir un reinicio del sistema). Consulte la publicación original del blog de investigación para obtener más detalles sobre esta técnica.

EDRSandBlast simplemente hace que el PoC original sea un poco más amigable con la opsec y proporciona soporte para varias versiones de wdigest.dll (a través de desplazamientos calculados para g_fParameter_useLogonCredential y g_IsCredGuardEnabled).

Recuperación de desplazamientos (offsets)

Para realizar de manera confiable operaciones de bypass de monitoreo del kernel, EDRSandblast necesita saber exactamente dónde leer y escribir la memoria del kernel. Esto se logra utilizando desplazamientos (offsets) de variables globales dentro de la imagen objetivo (ntoskrnl.exe, wdigest.dll), así como el desplazamiento de campos específicos en estructuras cuyas definiciones son publicadas por Microsoft en archivos de símbolos. Estos desplazamientos son específicos para cada compilación de las imágenes objetivo y deben obtenerse al menos una vez para una versión de plataforma específica.

La elección de usar desplazamientos "hardcoded" en lugar de búsquedas de patrones para localizar las estructuras y variables utilizadas por EDRSandblast se justifica por el hecho de que las API no documentadas responsables de agregar/eliminar callbacks del kernel están sujetas a cambios y que cualquier intento de leer o escribir memoria del kernel en la dirección incorrecta puede (y a menudo resultará) en un Bug Check (Pantalla azul de la muerte). Un bloqueo de la máquina no es aceptable tanto en escenarios de red-teaming como en pruebas de penetración normales, ya que una máquina que se bloquea es altamente visible para los defensores y perderá cualquier credencial que aún estuviera en memoria en el momento del ataque.

Para recuperar los desplazamientos para cada versión específica de Windows, se implementan dos enfoques.

Recuperación manual de desplazamientos

Los desplazamientos requeridos de ntoskrnl.exe y wdigest.dll se pueden extraer utilizando el script Python proporcionado ExtractOffsets.py, que se basa en radare2 y r2pipe para descargar y analizar símbolos de archivos PDB, y extraer de ellos los desplazamientos necesarios. Luego, los desplazamientos se almacenan en archivos CSV para su uso posterior por EDRSandblast.

Para admitir de forma nativa una amplia gama de compilaciones de Windows, muchas versiones de los binarios ntoskrnl.exe y wdigest.dll están referenciadas por Winbindex, y pueden descargarse automáticamente (y extraerse sus desplazamientos) mediante ExtractOffsets.py. Esto permite extraer desplazamientos de casi todos los archivos que se hayan publicado en paquetes de actualización de Windows (hasta la fecha, hay más de 450 versiones de ntoskrnl.exe y más de 30 versiones de wdigest.dll disponibles y precalculadas).

Recuperación y actualización automática de desplazamientos

Se ha implementado una opción adicional en EDRSandBlast para permitir que el programa descargue por sí mismo los archivos .pdb necesarios del Servidor de Símbolos de Microsoft, extraiga los desplazamientos requeridos e incluso actualice los archivos .csv correspondientes si están presentes.

Usar la opción --internet hace que la ejecución de la herramienta sea mucho más simple, aunque introduce un riesgo adicional de OpSec, ya que se descarga un archivo .pdb y se guarda en el disco durante el proceso. Esto es requerido por las funciones de dbghelp.dll utilizadas para analizar la base de datos de símbolos; sin embargo, es posible que en el futuro se implemente un análisis completo de PDB en memoria para eliminar este requisito y reducir la huella de la herramienta.

Uso

Controladores vulnerables

EDRSandblast implementa públicamente el soporte de al menos 3 controladores vulnerables: gdrv.sys (predeterminado), RTCore64.sys y DBUtil_2_3.sys. El controlador realmente utilizado se decide antes de la compilación de la herramienta (consulte #define VULN_DRIVER <nombre del controlador> en includes/KernelMemoryPrimitive.h). Se debe descargar una copia del controlador vulnerable y proporcionarla a EDRSandblast para que su operación de kernel funcione.

Los hashes de los controladores probados se mencionan al comienzo de cada archivo Driver<nombre>.c que implementa las primitivas de lectura y escritura de memoria del kernel utilizadas por EDRSandblast. Usando estos hashes, las muestras de controladores se pueden encontrar fácilmente en Internet, especialmente en https://www.loldrivers.io.

Aquí está la lista de los controladores vulnerables compatibles junto con los enlaces de descarga:

Uso rápido```

Usage: EDRSandblast.exe [-h | --help] [-v | --verbose] <audit | dump | cmd | credguard | firewall | load_unsigned_driver> [--usermode] [--unhook-method ] [--direct-syscalls] [--add-dll ]* [--kernelmode] [--dont-unload-driver] [--no-restore] [--nt-offsets <NtoskrnlOffsets.csv>] [--fltmgr-offsets <FltmgrOffsets.csv>] [--wdigest-offsets <WdigestOffsets.csv>] [--ci-offsets <CiOffsets.csv>] [--internet] [--vuln-driver <RTCore64.sys>] [--vuln-service <SERVICE_NAME>] [--unsigned-driver <evil.sys>] [--unsigned-service <SERVICE_NAME>] [--no-kdp] [-o | --dump-output <DUMP_FILE>]

root@kitploit:~
### Opciones```
-h | --help             Show this help message and exit.
-v | --verbose          Enable a more verbose output.

Actions mode:

        audit                     Display the user-land hooks and / or Kernel callbacks without taking actions.
        dump                      Dump the process specified by --process-name (LSASS process by default), as '<process_name>' in the current directory or at the
                                  specified file using -o | --output <DUMP_FILE>.
        cmd                       Open a cmd.exe prompt.
        credguard                 Patch the LSASS process' memory to enable Wdigest cleartext passwords caching even if
                                  Credential Guard is enabled on the host. No kernel-land actions required.
        firewall                  Add Windows firewall rules to block network access for the EDR processes / services.
        load_unsigned_driver      Load the specified unsigned driver, bypassing Driver Signature Enforcement (DSE).
                                  WARNING: currently an experimental feature, only works if KDP is not present and enabled.

--usermode              Perform user-land operations (DLL unhooking).
--kernelmode            Perform kernel-land operations (Kernel callbacks removal and ETW TI disabling).


Hooking-related options:

--add-dll <dll name or path>            Loads arbitrary libraries into the process' address space, before starting
                                        anything.This can be useful to audit userland hooking for DLL that are not
                                        loaded by default by this program. Use this option multiple times to load
                                        multiple DLLs all at once.
                                        Example of interesting DLLs to look at: user32.dll, ole32.dll, crypt32.dll,
                                        samcli.dll, winhttp.dll, urlmon.dll, secur32.dll, shell32.dll...

--unhook-method <N>                     Choose the userland un-hooking technique, from the following:

        0                               Do not perform any unhooking (used for direct syscalls operations).
        1 (Default)                     Uses the (probably monitored) NtProtectVirtualMemory function in ntdll to remove all
                                        present userland hooks.
        2                               Constructs a 'unhooked' (i.e. unmonitored) version of NtProtectVirtualMemory, by                                        allocating an executable trampoline jumping over the hook, and remove all present
                                        userland hooks.
        3                               Searches for an existing trampoline allocated by the EDR itself, to get an 'unhooked'
                                        (i.e. unmonitored) version of NtProtectVirtualMemory, and remove all present userland
                                        hooks.
        4                               Loads an additional version of ntdll library into memory, and use the (hopefully                                        unmonitored) version of NtProtectVirtualMemory present in this library to remove all
                                        present userland hooks.
        5                               Allocates a shellcode that uses a direct syscall to call NtProtectVirtualMemory,                                        and uses it to remove all detected hooks

--direct-syscalls       Use direct syscalls to dump the selected process memory without unhooking unserland hooks.


BYOVD options:

--dont-unload-driver                    Keep the vulnerable driver installed on the host
                                        Default to automatically unsinstall the driver.
--no-restore                            Do not restore the EDR drivers' Kernel Callbacks that were removed.
                                        Default to restore the callbacks.
--vuln-driver <gdrv.sys>                Path to the vulnerable driver file.
                                        Default to 'gdrv.sys' in the current directory.
--vuln-service <SERVICE_NAME>           Name of the vulnerable service to intall / start.


Driver sideloading options:

--unsigned-driver <evil.sys>            Path to the unsigned driver file.
                                        Default to 'evil.sys' in the current directory.
--unsigned-service <SERVICE_NAME>       Name of the unsigned driver's service to intall / start.
--no-kdp                                Switch to g_CiOptions patching method for disabling DSE (default is callback swapping).


Offset-related options:

--nt-offsets <NtoskrnlOffsets.csv>      Path to the CSV file containing the required ntoskrnl.exe's offsets.
                                        Default to 'NtoskrnlOffsets.csv' in the current directory.
--fltmgr-offsets <FltmgrOffsets.csv>    Path to the CSV file containing the required fltmgr.sys's offsets
                                        Default to 'FltmgrOffsets.csv' in the current directory.
--wdigest-offsets <WdigestOffsets.csv>  Path to the CSV file containing the required wdigest.dll's offsets
                                        (only for the 'credguard' mode).
                                        Default to 'WdigestOffsets.csv' in the current directory.
--ci-offsets <CiOffsets.csv>            Path to the CSV file containing the required ci.dll's offsets
                                        (only for the 'load_unsigned_driver' mode).
                                        Default to 'WdigestOffsets.csv' in the current directory.
-i | --internet                         Enables automatic symbols download from Microsoft Symbol Server
                                        If a corresponding *Offsets.csv file exists, appends the downloaded offsets to the file for later use
                                        OpSec warning: downloads and drops on disk a PDB file for the corresponding image

Dump options:

-o | --dump-output <DUMP_FILE>          Output path to the dump file that will be generated by the 'dump' mode.
                                        Default to 'process_name' in the current directory.
--process-name <NAME>                   File name of the process to dump (defaults to 'lsass.exe')

Compilación

EDRSandBlast (solo x64) se compiló en Visual Studio 2019 (Windows SDK Versión: 10.0.19041.0 y Conjunto de herramientas de plataforma: Visual Studio 2019 (v142)).

Uso de ExtractOffsets.py

Tenga en cuenta que ExtractOffsets.py solo se ha probado en Windows.```

Installation of Python dependencies

pip.exe install -m .\requirements.txt

Script usage

ExtractOffsets.py [-h] -i INPUT [-o OUTPUT] [-d] mode

positional arguments: mode ntoskrnl or wdigest. Mode to download and extract offsets for either ntoskrnl or wdigest

optional arguments: -h, --help show this help message and exit -i INPUT, --input INPUT Single file or directory containing ntoskrnl.exe / wdigest.dll to extract offsets from. If in download mode, the PE downloaded from MS symbols servers will be placed in this folder. -o OUTPUT, --output OUTPUT CSV file to write offsets to. If the specified file already exists, only new ntoskrnl versions will be downloaded / analyzed. Defaults to NtoskrnlOffsets.csv / WdigestOffsets.csv in the current folder. -d, --download Flag to download the PE from Microsoft servers using list of versions from winbindex.m417z.com.

root@kitploit:~
## Detección
Desde el punto de vista del defensor (proveedor de EDR, Microsoft, analistas de SOC que examinan la telemetría del EDR, ...), se pueden utilizar múltiples indicadores para detectar o prevenir este tipo de técnicas.

### Lista blanca de controladores
Dado que cada acción realizada por la herramienta en la memoria en modo kernel depende de un controlador vulnerable para leer/escribir contenido arbitrario, los eventos de carga de controladores deben ser examinados minuciosamente por el producto EDR (o los analistas de SOC), y generar una alerta ante cualquier carga de controlador inusual, o incluso bloquear controladores vulnerables conocidos. Este último enfoque está incluso [recomendado por Microsoft](https://docs.microsoft.com/en-us/windows/security/threat-protection/windows-defender-application-control/microsoft-recommended-driver-block-rules): cualquier dispositivo Windows con HVCI (*Hypervisor-protected code integrity*) habilitado incluye una lista de bloqueo de controladores, y esto se convertirá progresivamente en un comportamiento predeterminado en Windows (ya lo es en Windows 11).

### Comprobaciones de integridad de la memoria del kernel
Dado que un atacante aún podría usar un controlador vulnerable desconocido para realizar las mismas acciones en memoria, el controlador del EDR podría verificar periódicamente que sus devoluciones de llamada del kernel siguen registradas, ya sea inspeccionando directamente la memoria del kernel (como hace esta herramienta), o simplemente desencadenando eventos (creación de procesos, creación de hilos, carga de imágenes, etc.) y verificando que las funciones de devolución de llamada sean efectivamente invocadas por el kernel ejecutivo.

Como nota al margen, este tipo de estructura de datos podría protegerse mediante el reciente mecanismo [Kernel Data Protection (KDP)](https://www.microsoft.com/security/blog/2020/07/08/introducing-kernel-data-protection-a-new-platform-security-technology-for-preventing-data-corruption/), que se basa en Virtual Based Security, para evitar que el array de devoluciones de llamada del kernel sea escribible sin llamar a las API correctas.

La misma lógica podría aplicarse a variables ETW sensibles como `ProviderEnableInfo`, abusada por esta herramienta para deshabilitar la generación de eventos de Inteligencia de Amenazas de ETW.

### Detección en modo usuario
El primer indicador de que un proceso está tratando activamente de evadir el hooking del espacio de usuario es el acceso a archivos de cada DLL correspondiente a los módulos cargados; en una ejecución normal, un proceso de espacio de usuario rara vez necesita leer archivos DLL fuera de una llamada `LoadLibrary`, especialmente `ntdll.dll`.

Para proteger el hooking de API de ser eludido, los productos EDR podrían verificar periódicamente que los hooks no hayan sido alterados en memoria, dentro de cada proceso monitoreado.

Finalmente, para detectar la evasión de hooks (abuso de un trampolín, uso de syscalls directas, etc.) que no implique la eliminación de hooks, los productos EDR podrían potencialmente basarse en devoluciones de llamada del kernel asociadas a las syscalls abusadas (ej. `PsCreateProcessNotifyRoutine` para la syscall `NtCreateProcess`, `ObRegisterCallbacks` para la syscall `NtOpenProcess`, etc.), y realizar un análisis de la pila de llamadas en modo usuario para determinar si la syscall se activó desde una ruta normal (`kernel32.dll` -> `ntdll.dll` -> syscall) o una anormal (ej. `program.exe` -> syscall directa).

## Agradecimientos

- Enumeración y eliminación de devoluciones de llamada del kernel:
  https://github.com/br-sn/CheekyBlinder

- Primitivas de lectura/escritura de memoria del kernel a través del controlador
  vulnerable `Micro-Star MSI Afterburner`:
  https://github.com/Barakat/CVE-2019-16098/

- Deshabilitación del proveedor de Inteligencia de Amenazas de ETW:
  https://public.cnotools.studio/bring-your-own-vulnerable-kernel-driver-byovkd/exploits/data-only-attack-neutralizing-etwti-provider

- Instalación/desinstalación de controladores: https://github.com/gentilkiwi/mimikatz

- Lista inicial de nombres de controladores de EDR:
  https://github.com/SadProcessor/SomeStuff/blob/master/Invoke-EDRCheck.ps1

- Bypass de Credential Guard re-habilitando `Wdigest` mediante parcheo de memoria
  de `LSASS`: https://teamhydra.blog/2020/08/25/bypassing-credential-guard/

## Autores

[Thomas DIOT (Qazeer)](https://github.com/Qazeer/)
[Maxime MEIGNAN (themaks)](https://github.com/themaks)

## Agradecimientos a los colaboradores
- [v1k1ngfr](https://github.com/v1k1ngfr): por el bypass de la comprobación de firma de controladores (mediante parcheo de `g_CiOptions`) y soporte del controlador GDRV.sys
- [Windy Bug](https://github.com/0mWindyBug): por un bypass de la comprobación de firma de controladores compatible con KDP (mediante *intercambio de devoluciones de llamada*) y su gran contribución a la funcionalidad de bypass de minifiltro

## Licencia

Licencia CC BY 4.0 - https://creativecommons.org/licenses/by/4.0/
Descargar herramienta
Controlador compatibleEnlace de descargaSHA256
GDRV.sysLOLDrivers link31f4cfb4c71da44120752721103a16512444c13c2ac2d857a7e6f13cb679b427
RTCore64.sysLOLDrivers link01aa278b07b58dc46c84bd0b1b5c8e9ee4e62ea0bf7a695862444af32e87f1fd
DBUtil_2_3.sysLOLDrivers link0296e2ce999e67c76352613a718e11516fe1b0efc3ffdb8918fc999dd76a73a5