
Cobalt StrikeのExternal C2仕様で使用するためのPython API
Cobalt Strike の External C2 仕様(仕様書)で説明されている仕様と併せて使用するための Python フレームワークです。
主な設計目標は、external c2 仕様を非常にモジュール化された実装とし、Cobalt Strike 用の C2 チャネルを簡単に実装できる十分な抽象化を提供することです。理想的には、ユーザーは transport モジュールと encoder モジュールを作成し、設定ファイルに値を記入するだけで、新しいチャネルを実装できます。
開始する前に、いくつかの設定変更を行う必要があります。次のことを行ってください。
builds/client/dbox/dbox_client.py 内で、token を手順 2 で生成したものに変更します。builds/server/utils/transports/transport_dbox.py でも、手順 3 と同じ変更を行います。cd builds/client/dbox && ./compile_dll.shstart_externalc2.cna スクリプトを読み込みます。cd builds/server/ && ./dbox_server.py でサーバーを実行します。ビデオデモへのリンク: https://www.youtube.com/watch?v=nTRHSh_uCcA
このプロジェクトは、次の 3 つの主要部分で構成されています。
Builder は、指定された設定に基づいてクライアントとサーバーのデプロイメントを動的に構築します。理想的には、クライアントは DLL や EXE などの単一のコンパイル済みファイルとして配布できることが望まれます。
Client は基本的にエンドポイント上で実行されるペイロードであり、仕様書では third-party client と呼ばれます。クライアントのロジックは主に静的です。
transport を利用するために必要な準備を実行しますtransport を介してビーコンから C2 サーバーへメタデータを中継しますtransport を監視しますtransport を介してビーコンからの応答を中継しますトランスポートとエンコーディングの仕組みに必要な設定は、クライアントに静的にコピーされます。トランスポートとエンコーディングの仕組みの関数ロジックも、それぞれのモジュールから静的にコピーされます。
プロセスインジェクションのロジックは Builder によって決定されます。
Server は、client と c2 server の間の通信を仲介するアプリケーションであり、仕様書では third-party Client Controller と呼ばれます。サーバーロジックは主に静的ですが、開発を支援するための verbose 出力とデバッグ出力をサポートしています。
encoder モジュールでステージャーをエンコードしますtransport モジュールでステージャーを転送しますtransport を介して受信したクライアントからのメタデータ応答を待ちますencoder モジュールでメタデータをデコードしますtransport を介して新しいタスクをクライアントへ中継しますtransport を介して受信したクライアントからの応答を待ちますencoder モジュールで応答をデコードしますサーバーがインポートする encoder モジュールと transport モジュールの決定は、config.py に保存されている値に基づいて行われます。
未使用の transport モジュールや encoder モジュールのインポートは実行されません。
次の表は、encoding モジュールと transport モジュール、および client の間で共有される関数を示しています。共有関数は基本的にまったく同じコードです。
非常に重要な注意: client の sendData 関数と recvData 関数に送信するデータは生データ(raw data)である必要があります。一方、transport モジュールの sendData 関数と retrieveData 関数に送信するデータは、必要に応じてエンコードまたはデコード済みである必要があります。
| Transport 関数 | Client 関数 | 説明 |
|---|---|---|
| prepTransport | prepTransport | トランスポートメカニズムを利用するために必要な事前設定を実行します |
| Encoder 関数 | Client 関数 | 説明 |
|---|---|---|
| encode | encode | トランスポートに備えて生データに施す変更を定義します |
| decode | decode | トランスポートから受信した生データを宛先へ中継するために施す変更を定義します |
まず、使用する transport モジュールと encoding モジュールを決定します。次の例では、transport_gmail と encoder_b64url を使用します。
次に、server/config.py を自分のニーズに合わせて変更し、ENCODER_MODULE と TRANSPORT_MODULE が適切に設定され、目的のモジュールを指すようにします。
EXTERNAL_C2_ADDR = "127.0.0.1"
EXTERNAL_C2_PORT = "2222"
C2_PIPE_NAME = "foobar"
C2_BLOCK_TIME = 100
C2_ARCH = "x86"
IDLE_TIME = 5
ENCODER_MODULE = "encoder_b64url"
TRANSPORT_MODULE = "transport_gmail"
verbose = False
debug = False
次に、選択した transport モジュールと encoder モジュールの設定セクションを変更します。
client/mechanism/$mechanism_client.py の設定セクションが、これまでに定義したすべての設定と一致することを確認してください。
サーバーを実行するマシン上で、次を実行します:
python server.py
より詳細な出力を得るには、次を実行します:
python server.py -v
より詳細な出力と、デバッグに役立つ追加出力を得るには、次を実行します:
python server.py -d
次に、対象エンドポイント上でクライアントを実行します。
すべてがうまくいけば、Cobalt Strike コンソール内に新しいビーコンが登録され、操作できるようになります。
なぜこれを書いたのか?: この仕様の実装はあまり公開されておらず、公開されているものも、自分が慣れ親しんだ言語でなかったり、求めているモジュール性や抽象化を備えていなかったからです。
なぜ Python 2 なのか?: 私が怠惰だからです。そして、Python 2 では新しいトランスポートチャネルやエンコーディングチャネルを簡単に実装できます。
お前のコードはクソだ: それは質問ではありません。
新しい transport モジュールや encoder モジュールを提出できますか?: ぜひどうぞ!プルリクエストを送っていただければ、喜んでレビューします。
クライアントコンポーネントにも同様の抽象化とモジュール性を実装し、ビーコンペイロードのプロセスインジェクションのさまざまな方法や、ロードマップ上の他の機能をサポートする予定です。
現在、このプロジェクトには Builder 機能がありません。これはクライアントとサーバーのデプロイメントを動的に構築するために計画されているものですが、ロードマップに含まれています。
| sendData | sendData | トランスポートメカニズムを介してデータを送信する方法を定義します |
| retrieveData | recvData | トランスポートメカニズムを介してデータを受信する方法を定義します |