
탐지 회피 기법을 사용하여 beacon 내에서 .NET 어셈블리를 실행하는 Cobalt Strike용 Beacon Object File.
Cobalt Strike용 Beacon Object File로, 회피 기법을 사용하여 비콘에서 .NET 어셈블리를 실행합니다.
┌──────────────────────────────────────────────────────────────────────────────┐
│ Cobalt Strike Beacon │
│ (Parent Process) │
└──────────────────────────────────┬───────────────────────────────────────────┘
│
│ beacon_inline_execute()
│ - Parse packed arguments
│ - Call go()
▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ BOF Execute-Assembly Entry (go) │
│ ┌────────────────────────────────────────────────────────────────────────┐ │
│ │ Configuration Parsing │ │
│ │ • ProxyMethod (None/Draugr/Timer/RegWait) │ │
│ │ • AmsiEvasion (None/Patch/HWBP) │ │
│ │ • EtwEvasion (None/Patch) │ │
│ │ • PipeName, AppDomainName, Assembly bytes, Arguments │ │
│ └────────────────────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
│ │ Framework Initialization │ │
│ │ • InitVxTable() - Resolve syscall numbers │ │
│ │ └─> NtProtectVirtualMemory, NtContinue, NtCreateEvent, │ │
│ │ NtSetEvent, NtWaitForSingleObject, NtClose │ │
│ │ • DraugrInit() - Setup synthetic stack frames │ │
│ │ └─> Locate RtlUserThreadStart, BaseThreadInitThunk │ │
│ └────────────────────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
│ │ DLL Loading (ProxyLoadLibraryA) │ │
│ │ • amsi.dll, OleAut32.dll, mscoree.dll, User32.dll │ │
│ │ │ │
│ │ PROXY_NONE: LoadLibraryA() directly │ │
│ │ PROXY_DRAUGR: DRAUGR_API(LoadLibraryA) - spoofed stack │ │
│ │ PROXY_TIMER: CreateTimerQueue → Timer callback │ │
│ │ PROXY_REGWAIT: RegisterWaitForSingleObject → Event callback │ │
│ └────────────────────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
│ │ AMSI Evasion Setup │ │
│ │ │ │
│ │ AMSI_PATCH: AMSI_HWBP: │ │
│ │ ┌─────────────────────────┐ ┌──────────────────────────────┐ │ │
│ │ │ 1. Backup 4 bytes │ │ 1. Add VEH Handler │ │ │
│ │ │ 2. NtProtectVirtualMem │ │ 2. RtlCaptureContext │ │ │
│ │ │ (RW) │ │ 3. Set DR0 = AmsiScanBuffer │ │ │
│ │ │ 3. Write: │ │ 4. Enable DR7 breakpoint │ │ │
│ │ │ 48 31 C0 xor rax,rax│ │ 5. NtContinue (apply ctx) │ │ │
│ │ │ C3 ret │ │ │ │ │
│ │ │ 4. NtProtectVirtualMem │ │ On AmsiScanBuffer call: │ │ │
│ │ │ (restore) │ │ → #BP Exception │ │ │
│ │ └─────────────────────────┘ │ → VEH redirects to RET │ │ │
│ │ │ → RAX = 0 │ │ │
│ │ └──────────────────────────────┘ │ │
│ └────────────────────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
│ │ ETW Evasion (if enabled) │ │
│ │ • NtProtectVirtualMemory(NtTraceEvent, RW) │ │
│ │ • Backup 4 bytes │ │
│ │ • Write: 48 31 C0 C3 (xor rax,rax; ret) │ │
│ │ • NtProtectVirtualMemory(restore protection) │ │
│ └────────────────────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
│ │ Output Redirection Setup │ │
│ │ ┌──────────────────────────────────────────────────────────────────┐ │ │
│ │ │ 1. CreateNamedPipeW(\\.\pipe\{CustomName}) → hPipe │ │ │
│ │ │ 2. CreateFileW(pipe path) → hFile │ │ │
│ │ │ 3. AllocConsole() + ShowWindow(SW_HIDE) → Hidden console │ │ │
│ │ │ │ │ │
│ │ │ 4. PEB Manipulation: │ │ │
│ │ │ • Backup: hCurrentStdOut = PEB->ProcessParameters->StdOut │ │ │
│ │ │ • Backup: hCurrentStdErr = PEB->ProcessParameters->StdErr │ │ │
│ │ │ • Redirect: PEB->StdOut = hFile │ │ │
│ │ │ • Redirect: PEB->StdErr = hFile │ │ │
│ │ └──────────────────────────────────────────────────────────────────┘ │ │
│ └────────────────────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
│ │ CLR Hosting & Assembly Execution (ExecuteAssembly) │ │
│ │ ┌──────────────────────────────────────────────────────────────────┐ │ │
│ │ │ 1. CLR Version Detection │ │ │
│ │ │ • Scan assembly bytes for "v2.0.50727" or "v4.0.30319" │ │ │
│ │ │ │ │ │
│ │ │ 2. CLR Initialization │ │ │
│ │ │ • CLRCreateInstance → ICLRMetaHost │ │ │
│ │ │ • GetRuntime(v2/v4) → ICLRRuntimeInfo │ │ │
│ │ │ • GetInterface → ICorRuntimeHost │ │ │
│ │ │ • Start() │ │ │
│ │ │ │ │ │
│ │ │ 3. AppDomain Management │ │ │
│ │ │ • GetDefaultDomain() → Default AppDomain │ │ │
│ │ │ • CreateDomain(CustomName) → Isolated AppDomain │ │ │
│ │ │ │ │ │
│ │ │ 4. Assembly Loading │ │ │
│ │ │ • Create SAFEARRAY (VT_UI1) with assembly bytes │ │ │
│ │ │ • SafeArrayAccessData → Copy assembly to safe array │ │ │
│ │ │ • CustomAppDomain->Load_3(safearray) → Load in memory │ │ │