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
ShellGhost — Una técnica de evasión basada en memoria que hace que el shellcode sea invisible desde el inicio hasta el final del proceso. | Kitploit
Herramientas/GitHubGitHub/lem0nsec/shellghost
Herramientas de Cifrado/DescifradoForensia de MemoriaExplotaciónShellcodeAnálisis de BinariosRed TeamingDesarrollo de Payloads
GitHublem0nsec/shellghost

ShellGhost

Una técnica de evasión basada en memoria que hace que el shellcode sea invisible desde el inicio hasta el final del proceso.

Ver Repositorio
1.2k14061hace 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

ShellGhost

Una técnica de evasión basada en memoria que hace que el shellcode sea invisible desde el inicio hasta el final del proceso.


Motivación

Quería compartir esta POC de autoinyección de shellcode para mostrar algunos conceptos de evasión de AV/EDR que pueden ser útiles para Red Teaming. Hace apenas unas semanas se me ocurrió una técnica personalizada de evasión en memoria a la que llamé ShellGhost. Esta técnica surge de la necesidad de tener un código que ejecute un shellcode 'invisible' desde el inicio hasta el final del proceso.


Manejo del flujo de ejecución del hilo

ShellGhost se basa en el manejo de excepciones vectorizadas (VEH) en combinación con breakpoints de software para detener cíclicamente la ejecución del hilo, reemplazar el breakpoint ejecutado con una instrucción de shellcode cifrada con RC4, descifrar la instrucción y reanudar la ejecución después de restaurar la protección de memoria a RX. Cuando se genera la siguiente EXCEPTION_BREAKPOINT, el manejador de excepciones reemplaza la instrucción de shellcode anterior con un nuevo breakpoint, de modo que la asignación nunca revelará el shellcode completo en un estado no cifrado. Esto ocurre dentro de una página de memoria privada que inicialmente está marcada como LECTURA/ESCRITURA. Tener una asignación PRV RW no se considerará un 'Indicador de Compromiso' por parte de escáneres de memoria como PE-Sieve y Moneta. Cuando la asignación se vuelve RX y se escanea la página, no se encontrará nada más que breakpoints. Esto sucede mientras el shellcode está realmente en ejecución. La siguiente imagen muestra que un reverse shell está en ejecución, pero Moneta no encuentra ningún IOC (aparte de que el binario no está firmado).

El intento de escanear el proceso con Pe-Sieve tiene un resultado aún mejor:


Mapeo de shellcode

El mapeo de shellcode es la funcionalidad principal de ShellGhost. Esta táctica permite que el hilo ejecute instrucciones de forma intermitente sin exponer nunca el shellcode completo en memoria. Esto es posible porque la posición de cada instrucción individual del shellcode que ejecuta el hilo corresponde a la posición de un determinado breakpoint dentro de la página de memoria asignada. ShellGhost resuelve esta posición calculando la dirección virtual relativa (RVA) desde el RIP del hilo hasta la dirección base de la página de memoria asignada y la suma a la dirección base del shellcode cifrado / instrucciones cifradas. La cantidad de breakpoints que se reemplazarán no siempre es la misma, sino que varía según la cantidad de opcodes que cada instrucción necesita para generarse e interpretarse correctamente (CUOTA). Entonces, por ejemplo, la instrucción 'POP RBP' es igual a '5D', lo que significa que solo se reemplazará un breakpoint. Por el contrario, la instrucción 'JMP RAX' requiere los opcodes 'FF E0', por lo que se reemplazarán dos breakpoints. Por esta razón, creé la siguiente estructura de datos en C.

typedef struct CRYPT_BYTES_QUOTA {

	DWORD RVA;		// offset a la instrucción cifrada
	DWORD quota;	// número de opcodes que generan la instrucción

} CRYPT_BYTES_QUOTA, * PCRYPT_BYTES_QUOTA;

Los breakpoints no se reemplazan inmediatamente por sus instrucciones correspondientes. Esto se debe a que las instrucciones deben pasar por una rutina de descifrado antes de ejecutarse. Aquí es donde entra en juego el DWORD quota. ShellGhost se basa en la ahora popular 'SystemFunction032' para realizar el descifrado RC4. A diferencia de XOR, RC4 no es un esquema de cifrado de un solo byte. Esto significa que el shellcode no se puede cifrar y descifrar de una sola vez. Esta es también otra razón por la que cada instrucción se trata por separado. Después de reemplazar los breakpoints, la longitud del búfer que necesita SystemFunction032 será igual a la 'cuota de instrucción', que nuevamente representa el número de opcodes que componen la instrucción específica. Así que, por ejemplo, considere el siguiente fragmento.


CRYPT_BYTES_QUOTA instruccion[200];
instruccion[5].quota = 2

USTRING buf = { 0 }; 	// contendrá el búfer a descifrar y su longitud
USTRING key = { 0 }; 	// contendrá la clave RC4 y su longitud

buf.Length = 2 		// longitud del búfer, o longitud de la instrucción a descifrar

Sabemos que la instrucción número 5 del shellcode se compone de 2 opcodes, por lo que se pasará una longitud de búfer de 2 a SystemFunction032. Esto es importante porque intentar descifrar todo el shellcode con una sola llamada a SystemFunction032 lo corromperá por completo.

¿Cómo se realiza el mapeo del shellcode?

El shellcode debe mapearse con ShellGhost_mapping.py antes de la compilación. El script extrae cada instrucción individual y la trata como un pequeño shellcode independiente. Las instrucciones se cifran una por una y se imprimen en formato C todas juntas como unsigned char. El resultado se puede codificar directamente en el código C. A continuación se muestra un ejemplo de cómo se ven las instrucciones de shellcode cifradas de MSF para calc.exe.

Este shellcode tiene 98 instrucciones, por lo que se declaran 98 estructuras CRYPT_BYTES_QUOTA. Cuando el código se ejecuta, estas estructuras deben poblarse con las RVA y CUOTAS de instrucciones adecuadas. El parámetro '-1' le indica al script de mapeo que imprima el fragmento de código que hace esto.

Ajuste de parámetros de Winapi

Los shellcodes x64 de Metasploit suelen tener parámetros de cadena de winapi almacenados entre instrucciones. Es decir, un shellcode x64 de MSF que llama a Winexec no empuja una serie de bytes con un byte nulo al final para tener el primer parámetro de cadena en la pila. Más bien, el registro RCX (primer parámetro) es un puntero dentro del propio shellcode, como se muestra en la siguiente imagen.

Descargar herramienta