
Cobalt Strike向けのBeacon Object Fileで、回避技術を用いてビーコン内で.NETアセンブリを実行します。
Cobalt Strike の Beacon Object File で、.NET アセンブリを回避技術とともに Beacon 内で実行します。
┌──────────────────────────────────────────────────────────────────────────────┐
│ Cobalt Strike Beacon │
│ (親プロセス) │
└──────────────────────────────────┬───────────────────────────────────────────┘
│
│ beacon_inline_execute()
│ - パックされた引数をパース
│ - go() を呼び出す
▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ BOF Execute-Assembly エントリ (go) │
│ ┌────────────────────────────────────────────────────────────────────────┐ │
│ │ 設定パース │ │
│ │ • ProxyMethod (None/Draugr/Timer/RegWait) │ │
│ │ • AmsiEvasion (None/Patch/HWBP) │ │
│ │ • EtwEvasion (None/Patch) │ │
│ │ • PipeName, AppDomainName, アセンブリバイト列, 引数 │ │
│ └────────────────────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
│ │ フレームワーク初期化 │ │
│ │ • InitVxTable() - システムコール番号を解決 │ │
│ │ └─> NtProtectVirtualMemory, NtContinue, NtCreateEvent, │ │
│ │ NtSetEvent, NtWaitForSingleObject, NtClose │ │
│ │ • DraugrInit() - 合成スタックフレームをセットアップ │ │
│ │ └─> RtlUserThreadStart, BaseThreadInitThunk の位置を特定 │ │
│ └────────────────────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
│ │ DLL 読み込み (ProxyLoadLibraryA) │ │
│ │ • amsi.dll, OleAut32.dll, mscoree.dll, User32.dll │ │
│ │ │ │
│ │ PROXY_NONE: LoadLibraryA() を直接呼び出し │ │
│ │ PROXY_DRAUGR: DRAUGR_API(LoadLibraryA) - スタックを偽装 │ │
│ │ PROXY_TIMER: CreateTimerQueue → タイマーコールバック │ │
│ │ PROXY_REGWAIT: RegisterWaitForSingleObject → イベントコールバック │ │
│ └────────────────────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
│ │ AMSI 回避設定 │ │
│ │ │ │
│ │ AMSI_PATCH: AMSI_HWBP: │ │
│ │ ┌─────────────────────────┐ ┌──────────────────────────────┐ │ │
│ │ │ 1. 4バイトをバックアップ │ │ 1. VEH ハンドラを追加 │ │ │
│ │ │ 2. NtProtectVirtualMem │ │ 2. RtlCaptureContext │ │ │
│ │ │ (RW) │ │ 3. DR0 = AmsiScanBuffer を設定│ │ │
│ │ │ 3. 書き込み: │ │ 4. DR7 ブレークポイントを有効化│ │ │
│ │ │ 48 31 C0 xor rax,rax│ │ 5. NtContinue (コンテキスト適用)│ │ │
│ │ │ C3 ret │ │ │ │ │
│ │ │ 4. NtProtectVirtualMem │ │ AmsiScanBuffer 呼び出し時: │ │ │
│ │ │ (復元) │ │ → #BP 例外 │ │ │
│ │ └─────────────────────────┘ │ → VEH が RET にリダイレクト│ │ │
│ │ │ → RAX = 0 │ │ │
│ │ └──────────────────────────────┘ │ │
│ └────────────────────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
│ │ ETW 回避 (有効時) │ │
│ │ • NtProtectVirtualMemory(NtTraceEvent, RW) │ │
│ │ • 4バイトをバックアップ │ │
│ │ • 書き込み: 48 31 C0 C3 (xor rax,rax; ret) │ │
│ │ • NtProtectVirtualMemory(保護を復元) │ │
│ └────────────────────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
│ │ 出力リダイレクト設定 │ │
│ │ ┌──────────────────────────────────────────────────────────────────┐ │ │
│ │ │ 1. CreateNamedPipeW(\\.\pipe\{CustomName}) → hPipe │ │ │
│ │ │ 2. CreateFileW(パイプパス) → hFile │ │ │
│ │ │ 3. AllocConsole() + ShowWindow(SW_HIDE) → 隠しコンソール │ │ │
│ │ │ │ │ │
│ │ │ 4. PEB 操作: │ │ │
│ │ │ • バックアップ: hCurrentStdOut = PEB->ProcessParameters->StdOut│ │ │
│ │ │ • バックアップ: hCurrentStdErr = PEB->ProcessParameters->StdErr│ │ │
│ │ │ • リダイレクト: PEB->StdOut = hFile │ │ │
│ │ │ • リダイレクト: PEB->StdErr = hFile │ │ │
│ │ └──────────────────────────────────────────────────────────────────┘ │ │
│ └────────────────────────────────┬───────────────────────────────────────┘ │
│ │ │
│ ┌────────────────────────────────▼───────────────────────────────────────┐ │
│ │ CLR ホスティング & アセンブリ実行 (ExecuteAssembly) │ │
│ │ ┌──────────────────────────────────────────────────────────────────┐ │ │
│ │ │ 1. CLR バージョン検出 │ │ │
│ │ │ • アセンブリバイト列から "v2.0.50727" または "v4.0.30319" をスキャン│ │ │
│ │ │ │ │ │
│ │ │ 2. CLR 初期化 │ │ │
│ │ │ • CLRCreateInstance → ICLRMetaHost │ │ │
│ │ │ • GetRuntime(v2/v4) → ICLRRuntimeInfo │ │ │
│ │ │ • GetInterface → ICorRuntimeHost │ │ │
│ │ │ • Start() │ │ │
│ │ │ │ │ │
│ │ │ 3. AppDomain 管理 │ │ │
│ │ │ • GetDefaultDomain() → デフォルト AppDomain │ │ │
│ │ │ • CreateDomain(CustomName) → 分離された AppDomain │ │ │
│ │ │ │ │ │
│ │ │ 4. アセンブリ読み込み │ │ │
│ │ │ • アセンブリバイト列で SAFEARRAY (VT_UI1) を作成 │ │ │
│ │ │ • SafeArrayAccessData → セーフアレイにアセンブリをコピー │ │ │
│ │ │ • CustomAppDomain->Load_3(safearray) → メモリにロード │ │ │
│ │ │ │ │ │
│ │ │ 5. 引数準備 │ │ │
│ │ │ • スペース区切りの引数をパース │ │ │
│ │ │ • 各引数に対して SAFEARRAY(VT_BSTR) を作成 │ │ │