
Inyección de shellcode mediante la API de depuración de Windows
DbgNexum es una prueba de concepto (PoC) para inyectar shellcode mediante la API de depuración de Windows y memoria compartida (File Mapping). Evita escribir y leer memoria remota directamente; en su lugar, utiliza la manipulación del contexto para forzar al proceso objetivo a cargar y ejecutar el payload por sí mismo.
El inyector se adjunta a un proceso objetivo y crea un hilo suspendido. A través de un bucle de depuración, establece un punto de interrupción de hardware (Hardware Breakpoint) para atrapar la ejecución en una dirección de retorno específica. En cada trampa, el inyector modifica los registros de la CPU para simular llamadas a funciones, orquestando una secuencia de llamadas a funciones de la API de Windows dentro del proceso objetivo.
Al momento de escribir este README, probé la técnica contra MDE y Elastic, y ninguno de los dos la detectó.
WriteProcessMemory / VirtualAllocEx: el payload se transfiere mediante CreateFileMapping y MapViewOfFile.ReadProcessMemory: el enfoque obtiene toda la información clave del contexto del hilo.El PoC utiliza un shellcode de msfvenom con XOR que ejecuta "calc.exe". ¡Pero usa tu propio shellcode!
shellcode.hDbgNexum.exe <PID>
Ejemplo de salida:
[i] Section 'MZ' created and shellcode copied
[+] Bait thread created. Setting HWBP on FileTimeToSystemTime
[i] Execution Redirected:
|-> [0] Preparation & anchoring stack
|-> [1] Setting HWBP & buffer alloc
|-> [2] Copying File-Mapping name
|-> [3] Zeroing stack slot
|-> [4] Opening handle to named file mapping
|-> [5] Mapping payload into mem. with exec. perm.
|-> [6] Cleanup & shellcode execution
[+] Successfully detached from process 19256
[i] Orchestration complete.
El flujo de ejecución es un constante ir y venir entre el bucle de depuración del inyector y el proceso objetivo.
Etapas de inyección
La función DebugLoop contiene la lógica principal de inyección y orquesta la "máquina de estados":
0. Preparación:
ret instantánea.1. Asignación:
LocalAlloc para (obviamente) asignar un pequeño búfer.2. Preparación de datos:
memcpy para copiar la cadena MZ en el búfer asignado previamente.3. Preparación de la pila:
memset para poner a cero una ranura de la pila. Esto es en preparación de la etapa 5, que llamará a MapViewOfFile. Dado que la función usará más de 4 argumentos, el quinto argumento se pasa mediante la pila (que establecemos aquí).4. Abrir la asignación:
OpenFileMappingA usando el nombre MZ, "creado" en las etapas 2 y 3.5. Mapear el payload:
MapViewOfFile. Esto mapea la sección de memoria compartida (que contiene el shellcode) en el espacio de direcciones del objetivo con permisos EXECUTE.6. Ejecución:
RIP a la dirección devuelta por MapViewOfFile.