
KillDefenderとBackstabを組み合わせたBOFコンビネーション
2022年6月28日: Microsoftは、MsMpEng.exeのトークンへのハンドルを開くことを防ぐパッチをリリースしました。そのため、このツールのKillDefender部分は機能しなくなりました。Backstabは引き続き動作するはずです。パッチIDは不明ですが、未パッチの古いシステムでは動作する可能性があります。Win10 21H2およびWin11で確認済みです。
これは、YaxserのBackstabとpwn1sherのKillDefenderを組み合わせて実装したBeacon Object Fileで、Cobalt Strikeで使用するためのものです。

KDStabは、Windows Defender(理論上は他のセキュリティソリューションでも動作する可能性はありますが、テストはしていません)を無効化するためのポストエクスプロイテーションツールであり、他のポストエクスプロイテーションツールが検出されることをそれほど恐れずに使用できるようにします。これを実現するために、BackstabとKillDefenderを活用しており、kdstab Cobalt Strikeコマンドによって適切なタイミングで両方が呼び出されます。
KDStabは、x64版Windows 10、Windows 11、Server 2019で正常にテストされています。
KDStabには、管理者またはシステムレベルのアクセス権限が必要です。
主な機能:
プロセスの整合性(Integrity)を列挙する
プロセスから特権を剥奪し、その整合性を「信頼されない(Untrusted)」に設定する
PPL保護されたプロセスを強制終了する
PPL保護されたプロセスのハンドルを一覧表示する
PPL保護されたプロセスの特定のハンドルを閉じる
プロセスの整合性レベルを確認する

プロセスから特権を剥奪し、そのトークンを「信頼されない」に設定する

/STRIP コマンドの結果

PPL保護されたプロセスを強制終了する

私はpwn1sherのKillDefenderをリリース直後に見つけ、素晴らしいと思いました。MsMpEng.exe(Defender)を無力化するだけでなく、プロセスを実行したままにするため、OPSECの観点からも望ましいと思われます(さらに、WinDefendサービスのデフォルト動作では、障害発生時にMsMpEng.exeが再起動されるため、後で役立つ可能性があります)。
Defenderを無効化することはエンゲージメントに有効ですが、プロフェッショナルとしてクライアントの資産を元の状態に戻す責任があります。さらに、KillDefenderでDefenderを殺してしまったことで、他の攻撃者にシステムをさらしたくはありません。
問題は、MsMpEng.exeを動作状態に「復元」するのが難しいことです。KillDefenderは、対象プロセスから特権(SeDebugPrivilegeなど)を剥奪し、そのトークンの整合性を「信頼されない」に設定することで機能します。トークンを再び「システム」に昇格させて特権を復元することはできません。プロセスを強制終了し、新しいインスタンスを起動する必要があります。もちろん、MsMpEng.exeはPsProtectedSignerAntimalware-Lightプロセスでもあるため、システム権限でもプロセスを終了させることはできません。もどかしいことに、最近TrustedInstallerグループがMsMpEng.exeから削除されました(これに関する他の調査もあります)。そのため、MsMpEng.exeプロセス(またはWinDefendサービス)を実際に強制終了するための、長年使われてきた手法は効果がなくなりました。このような状況から、唯一実行可能な選択肢はマシンを再起動することですが、サーバーやDCについて話し始めると、クライアントに問題を引き起こす可能性があります。
この問題を抱えて調査を始め、すぐにYaxserのBackstabを見つけました。Backstabは、ProcExpのドライバー(SysinternalsのMicrosoft署名済みドライバー)を利用して、PPL保護されたプロセスを強制終了できます。BackstabはOPSEC上安全ではない動作も行います。ドライバーをディスクにドロップし、レジストリキーを作成します。しかし、Defenderが既に無効化されていれば問題ありません... :)。
私はこれら両方のツールをBOF形式に移植し、Cobalt Strike Beaconを通じてディスクにドロップすることなく使用できるようにしようと考えました(元のBackstabバイナリは実行時にDefenderによってブロックされました)。
私はC/C++およびBOFの作成に不慣れであり、その過程で多くのことを学びました。コードに多少の不整合があります(たとえば、Backstab_bofはLinux上でgccを使用して作成・コンパイルされ、KillDefender_bofはVisual Studioで作成・コンパイルされています)。これは作成過程での学習によるものですが、機能を確保するために十分なテストを行い、またアグレッサースクリプトに多くのレールを組み込み、BOFへの適切な使用法と入力を保証しています。このツールがお役に立てば幸いです。
ツールのソースコードにいくつかの顕著な変更が加えられ、特定のプログラム上の選択が行われました。以下にその一部を記します。
ProcExpドライバーはリソースとして保存/ロードされなくなり、backstab_src/resource.c内のハードコードされたバイト配列になりました。
元のBackstabコードにはいくつかのメモリリークがあり、それらを発見して修正しました。
KillDefender POCは、ユーザーがSystemでない場合に失敗します。そこで、実行中のユーザーを列挙し、必要に応じてWinlogonのトークンを借用してSystem権限を取得するスニペットを追加しました。
KillDefenderを変更し、ユーザーが対象とするプロセスを指定できるようにしました。さらに、「Check」モードを追加して、プロセスの整合性レベルを列挙できるようにしました(これにより、プロセスから特権と整合性が正常に剥奪されたことを確認できます)。
Backstabは多くの異なるAPIとC呼び出しを使用するため、Cobalt Strikeだけではすべての動的関数解決を管理できませんでした。そこで、trustedsecの動的関数解決を実装して、CSの解決を補完し、必要なすべてのAPIを呼び出せるようにしました。
元のBackstabにはいくつかのswitch/case文があり、移植中に問題を引き起こしたため、if/else文に置き換えました。また、同様の理由から、ほとんどのグローバル変数を排除しました。
一方のツールがVisual Studio用に、もう一方がGCC用に作成されているのは奇妙に思えるかもしれません。これは移植に苦労し、多くの成長痛を経験した結果です。今後のツールは、この過程で学んだ教訓を活かせることを願っています。
KillDefender_bofとBackstab_bofは、それぞれ独立したリポジトリとして存在します。スタンドアロンのリポジトリとこのツールの間でコードが異なることに注意してください。これは、これらのツールをより柔軟にし、単一のパッケージに統合しやすくするために行われました。
どちらのツールもx86向けにコンパイルしようとはしていません。もしそのバージョンがどうしても必要な場合は、各自で解決してください。
gccを使用してBackstab_bofをコンパイルする場合:
x86_64-w64-mingw32-gcc -o backstab.x64.o -Os -c main.c -DBOF -D_UNICODE
mingwを最新バージョンに更新していることを確認してください!古いバージョンではヘッダーファイルが古く、問題が発生しましたが、最新バージョンのヘッダーファイルは正しいです。
x64 Nativeコマンドプロンプトを使用してKillDefender_bofをコンパイルする場合:
cl.exe /c /GS- /TP killdefender_bof.cpp /FoKillDefender.x64.o
Yaxserと彼のBackstabツール:https://github.com/Yaxser/Backstab
pwn1sherと彼のKillDefenderツール:https://github.com/pwn1sher/KillDefender
Trustedsecと彼のCS-Situational-Awareness-BOFリポジトリ:移植プロセスで大いに助けられました。このプロジェクトでは彼のコードの一部を使用しており、BOFの作成に取り組み始めた方にはぜひこのリポジトリをチェックすることをお勧めします:https://github.com/trustedsec/CS-Situational-Awareness-BOF