
BOF zum Ausführen von PE in Cobalt Strike Beacon ohne Konsolenerstellung
BOF RunPE ist eine Beacon-Objektdatei für Cobalt Strike, die PE-Dateien vollständig im Speicher innerhalb des Beacon-Prozesses ausführt. Anders als beim traditionellen fork&run wird kein untergeordneter Prozess erzeugt, keine Konsole erstellt und keine Pipe verwendet – die gesamte Ausgabe wird über IAT-Hooking erfasst und an die Beacon-Konsole umgeleitet.
Architektur: nur 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/WriteConsole-Hooks erfasstDas Verhalten des BOF kann bearbeitet werden in Additionals postex -> RunPe Config

| Methode | Beschreibung |
|---|---|
None | Direkte API-Aufrufe |
Draugr | Stack-gespoofte API-Aufrufe |
Regwait | RegisterWaitForSingleObject-Callback |
Timer | Timer-Queue-Callback |
| Methode | Beschreibung |
|---|---|
Heap | Privater Heap über RtlCreateHeap mit Draugr |
VirtualAlloc | NtAllocateVirtualMemory mit Draugr |
Module stomping | Überschreibt den .text-Abschnitt einer legitimen DLL |
| Option | Beschreibung |
|---|---|
AllocRWX | Als RWX allozieren (statt RW→RX-Übergang) |
UnhookNtdll | ntdll.dll .text durch eine frische Kopie von der Festplatte ersetzen |
Timeout | Ausführungs-Timeout in Millisekunden (0 = unendlich) |
StompModule | DLL-Pfad für Module Stomping (z. B. chakra.dll) |
| Option | Beschreibung |
|---|---|
ModuleName | Legitimes Modul für die Startadresse (z. B. Kernel32.dll) |
ProcedureName | Funktionsname innerhalb des Moduls (z. B. BaseThreadInitThunk) |
Offset | Offset vom Funktionsbeginn |
Die gesamte PE-Ausgabe wird über IAT-Hooks an die Beacon-Konsole umgeleitet. Es wird kein Konsolenfenster und keine Named Pipe erstellt.
| Abgefangene Funktion | Ziel |
|---|---|
GetCommandLineA/W | Gibt gespoofte Argumente zurück |
__getmainargs / __wgetmainargs | CRT-Argumentinitialisierung |
printf / wprintf | BeaconPrintf-Weiterleitung |
WriteConsoleA/W | BeaconPrintf-Weiterleitung |
__stdio_common_vfprintf | UCRT-Druckfunktionen |
ExitProcess / exit | In ExitThread umgewandelt |
| Technik | Umgeht |
|---|---|
| Indirekte Syscalls | Userland-API-Hooks (EDR/AV) |
| Draugr Stack Spoofing | Call-Stack-Inspektion |
| Thread Start Spoofing | Analyse der Thread-Startadresse |
| Module Stomping | Erkennung von nicht hinterlegtem Speicher |
| Private Heap Allocation | VirtualAlloc-Überwachung |
| Ntdll Unhooking | ntdll im Speicher durch ntdll von der Festplatte ersetzen |
| IAT-Hooking (keine Pipes) | Named-Pipe-Überwachung |
NtGetContextThread / NtSetContextThread:
Speicheroperationen:
DONT_RESOLVE_DLL_REFERENCES geladen (wenn der Speicherallokator Module Stomping ist)Cobalt Strike → Script Manager → Load → BOF_RunPe.cna
beacon> runpe /path/to/binary.exe --arg1 value1

beacon> help runpe

Erfordert GCC 13 (mingw-w64). Verwenden Sie das bereitgestellte Dockerfile:
sudo docker build -t ubuntu-gcc-13 .
sudo docker run --rm -it -v "$PWD":/work -w /work ubuntu-gcc-13:latest make
Ausgabe: Bin/runpe.o
| Einschränkung | Beschreibung |
|---|---|
| CET | Control-flow Enforcement Technology kann synthetische Stack-Frames blockieren |
| Nur x64 | Keine x86/WoW64-Unterstützung |
| Kernel-Sichtbarkeit | Thread-Erstellung für Kernel-Callbacks sichtbar |
| .NET | Verwaltete ausführbare Dateien werden nicht unterstützt |
Windows Native API Programming von Pavel YosifovichWindows Internals, Part 1 von Pavel YosifovichWindows Internals, Part 2 von Andrea Allievi