
Variación más sigilosa de las técnicas de inyección Module Stomping y Module Overloading que reduce los IoCs de memoria. Implementado en Python ctypes
 [](https://twitter.com/intent/follow?screen_name=naksyn) # ModuleShifting Esta herramienta se presentó en la **[charla x33fcon 2023: "Mejorando la sigilosidad de las técnicas de inyección de memoria"](https://github.com/naksyn/talks/blob/main/x33fcon%202023%20-%20Improving%20the%20Stealthiness%20of%20Memory%20Injection%20Techniques.pdf) [[Video]](https://www.youtube.com/watch?v=_TEnBLt2JF4) [[Blogpost]](https://naksyn.com/edr%20evasion/2023/06/01/improving-the-stealthiness-of-memory-injections.html)** # Qué es ModuleShifting es una variación más sigilosa de las técnicas de inyección Module Stomping y Module Overloading. Está implementado en Python ctypes para que pueda ejecutarse completamente en memoria a través de un intérprete de Python y [Pyramid](https://github.com/naksyn/Pyramid), evitando así el uso de cargadores compilados. La técnica se puede utilizar con payloads PE o shellcode, sin embargo, la variación más sigilosa debe usarse con payloads shellcode que necesitan ser **funcionalmente independientes del payload final que el shellcode está cargando.** ModuleShifting, cuando se usa con un payload shellcode, realiza las siguientes operaciones: 1. La DLL anfitriona legítima se carga mediante LoadLibrary 2. Cambiar los permisos de memoria de una sección especificada a RW 3. Sobrescribir el shellcode sobre la sección objetivo 4. añadir padding opcional para integrarse mejor en el comportamiento de falso positivo ([más información aquí](https://www.forrest-orr.net/post/masking-malicious-memory-artifacts-part-ii-insights-from-moneta)) 5. Cambiar permisos a RX 6. Ejecutar el shellcode mediante un puntero a función - métodos de ejecución adicionales: callback de función o API CreateThread 7. **Escribir el contenido original de la DLL sobre el shellcode ejecutado** - este paso evita dejar un artefacto de memoria malicioso en el espacio de memoria de imagen de la DLL anfitriona. El shellcode debe ser funcionalmente independiente de etapas posteriores; de lo contrario, la ejecución se romperá.  Cuando se utiliza un payload PE, ModuleShifting realizará las siguientes operaciones: 1. La DLL anfitriona legítima se carga mediante LoadLibrary 2. Cambiar los permisos de memoria de una sección especificada a RW 3. copiar el PE sobre el punto de sección objetivo especificado sección por sección 4. añadir padding opcional para integrarse mejor en el comportamiento de falso positivo 5. realizar reubicación base 6. resolver importaciones 7. finalizar la sección estableciendo los permisos a sus valores nativos (evita la creación de una región de memoria RWX) 8. ejecución de callbacks TLS 9. Ejecutar el punto de entrada del PE # Por qué es útil ModuleShifting se puede usar para inyectar un payload sin asignar memoria dinámicamente (es decir, VirtualAlloc) y en comparación con Module Stomping y Module Overloading es más sigiloso porque reduce la cantidad de IoCs generados por la propia técnica de inyección. Hay 3 diferencias principales entre Module Shifting y algunas implementaciones públicas de Module Stomping (una de [Bobby Cooke](https://github.com/boku7/Ninja_UUID_Runner) y [WithSecure](https://blog.f-secure.com/hiding-malicious-code-with-module-stomping/)) 1. Padding: al escribir shellcode o PE, puede usar padding para integrarse mejor en el comportamiento común de Falso Positivo (como aplicaciones de terceros o dlls .net que escriben x cantidad de bytes sobre su sección .text). 2. Ejecución de shellcode usando un puntero a función. Esto ayuda a evitar la creación de un nuevo hilo o llamar a callbacks de función inusuales. 3. Restauración del contenido original de la DLL sobre el shellcode ejecutado. **Esta es una diferencia clave.** Las diferencias entre Module Shifting y Module Overloading son las siguientes: 1. El PE se puede escribir comenzando desde una sección especificada en lugar de comenzar desde el PE de la DLL anfitriona. Una vez que la sección objetivo se elige cuidadosamente, esto puede reducir la cantidad de IoCs generados (es decir, el encabezado PE de la DLL anfitriona no se sobrescribe o se sobrescriben menos bytes en la sección .text, etc.) 2. Padding que se puede agregar al propio payload PE para integrarse mejor en los falsos positivos. Usando un payload shellcode funcionalmente independiente, como un payload shellcode AceLdr Beacon Stageless, ModuleShifting es capaz de inyectar localmente sin asignar memoria dinámicamente y, por el momento, generando **cero IoC en un escaneo de Moneta y PE-Sieve**. Soy consciente de que los payloads durmientes de AceLdr pueden ser detectados con otras grandes herramientas como [Hunt-Sleeping-Beacon](https://github.com/thefLink/Hunt-Sleeping-Beacons), pero el enfoque aquí está en la técnica de inyección en sí misma, no en el payload. En nuestro caso, lo que permite mayor sigilosidad en la inyección es la independencia funcional del shellcode, de modo que los bytes maliciosos escritos pueden restaurarse a su contenido original, borrando efectivamente los rastros de la inyección. # Descargo de responsabilidad Toda la información y el contenido se proporcionan únicamente con fines educativos. Siga las instrucciones bajo su propio riesgo. Ni el autor ni su empleador son responsables de cualquier daño o pérdida directa o consecuente que surja de cualquier persona u organización. # Créditos Este trabajo ha sido posible gracias al conocimiento y las herramientas compartidas por personas increíbles como Aleksandra Doniec @[hasherezade](https://twitter.com/hasherezade), Forest Orr y Kyle Avery. Utilicé intensamente [Moneta](https://github.com/forrest-orr/moneta), [PeSieve](https://github.com/hasherezade/pe-sieve), [PE-Bear](https://github.com/hasherezade/pe-bear) y [AceLdr](https://github.com/kyleavery/AceLdr) a lo largo de todo mi proceso de aprendizaje y han sido clave para mi comprensión de este tema. # Uso ModuleShifting se puede usar con [Pyramid](https://github.com/naksyn/Pyramid) y un intérprete de Python para ejecutar la inyección local de procesos completamente en memoria, evitando cargadores compilados. 1. Clone el repositorio de Pyramid: `git clone https://github.com/naksyn/Pyramid` 2. Genere un payload shellcode con su C2 preferido y colóquelo en la carpeta **Delivery_files** de Pyramid. Consulte la sección [Advertencias](#advertencias) para conocer los requisitos del payload. 3. modifique los parámetros del script moduleshifting.py dentro de la carpeta Modules de Pyramid. 4. Inicie el servidor de Pyramid: `python3 pyramid.py -u testuser -pass testpass -p 443 -enc chacha20 -passenc superpass -generate -server 192.168.1.2 -setcradle moduleshifting.py` 5. ejecute el código cradle generado en un intérprete de Python. ### Demostración https://github.com/naksyn/ModuleShifting/assets/59816245/67fcf888-3385-47da-b828-8a2dafeeb1e2 # Advertencias Para ejecutar con éxito esta técnica, debe usar un payload shellcode que sea capaz de cargar un payload adicional autosostenible en otra área de memoria. ModuleShifting se ha probado con el payload AceLdr, que es capaz de cargar una copia completa de Beacon en el heap, rompiendo así la dependencia funcional con el shellcode inicial. Esta técnica funcionaría con cualquier payload shellcode que tenga capacidades similares. Por lo tanto, el shellcode inicial se vuelve inútil una vez ejecutado y no hay razón para mantenerlo en memoria como un IoC. También se debe elegir una DLL anfitriona con suficiente espacio para el shellcode en la sección objetivo; de lo contrario, la técnica fallará. # Oportunidades de detección Module Stomping y Module Shifting necesitan escribir shellcode en un espacio de memoria de DLL legítima. ModuleShifting eliminará este IoC después de la fase de limpieza, pero los indicadores podrían ser detectados por escáneres con capacidades de inspección en tiempo real. 