BOF_RunPE
BOF RunPE è un Beacon Object File per Cobalt Strike che esegue file PE interamente in memoria all'interno del processo del beacon. A differenza del tradizionale fork&run, nessun processo figlio viene generato, nessuna console viene creata e nessuna pipe viene utilizzata - tutto l'output viene catturato tramite hooking IAT e reindirizzato alla console del beacon.
Architettura: solo x64
Panoramica
┌──────────────────────────────────────────────────────────────┐
│ 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 │ │
│ └────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
Caratteristiche Principali
- Nessuna Creazione di Processi: il PE viene eseguito all'interno del processo del beacon
- Nessuna Console/Pipe: Output catturato tramite hook
printf/WriteConsole
- Metodi di Allocazione Multipli: Heap, VirtualAlloc, Module Stomping
- Caricamento Proxy: Timer Queue, RegisterWait o chiamate dirette
- Ntdll Unhooking: Copia fresca opzionale dal disco
- RWX: Allocazione opzionale della memoria in RWX
- Thread Start Spoofing: Indirizzo di partenza legittimo con hijacking RIP
Opzioni di Configurazione
Il comportamento del BOF può essere modificato in Additionals postex -> RunPe Config

Metodi Proxy
| Metodo | Descrizione |
|---|
None | Chiamate API dirette |
Draugr | Chiamate API con spoofing dello stack |
|
Metodi di Allocazione
| Metodo | Descrizione |
|---|
Heap | Heap privato tramite RtlCreateHeap con Draugr |
VirtualAlloc | NtAllocateVirtualMemory con Draugr |
Module stomping | Sovrascrive la sezione .text di una DLL legittima |
Opzioni Generali
Thread Spoofing
| Opzione | Descrizione |
|---|
ModuleName | Modulo legittimo per l'indirizzo di avvio (es. Kernel32.dll) |
ProcedureName |
Cattura dell'Output
Tutto l'output del PE viene reindirizzato alla console del beacon tramite hook IAT. Nessuna finestra di console o named pipe viene creata.
Tecniche di Evasione
Vettori di Rilevamento
Telemetria del Kernel (ETW-TI)
NtGetContextThread / NtSetContextThread:
- Manipolazione del contesto del thread su thread sospesi e poi ripresa
Operazioni di Memoria:
- Allocazione NtAllocateMemory, può essere in RWX (dipende dalla configurazione)
- Transizioni NtProtectVirtualMemory (RW → RX)
- La memoria eseguibile nelle regioni heap è sospetta (dipende dalla configurazione)
- Module stomping rilevabile tramite mancata corrispondenza dell'hash della sezione (dipende dalla configurazione)
Indicatori Comportamentali
- Thread sospeso creato, acquisizione del contesto e modifica del valore di RIP
- Memoria heap marcata come eseguibile (se l'allocatore di memoria è heap)
- DLL caricata con
DONT_RESOLVE_DLL_REFERENCES (se l'allocatore di memoria è module stomping)
- Sezione .text di ntdll modificata (se unhooking abilitato)
Utilizzo
Caricamento dello Script
Cobalt Strike → Script Manager → Load → BOF_RunPe.cna
Comandi Aggressor
beacon> runpe /path/to/binary.exe --arg1 value1


Compilazione
Richiede GCC 13 (mingw-w64). Usa il Dockerfile fornito:
sudo docker build -t ubuntu-gcc-13 .
sudo docker run --rm -it -v "$PWD":/work -w /work ubuntu-gcc-13:latest make
Output: Bin/runpe.o
Limitazioni
| Limitazione | Descrizione |
|---|
| CET | Control-flow Enforcement Technology potrebbe bloccare i frame di stack sintetici |
|
Crediti / Risorse utilizzate per lo sviluppo
Repository e Blogpost
Libri
Windows Native API Programming di Pavel Yosifovich
Windows Internals, Part 1 di Pavel Yosifovich
Windows Internals, Part 2 di Andrea Allievi