Un proof-of-concept de Reflective Loader para Cobalt Strike que tiene como objetivo recrear, integrar y mejorar las funciones de evasión de Cobalt Strike.
Una prueba de concepto de User-Defined Reflective Loader (UDRL) que tiene como objetivo recrear, integrar y mejorar las funciones de evasión de Cobalt Strike.
El Cobalt Strike reflective loader integrado es robusto y maneja todas las funciones de evasión de Malleable PE que Cobalt Strike ofrece. La principal desventaja de usar un UDRL personalizado es que las funciones de evasión de Malleable PE pueden o no ser compatibles de fábrica.
El objetivo del proyecto público BokuLoader es ayudar a los equipos rojos a crear su propio UDRL interno para Cobalt Strike. El proyecto pretende ser compatible con todas las funciones de evasión de Malleable PE de CS que valgan la pena. Algunas funciones de evasión aprovechan la integración con CS, otras han sido recreadas por completo y algunas no son compatibles.
Antes de usar este proyecto, en cualquier forma, debes probar adecuadamente que las funciones de evasión funcionan como se espera. Entre el código C y el script de Aggressor, la compilación con diferentes versiones de sistemas operativos, compiladores y Java puede devolver resultados diferentes.
Funciones de evasión
Funciones de evasión específicas de BokuLoader
Reflective callstack spoofing mediante marcos sintéticos.
Código de reflective loader personalizado en ASM/C.
Indirect NT syscalls mediante las técnicas HellsGate y HalosGate.
Todos los cambios de protección de memoria para todas las opciones de asignación se realizan mediante indirect syscall a NtProtectVirtualMemory.
obfuscate "true" con implementación personalizada del script de Aggressor del UDRL.
NOHEADERCOPY
El loader no copiará las cabeceras de la DLL beacon cruda a la DLL beacon virtual. Los primeros 0x1000 bytes serán nulos.
XGetProcAddress para resolver símbolos.
No usa Kernel32.GetProcAddress.
xLoadLibrary para resolver la dirección base de las DLL y la carga de DLL.
Para las DLL cargadas, obtiene la dirección base de la DLL desde TEB->PEB->PEB_LDR_DATA->InMemoryOrderModuleList.
No usa Kernel32.LoadLibraryA.
Cifrado César para ofuscación de cadenas.
Tamaño de UDRL de 100k.
Los nombres de las DLL importadas y las cadenas de nombres de las entradas importadas se sobrescriben (stomped) en la DLL beacon virtual.
Funciones de evasión de Malleable PE compatibles
Comando
Opción(es)
Compatible
allocator
HeapAlloc, MapViewOfFile, VirtualAlloc
Todas compatibles mediante la implementación de BokuLoader
Los beacons HTTP/S son compatibles mediante la implementación de BokuLoader. SMB/TCP actualmente no es compatible con obfuscate true. Detalles en el issue. Se acepta ayuda si puedes corregirlo :)
entry_point
RVA como número decimal
Compatible mediante la implementación de BokuLoader
cleanup
true
Compatible mediante la integración con CS
userwx
true/false
Compatible mediante la implementación de BokuLoader
sleep_mask
(true/false) o (Sleepmask Kit+true)
Compatible. Cuando se usa el "sleepmask true" por defecto (sin sleepmask kit) establece "userwx true". Cuando se usa el sleepmask kit que soporta memoria RX de beacon.text (src47/Ekko) establece "sleepmask true" y "userwx false".
magic_mz_x64
cadena de 4 caracteres
Compatible mediante la integración con CS
magic_pe
cadena de 2 caracteres
Compatible mediante la integración con CS
transform-x64 prepend
cadena hexadecimal escapada
Modificación del script de Aggressor BokuLoader.cna
transform-x64 strrep
cadena cadena
Modificación del script de Aggressor BokuLoader.cna
stomppe
true/false
No compatible. BokuLoader no copia las cabeceras de la DLL beacon. Los primeros 0x1000 bytes de la DLL beacon virtual son 0x00
Dentro de Cobalt Strike, importa el script de Aggressor BokuLoader.cna
Genera el beacon x64 (Attacks -> Packages -> Windows Executable (S))
Usa la Script Console para asegurarte de que BokuLoader se implementó en la compilación del beacon
No es compatible con la opción x86. El binario x86 es el archivo objeto del Reflective Loader original.
La generación de beacons RAW funciona de fábrica. Cuando se usa Artifact Kit para el loader del beacon, la variable stagesize debe ser mayor que la predeterminada.
BokuLoader cambia algunas cadenas comúnmente detectadas por nuevos valores hardcodeados. Estas cadenas se pueden usar para crear firmas de BokuLoader:
Cadena original de Cobalt Strike
Cadena de BokuLoader en Cobalt Strike
ReflectiveLoader
BokuLoader
Microsoft Base Cryptographic Provider v1.0
12367321236742382543232341241261363163151d
(admin)
(tomin)
beacon
bacons
Asignadores de memoria
DLL Module Stomping
Se llama a Kernel32.LoadLibraryExA para mapear la DLL desde el disco.
El tercer argumento de Kernel32.LoadLibraryExA es DONT_RESOLVE_DLL_REFERENCES (0x00000001)
el sistema no llama a DllMain
No resuelve direcciones en la entrada LDR del PEB, como detalla MDSec aquí
Detectable escaneando la memoria del proceso con la herramienta pe-sieve
Asignación en Heap
Existirá memoria ejecutable RX o RWX en el heap si no se usa el sleepmask kit.
Asignador Mapeado
Se llama a Kernel32.CreateFileMappingA y Kernel32.MapViewOfFile para asignar memoria para la DLL beacon virtual.
Detección de Sleepmask
Si se usa el sleepmask kit, existen métodos de detección para esta asignación de memoria independiente, como detalla MDSec aquí
Indirect Syscalls
BokuLoader llama a los siguientes systemcalls de NT para preparar la memoria ejecutable del beacon cargado: NtAllocateVirtualMemory, NtProtectVirtualMemory
Se llaman indirectamente desde la memoria ejecutable de BokuLoader.
Establecer hooks en modo usuario en ntdll.dll no detectará estos systemcalls.
Es posible registrar kernelcallbacks mediante un driver de kernel para monitorear los system calls anteriores y detectar su uso.
El propio BokuLoader contendrá las instrucciones ensamblador mov eax, r11d; mov r11, r10; mov r10, rcx; jmp r11 dentro de su memoria ejecutable.
Cabecera de la DLL beacon virtual
Los primeros 0x1000 bytes de la DLL beacon virtual son ceros.
Código fuente disponible
El código fuente de BokuLoader se proporciona dentro del repositorio y se puede usar para crear firmas de memoria.
Si tienes guía de detección adicional, no dudes en contribuir enviando un pull request.