
Una técnica avanzada de evasión en memoria que alterna la protección de memoria del shellcode entre RW/NoAccess y RX, y luego cifra/descifra su contenido.
Una implementación de prueba de concepto para otra técnica de evasión en memoria que cifra y descifra cíclicamente el contenido del shellcode para luego hacerlo fluctuar entre la protección de memoria RW (o NoAccess) y RX.
Cuando nuestro shellcode reside en páginas de memoria RW o NoAccess, escáneres como Moneta o pe-sieve no podrán localizarlo y volcarlo para su posterior análisis.
Después de publicar ThreadStackSpoofer recibí algunas preguntas sobre el siguiente punto del README:
Cambia la protección de las páginas de memoria de tu Beacon a RW (desde RX/RWX) y cifra su contenido antes de dormir (eso podría evadir escáneres como Moneta o pe-sieve)
Antes estaba bastante seguro de que la comunidad ya sabía cómo cifrar/descifrar sus payloads y cambiar sus protecciones de memoria para simplemente evadir los escáneres de memoria que buscan regiones ejecutables anómalas. Las preguntas demostraron lo contrario, así que decidí publicar esta PoC no armada para documentar otra estrategia de evasión y ofrecer una implementación de muestra con la que la comunidad pueda trabajar.
Esta PoC es una demostración de una técnica bastante simple, ya conocida por la comunidad ofensiva (así que realmente no estoy aportando nada nuevo aquí) con la esperanza de revelar el secreto detrás de la magia mostrada por algunos frameworks comerciales que demuestran sus capacidades de evasión apuntando a ambos escáneres de memoria mencionados anteriormente.
Aquí hay una comparación cuando se fluctúa a RW (otra opción es fluctuar a PAGE_NOACCESS - descrito más abajo):

Esta implementación, junto con mi ThreadStackSpoofer, ofrece a la comunidad de Seguridad Ofensiva implementaciones de muestra para ponerse al día con lo que ofrecen los productos C2 comerciales, para que no podamos hacer nada peor en nuestras herramientas de Red Team. 💪
Este programa realiza auto-inyección de shellcode (aproximadamente mediante el clásico VirtualAlloc + memcpy + CreateThread).
Cuando el shellcode se ejecuta (esta implementación apunta específicamente a implantes Cobalt Strike Beacon), se enganchará una función de Windows para interceptar el momento en que Beacon se duerme, kernel32!Sleep.
Cada vez que se invoca la función enganchada MySleep, localizará los límites de su asignación de memoria, cambiará su protección a RW y aplicará xor32 a todos los bytes almacenados allí.
Tras esperar la cantidad de tiempo esperada, cuando el shellcode regrese a nuestro manejador MySleep, descifraremos los datos del shellcode y devolveremos la protección a RX.
PAGE_READWRITE funciona de la siguiente manerakernel32!Sleep apuntando de vuelta a nuestro callback.VirtualAlloc + memcpy + CreateThread. Al contrario de lo que teníamos en ThreadStackSpoofer, aquí no enganchamos nada en ntdll para lanzar nuestro shellcode, sino que saltamos a él desde nuestra propia función. Esto intenta evitar dejar IOCs simples en memoria que apunten a memoria de ntdll modificada.MySleep es invocado.RWkernel32!Sleep original para evitar dejar un IOC simple en memoria que indique que Sleep ha sido modificado con trampolín (enganche en línea).::Sleep original para permitir que Beacon duerma mientras espera más comunicación.RX y luego re-enganchamos kernel32!Sleep para asegurar la intercepción del siguiente sueño.PAGE_NOACCESS funciona de la siguiente manerakernel32!Sleep apuntando de vuelta a nuestro callback.VirtualAlloc + memcpy + CreateThread ...MySleep es invocado.PAGE_NOACCESSkernel32!Sleep original para evitar dejar un IOC simple en memoria que indique que Sleep ha sido modificado con trampolín (enganche en línea).::Sleep original para permitir que Beacon duerma mientras espera más comunicación.kernel32!Sleep para asegurar la intercepción del siguiente sueño.RX y el shellcode se reanuda.La técnica no es nueva, no es algo que haya ideado yo mismo. Meramente una implementación que muestra el concepto y su utilización práctica para permitir que nuestra comunidad de Seguridad Ofensiva se ponga al día con lo que ofrecen los frameworks C2 comerciales.
De hecho, me introdujeron a la idea de cambiar la protección de memoria del shellcode hace un par de años a través del trabajo de Josh Lospinoso en su increíble Gargoyle.
Aquí hay más contexto:
Gargoyle lleva el concepto de shellcode auto-consciente y auto-fluctuante mucho más lejos, aprovechando una secuencia ROP que llama a VirtualProtect.
Sin embargo, la técnica es impresionante, pero es igualmente difícil aprovecharla con Cobalt Strike's Beacon sin tener que matar su hilo y mantener la reinicialización de Beacon en memoria.
Eso está lejos de ser perfecto, sin embargo, ya que operamos desde el terreno de nuestro propio proceso cargador de auto-inyección, podemos hacer lo que queramos con el entorno en el que opera el shellcode y ocultarlo como nos plazca. Esta técnica (y la anterior, ThreadStackSpoofer) muestra las ventajas de ejecutar nuestros shellcodes de esta manera.
La implementación de la fluctuación a PAGE_NOACCESS está inspirada en el trabajo de ORCA666 presentado en su https://github.com/ORCA666/0x41 inyector.
Él demostró que:
Esta implementación contiene esta idea implementada, disponible con la opción 2 en <fluctuate>.
Asegúrate de revisar también sus otros proyectos.