
BOF para ejecutar PE en Cobalt Strike Beacon sin crear consola
BOF RunPE es un archivo de objeto Beacon (BOF) para Cobalt Strike que ejecuta archivos PE completamente en memoria dentro del proceso del beacon. A diferencia del tradicional fork&run, no se crea ningún proceso hijo, no se crea ninguna consola y no se utiliza ninguna tubería (pipe); toda la salida se captura mediante el hooking de la IAT y se redirige a la consola del beacon.
Arquitectura: solo x64
┌──────────────────────────────────────────────────────────────┐
│ Cobalt Strike Beacon │
│ (Current Process) │
└────────────────────────┬─────────────────────────────────────┘
│
│ beacon_inline_execute()
│
▼
┌──────────────────────────────────────────────────────────────┐
│ BOF RunPE │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ VxTable + Draugr Initialization │ │
│ │ (Syscall Resolution + Stack Spoofing) │ │
│ └──────────────────────┬─────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────▼─────────────────────────────────┐ │
│ │ PE Mapping │ │
│ │ - Section Copy - IAT Patching (with hooks) │ │
│ │ - Relocations - Memory Protection │ │
│ └──────────────────────┬─────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────▼─────────────────────────────────┐ │
│ │ Thread Execution │ │
│ │ - Spoofed Start Address │ │
│ │ - RIP Hijacking to Entry Point │ │
│ │ - Output Redirection via Hooks │ │
│ └────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
printf/WriteConsoleEl comportamiento del BOF se puede editar en Additionals postex -> RunPe Config

| Método | Descripción |
|---|---|
None | Llamadas directas a la API |
Draugr | Llamadas a la API con la pila falsificada (stack spoofing) |
Regwait | Devolución de llamada (callback) de RegisterWaitForSingleObject |
Timer | Devolución de llamada de Timer Queue |
| Método | Descripción |
|---|---|
Heap | Heap privado mediante RtlCreateHeap con Draugr |
VirtualAlloc | NtAllocateVirtualMemory con Draugr |
Module stomping | Sobrescribe la sección .text de una DLL legítima |
| Opción | Descripción |
|---|---|
AllocRWX | Asignar como RWX (frente a la transición RW→RX) |
UnhookNtdll | Reemplazar la sección .text de ntdll.dll con una copia nueva del disco |
Timeout | Tiempo de espera de ejecución en milisegundos (0 = infinito) |
StompModule | Ruta de la DLL para module stomping (p. ej., chakra.dll) |
| Opción | Descripción |
|---|---|
ModuleName | Módulo legítimo para la dirección de inicio (p. ej., Kernel32.dll) |
ProcedureName | Nombre de la función dentro del módulo (p. ej., BaseThreadInitThunk) |
Offset | Desplazamiento desde el inicio de la función |
Toda la salida del PE se redirige a la consola del beacon mediante hooks de la IAT. No se crea ninguna ventana de consola ni tubería con nombre (named pipe).
| Función enganchada | Destino |
|---|---|
GetCommandLineA/W | Devuelve argumentos falsificados |
__getmainargs / __wgetmainargs | Inicialización de argumentos CRT |
printf / wprintf | Redirección a BeaconPrintf |
WriteConsoleA/W | Redirección a BeaconPrintf |
__stdio_common_vfprintf | Funciones de impresión UCRT |
ExitProcess / exit | Convertido en ExitThread |
| Técnica | Bypass |
|---|---|
| Syscalls indirectos | Hooks de API en modo usuario (EDR/AV) |
| Draugr Stack Spoofing | Inspección de la pila de llamadas |
| Thread Start Spoofing | Análisis de la dirección de inicio del hilo |
| Module Stomping | Detección de memoria sin respaldo (unbacked) |
| Private Heap Allocation | Monitorización de VirtualAlloc |
| Ntdll Unhooking | Sobrescribir la ntdll en memoria con la ntdll del disco |
| IAT Hooking (sin tuberías) | Monitorización de tuberías con nombre (named pipes) |
NtGetContextThread / NtSetContextThread:
Operaciones de memoria:
DONT_RESOLVE_DLL_REFERENCES (si el asignador de memoria es module stomping)Cobalt Strike → Script Manager → Load → BOF_RunPe.cna
beacon> runpe /path/to/binary.exe --arg1 value1

beacon> help runpe

Requiere GCC 13 (mingw-w64). Utilice el Dockerfile proporcionado:
sudo docker build -t ubuntu-gcc-13 .
sudo docker run --rm -it -v "$PWD":/work -w /work ubuntu-gcc-13:latest make
Salida: Bin/runpe.o
| Limitación | Descripción |
|---|---|
| CET | La tecnología Control-flow Enforcement Technology puede bloquear los marcos de pila sintéticos |
| Solo x64 | Sin soporte para x86/WoW64 |
| Visibilidad del kernel | La creación de hilos es visible para las devoluciones de llamada del kernel |
| .NET | No se admiten ejecutables administrados |