
Beacon Object File für Cobalt Strike, das .NET-Assemblys im Beacon mit Umgehungstechniken ausführt.
Beacon-Objekt-Datei für Cobalt Strike, die .NET-Assemblies im Beacon mit Umgehungstechniken ausführt.
┌──────────────────────────────────────────────────────────────────────────────┐
│ Cobalt Strike Beacon │
│ (Parent Process) │
└──────────────────────────────────┬───────────────────────────────────────────┘
│
│ beacon_inline_execute()
│ - Gepackte Argumente parsen
│ - go() aufrufen
▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ BOF Execute-Assembly Entry (go) │
│ ┌────────────────────────────────────────────────────────────────────────┐ │
│ │ Konfigurationsparsing │ │
│ │ • ProxyMethod (None/Draugr/Timer/RegWait) │ │
│ │ • AmsiEvasion (None/Patch/HWBP) │ │
│ │ • EtwEvasion (None/Patch) │ │
│ │ • PipeName, AppDomainName, Assembly-Bytes, Argumente │ │
│ └────────────────────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
│ │ Framework-Initialisierung │ │
│ │ • InitVxTable() - Syscall-Nummern auflösen │ │
│ │ └─> NtProtectVirtualMemory, NtContinue, NtCreateEvent, │ │
│ │ NtSetEvent, NtWaitForSingleObject, NtClose │ │
│ │ • DraugrInit() - Synthetische Stack-Frames einrichten │ │
│ │ └─> RtlUserThreadStart, BaseThreadInitThunk lokalisieren │ │
│ └────────────────────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
│ │ DLL-Laden (ProxyLoadLibraryA) │ │
│ │ • amsi.dll, OleAut32.dll, mscoree.dll, User32.dll │ │
│ │ │ │
│ │ PROXY_NONE: LoadLibraryA() direkt │ │
│ │ PROXY_DRAUGR: DRAUGR_API(LoadLibraryA) - gespoofter Stack │ │
│ │ PROXY_TIMER: CreateTimerQueue → Timer-Rückruf │ │
│ │ PROXY_REGWAIT: RegisterWaitForSingleObject → Event-Rückruf │ │
│ └────────────────────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
│ │ AMSI-Umgehung einrichten │ │
│ │ │ │
│ │ AMSI_PATCH: AMSI_HWBP: │ │
│ │ ┌─────────────────────────┐ ┌──────────────────────────────┐ │ │
│ │ │ 1. 4 Bytes sichern │ │ 1. VEH-Handler hinzufügen │ │ │
│ │ │ 2. NtProtectVirtualMem │ │ 2. RtlCaptureContext │ │ │
│ │ │ (RW) │ │ 3. DR0 = AmsiScanBuffer │ │ │
│ │ │ 3. Schreiben: │ │ 4. DR7-Breakpoint aktivieren │ │ │
│ │ │ 48 31 C0 xor rax,rax│ │ 5. NtContinue (Kontext anw.) │ │ │
│ │ │ C3 ret │ │ │ │ │
│ │ │ 4. NtProtectVirtualMem │ │ Bei Aufruf von AmsiScanBuffer:│ │ │
│ │ │ (wiederherstellen) │ │ → #BP-Exception │ │ │
│ │ └─────────────────────────┘ │ → VEH leitet zu RET um │ │ │
│ │ │ → RAX = 0 │ │ │
│ │ └──────────────────────────────┘ │ │
│ └────────────────────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
│ │ ETW-Umgehung (falls aktiviert) │ │
│ │ • NtProtectVirtualMemory(NtTraceEvent, RW) │ │
│ │ • 4 Bytes sichern │ │
│ │ • Schreiben: 48 31 C0 C3 (xor rax,rax; ret) │ │
│ │ • NtProtectVirtualMemory(Schutz wiederherstellen) │ │
│ └────────────────────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
│ │ Ausgabeumleitung einrichten │ │
│ │ ┌──────────────────────────────────────────────────────────────────┐ │ │
│ │ │ 1. CreateNamedPipeW(\\.\pipe\{CustomName}) → hPipe │ │ │
│ │ │ 2. CreateFileW(Pipe-Pfad) → hFile │ │ │
│ │ │ 3. AllocConsole() + ShowWindow(SW_HIDE) → Versteckte Konsole │ │ │
│ │ │ 4. PEB-Manipulation: │ │ │
│ │ │ • Sichern: hCurrentStdOut = PEB->ProcessParameters->StdOut │ │ │
│ │ │ • Sichern: hCurrentStdErr = PEB->ProcessParameters->StdErr │ │ │
│ │ │ • Umleiten: PEB->StdOut = hFile │ │ │
│ │ │ • Umleiten: PEB->StdErr = hFile │ │ │
│ │ └──────────────────────────────────────────────────────────────────┘ │ │
│ └────────────────────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
│ │ CLR-Hosting & Assembly-Ausführung (ExecuteAssembly) │ │
│ │ ┌──────────────────────────────────────────────────────────────────┐ │ │
│ │ │ 1. CLR-Versionserkennung │ │ │
│ │ │ • Assembly-Bytes auf "v2.0.50727" oder "v4.0.30319" prüfen │ │ │
│ │ │ 2. CLR-Initialisierung │ │ │
│ │ │ • CLRCreateInstance → ICLRMetaHost │ │ │
│ │ │ • GetRuntime(v2/v4) → ICLRRuntimeInfo │ │ │
│ │ │ • GetInterface → ICorRuntimeHost │ │ │
│ │ │ • Start() │ │ │
│ │ │ 3. AppDomain-Verwaltung │ │ │
│ │ │ • GetDefaultDomain() → Standard-AppDomain │ │ │
│ │ │ • CreateDomain(CustomName) → Isolierte AppDomain │ │ │
│ │ │ 4. Assembly laden │ │ │
│ │ │ • SAFEARRAY (VT_UI1) mit Assembly-Bytes erstellen │ │ │
│ │ │ • SafeArrayAccessData → Assembly in Safe Array kopieren │ │ │
│ │ │ • CustomAppDomain->Load_3(safearray) → Im Speicher laden │ │ │
│ │ │ 5. Argumente vorbereiten │ │ │
│ │ │ • Leerzeichen-getrennte Argumente parsen │ │ │
│ │ │ • SAFEARRAY(VT_BSTR) für jedes Argument erstellen │ │ │