セキュリティー・ソリューションの次世代AIや機械学習コンポーネントによって行動ベースの検知機能が強化され続けていますが、その中核となる方法としては依然としてシグネチャー・ベースの検知に依存しています。Cobalt Strikeは、脅威アクターやレッド・チームの両方に利用されている人気のレッド・チームの指揮統制(C2)フレームワークであり、セキュリティソリューションによるシグネチャー検出が依然として頻繁に行われています。
過去におけるCobalt Strikesの運用利用を進化させるために、IBM® X-Force Red Adversary Simulationチームは、Cobalt Strikeを内部ツールでカスタマイズするために、多大な研究を行いました。Cobalt Strike固有の内部ツールには、「InlineExecute- Assembly」、「CredBandit」、「BokuLoader」など、公開バージョンがあるものもあります。過去2年間では、Cobalt Strikeの過剰なシグネチャー検出があったことを踏まえ、IBMでは、その使用をあまり洗練されていない脅威アクターのシミュレーションに限定し、より高度なレッド・チーム演習を実行する際には、他のサード・パーティーや社内のC2を活用しています。
研究開発の取り組みを通じて、以下のような高度なレッド・チーム演習の運用上の成功が見られました。
ただし、Cobalt Strikeの偽造コピーを利用する脅威アクターは依然として多数存在しており、これらの脅威アクターをシミュレートできることは依然として重要です。研究開発に前向きなレッド・チームの場合、これらの敵対者をシミュレートしながらCobalt Strikeでの運用が成功する可能性があります。さらに、Cobalt Strikeは優れた学習ツールであり、初心者はレッド・チーム・トレーニング・コースを通じてC2フレームワークの実践的な経験を積むことができます。
C2機能の拡張を続ける中で、特にカスタムReflective Loaderを開発することによって、過去にCobalt Strikeフレームワークをどのように構築してきたかについての洞察を共有しています。また、防御側が、Cobalt Strikeがどのようにしてより堅牢な検出を作成するかを理解することも目的としています。
AI活用のグローバル・トレンドや日本の市場動向を踏まえたDX、生成AIの最新情報を毎月お届けします。本ニュースレターは【日本語】で配信しています。登録の際はIBMプライバシー・ステートメントをご覧ください。
このブログ投稿は、Cobalt Strike Reflective Loader開発の基本について取り上げる手引きの役割を果たしたシリーズの最初のものです。このシリーズでは、この基盤をベースにして、この投稿を参照していきます。
このシリーズの終わりまでに、Cobalt Strikeの既存の主要な機能と統合し、さらには現在ツールにはない高度なテクニックでそれらを強化する Reflective Loaderを作成することを目指しています。今後の記事では、特定の主要な機能の開発と、それらをCobalt Strikeの Reflective Loaderに実装する方法について深く掘り下げていきます。
まずこの投稿では以下について説明します。
攻撃的なセキュリティー・ツール開発者の視点からCobalt Strikeのインフラストラクチャー・ロードのリフレクティブ・ローディングを検証する中で、検知と回避の機会を明らかにしていきます。一部の開発側面は省略または簡素化されます。そのため、既存の Reflective Loader・プロジェクトをデバッグするか、最初から再構築するか、トレーニングを確保することによって、ギャップを埋めることをお勧めします。
Cobalt Strike C2インプラント(Beaconと呼ばれる)はWindows ダイナミック・リンク・ライブラリ(DLL)であり、Cobalt Strikeで独自のDLLローダーを使用するモジュール機能は、ユーザー定義Reflective Loader(UDRL)と呼ばれます。
通常、組み込みのWindows DLLローダーは、プロセスの仮想メモリー空間にDLLをロードする役割を担います。Windows DLLローダーは主にユーザー空間内に存在しますが、ディスクからDLLをマッピングする際にはカーネル空間を横断します。
Windows DLLローダーを使用すると、敵対者シミュレーションではいくつかの欠点が生じます。
したがって、ビーコンDLLのロードにWindows DLLローダーを使用することは理想的なソリューションではありません。これらの課題を克服するために、 Reflective Loaderを使用してメモリーからビーコンDLLをロードします。
リフレクティブ・ローディングが回避する3つの主な検知ポイントは次のとおりです。
リフレクティブ・ローディングは、ファイル・システムから未加工DLLをロードするのではなく、メモリーから直接ロードするだけと考えることができます。
リフレクティブ・ローディングと組み込みのWindows DLLローダーはどちらも、Rawファイル形式からプロセスの仮想メモリー空間にDLLをロードするという同じ目的を果たします。ただし、リフレクティブ・ローディングには、DLLファイルがファイル システム上に存在する必要がないという点で、Windows DLLローダーに比べて重要な利点があります。C2インプラントDLLは、プロセスのメモリー内の暗号化およびエンコーディング層に隠すことができるため、このメモリー内ロードでは無制限の数のチェーン・ロード・フェーズが可能になります。
DLLをロードするときに理解しておくべき重要な概念は、DLLがディスク上とメモリー上で異なるフォーマットになることを知っておくことです。Rawファイル形式のDLLと仮想アドレス形式のDLLの主な違いは次のとおりです。
Rawファイル形式:
仮想アドレス形式:
Aleksandra Doniec氏によるPE-BearツールでHTTPビーコンDLLを調べると、DLLの各セクションにおけるRawアドレスと仮想アドレスの違いがわかります:
ビーコンDLLの各セクションのRawアドレスと仮想アドレスをリストしたテーブル。
このHTTP/SビーコンDLLは
PE-Bearは、ビーコンDLLがRawファイル形式ではなく仮想アドレス形式で存在するため、ビーコンDLLを視覚的に表現します。
Raw形式(左)と仮想形式(右)におけるビーコンDLLの視覚的表現
敵対者シミュレーション中に実行できる最も賢明な動きではありませんが、ディスクに難読化のないRawビーコンDLLをディスクに落とし込み、Windows DLLローダーでロードすることは、ビーコンと DLLロードの両方をわかりやすく説明する優れた方法です。本質的に、ビーコンは単なるDLLです。Windows DLLローダーと Reflective Loaderは、DLLをプロセスにロードするだけです。
Windows DLLローダーでビーコンDLLをロードするには、次の手順を実行します。
を使用しますLoadLibrary
ディスクからビーコンDLLをロードするためのAPIまず、Windows DLLローダーでビーコンDLLがロード不可能になるように、Malleable PEオプションをすべて無効にします。これを実行するには、Malleable C2プロファイルを変更し、ステージ ブロックにあるMalleable PE回避オプションを無効にします。
Malleable C2プロファイルステージブロックは、Cobalt Strikeの主要な機能を無効にするために変更されました。
プロファイルを変更した後、Cobalt Strike Teamサーバーを再起動し、
Cobalt Strikeクライアントを備えたチーム・サーバーに接続します。次に作成するのが
Cobalt Strike Clientから「Rawステージレス」ビーコンDLLを作成するスクリーンショット
以下のコードを使用して、次のコードを使用してCプログラムを作成し
Windows DLLローダーを使用してディスクからビーコンDLLをロードするためのWindows Cコード。
私たちは
読み込みプロセスの一環として、Windows DLLローダーは、エントリー・ポイントを呼び出すことでビーコンDLLを初期化します。
Windows DLLローダーがビーコンDLLをプロセスの仮想メモリー空間にロードして初期化した後、仮想ビーコンDLLのエントリー・ポイントを引数で再度呼び出す必要があります。
私たちのプログラムは、仮想ビーコンDLLを実行するために仮想ビーコンDLLのエントリー・ポイントを知る必要があります。これは、エントリー・ポイントの相対的な仮想アドレス(RVA)の仮想ビーコンDLLヘッダーを解析することによってプログラム内で動的に行うことも、それが何であるかをすばやく確認して値をハードコードすることもできます。
概念実証のために、ビーコンDLLのエントリー・ポイントRVAを手動で検出し、プログラムにハードコーディングします。PE-Bearを使用することで、RVAからビーコンのエントリー・ポイントまで
PE-Bearを使用したビーコンDLLエントリー・ポイントRVAの検索のスクリーンショット
その
コードの準備が整ったので、CプログラムをWindows実行可能ファイルにコンパイルします。
プログラムのコンパイルに使用されるコマンド。
ビーコンDLLと実行可能なビーコン・ローダー・プログラムを同じディレクトリーに配置することで、Windows DLLローダーはロード・ルーチンを実行するときにDLLを検出できるようになります。
両方を
ビーコンDLLとローダー・プログラムは同じディレクトリーに配置されます。
Windowsデスクトップで、loadBeaconDLL.exeをダブルクリックします。チーム・サーバーへのアクティブなビーコン接続を確立します。
Windows DLLローダーを使用してロードされたビーコンDLLからC2チーム・サーバーへの接続に成功しました。
Cobalt Strikeは、Stephen FewerによるReflective Loaderプロジェクトの修正バージョンを使用します。この伝説的なインメモリーDLLローダーは10年以上の歴史があり、Metasploitやその他の著名な攻撃的セキュリティー・ツールで使用されています。
長年にわたり、Cobalt Strike Reflective Loaderは、Cobalt Strikeが提供するすべてのMalleable PE回避機能を処理できるように強化されてきました。カスタムUser-Defined Reflective Loader(UDRL)を使用する主な欠点は、Malleable PE回避機能がすぐにサポートされる場合とされない場合があることです。
一部の回避機能は、UDRLを使用する場合に完全に実装され、ビーコン・ペイロードの作成時にCobalt Strikes Malleable PEエンジンによってビーコンDLLにパッチ適用されます。ただし、現在は機能のうちのようなものはUDRLする必要がありますが、やのようなものは適切なUDRL統合によりビーコンで処理できます。
元のReflective Loaderプロジェクトでは、
その後、別のプロジェクトが以下を担当します。
元の Reflective Loaderの図。仮想メモリーにDLLをロードしています。
別の方法では、 Reflective LoaderをDLLに事前にデプロイします。これにより、管理されていないDLLを読み込むことができ、ソース コードからDLLをコンパイルする必要がなくなります。これは、あらゆるPEファイル(EXEまたはDLL)をロードできる堅牢なリフレクティブ・ローディング・メソッドです。
DLLを仮想メモリーにロードしている Reflective Loaderの図
Cobalt Strikeのリフレクティブ・ローディングの実装では、上記の2つの方法を組み合わせて使用しています。このリフレクティブ・ローディング・メソッドは、MetasploitのMeterpreterが反射読み込みをどのように行うかについて知識を持つ人にとってはよく知られたものかもしれません。
元の Reflective Loaderの方法のように、
UDRLがCobalt Strikeに読み込まれ、オペレーターがCobalt Strikeクライアントからビーコンペイロードを生成すると、Cobalt StrikeのMalleable PEエンジンは、未加工のファイル・オフセット位置にReflective Loaderのシェルコードにパッチをあてます
Malleable PEエンジンがRawビーコンDLLのパッチ適用を完了すると、RawビーコンDLLが実行可能なシェルコードのような形式でオペレーターに与えられます。
ビーコンDLLを仮想メモリーにロードしているCobalt Strike Reflective Loaderの図。
PE-Bearディスアセンブラーの最初のバイトを見ると、ビーコンDLL自体が実行可能であることがわかります。
Reflective Loaderスタブ呼び出しが実行可能なアセンブリ・オペレーション・コードとして表示されます。
最初のバイトは
オプションでプリペアドを実行した後
Rawファイルのオフセットが確認されていることを確認しました
PE-Bearを使用して、ReflectiveLoaderエクスポートのRawファイル・オフセットを決定する製品の画面。
エクスポート・ディレクトリー内に存在するため、
Rawファイルを特定することで
仮想及びRawアドレス
.textのRawアドレスと仮想アドレスビーコンDLLのセクション。
この2つの違いは
PE-Bearで右クリックすれば確認できます
Cobalt Strikeのリフレクティブ・ローディング・プロセス・フローを要約すると、次のとおりです。
Cobalt StrikeがビーコンDLのリフレクティブ・ローディングを実行する方法の主要なフェーズを示す図
Reflective LoaderはビーコンDLLがロードされる前に実行されるため、 Reflective Loaderコードは純粋なシェルコードである必要があります。
複雑なシェルコードを作成する最も簡単な方法は、外部依存関係なしでC言語で記述することです。次に、Cファイルがオブジェクト・ファイルにコンパイルされます。オブジェクト・ファイルのセクションにはすべてを含める必要があります最後に、.text
Cobalt StrikeのMalleable PEエンジンは、 Reflective Loaderのオブジェクトファイルからシェルコードを取得し、エクスポートのRawファイル・オフセット位置で生のビーコンDLLにパッチを当てる作業を処理します
Cobalt Strikeを利用してRawビーコンDLLに Reflective Loaderシェルコードを書き込むためのAggressorスクリプト。
UDRL Aggressorスクリプトは、次の手順を実行することで、Cobalt Strikeを Reflective Loaderシェルコードに書き込みます。
<a href="https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics_aggressor-scripts/as-resources_functions.htm#extract_reflective_loader">extract_reflective_loader</a>Cobalt Strike Aggressor関数はUDRLオブジェクト・ファイルを
<a href="https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics_aggressor-scripts/as-resources_functions.htm#setup_reflective_loader">setup_reflective_loader</a>Cobalt Strike Aggressor機能は、Malleable PEエンジンを使用して、Rawファイル・オフセットを検出します。
Cobalt Strikeは、リフレクティブローダーのオブジェクト・ファイルから.textセクションを抽出する作業、Reflective Loaderのシェルコードをパッチする作業、そしてビーコンDLLヘッダーにある「call reflective loader stub」を使ってリフレクティブローダーを呼び出す作業を、我々の代わりに済ませてくれます。
これらは、ビーコンを反射的に読み込むために開発しなければならないフェーズです。
メモリー内のRawビーコンDLLのアドレスを見つけるために使用できる方法はいくつかあります。次のような方法があります。
逆算してハンティングする方法を使用する場合は、まずスレッドの指示ポインターの現在のアドレスを取得する必要があります(
RDIレジスタからRawビーコンDLLのアドレスを取得するためのIntel x64アセンブリ・コード。
元の Reflective Loaderプロジェクトは、MZおよびPEヘッダーを逆方向にハンティングします。これらのヘッダーは検知ポイントになっています。このCobalt Strikeを克服するために、
Cobalt Strikeの文書には、
設定すると、
これらのバイトはある程度一意である必要があり、そうでない場合は Reflective Loaderがそれらを見つけることができません。さらに、MZヘッダーのバイトはオペレーションで実行可能でなければなりません。次のような値にはなりません
この潜在的な検知ポイントを発見した後、私はRawビーコンDLLベース・アドレスを見つけるための別の、同様の方法を開発しました。この方法では、エグゼクティブ・ハンターを使用したエグゼクティブ・ハンターが
このアドレス
Java Malleable PEエンジンには簡単にアクセスできないため、
RawビーコンDLLにeggを書き込み、Cobalt Strikeスクリプト・コンソールに変更を表示するAggressorスクリプト。
UDRLコードは、UDRLスクリプトによってRawビーコンDLLに書き込まれるegg値を知っている必要があります。以下のコードに示すように、既知eggでエグゼクティブ・ハンターはeggの2つのインスタンスを逆方向に検索します。
64ビットeggの2つのインスタンスを逆方向に検索するeggハンターのIntel x64アセンブリ・コード。
MZヘッダーとPEヘッダーが使用されなくなったため、UDRL Aggressorスクリプトでそれらを削除できます。
MZ、PE、およびRawビーコンDLLヘッダーにある DOS バナーの未使用バイトをマスクするAggressorスクリプト。
また、RawビーコンDLLベースのアドレスを発見するために、Cobalt Strike固有の方法がもう1つあります。上で見たように、Reflective Loaderスタブ呼び出しの最初のバイトには、RawビーコンDLLのベース・アドレスが保管されます。
デバッガーでこれをさらに調べるために、ビーコンを生成し、ブレークポイントを前立て(
Reflective Loaderを呼び出す前に、Reflective Loaderスタブ呼び出しを探索して、RawビーコンDLLのベース・アドレスがRDIレジスタに保存されていることを確認するX64dbgのスクリーンショット。
以下は、Reflective Loaderスタブ呼び出しからRawビーコンDLLのベース・アドレスを取得する方法の実行例です。
RDIレジスタからRawビーコンDLLベース・アドレスを取得するためのインライン・アセンブリCコード。
RawビーコンDLLのアドレスを使用して、ビーコンをプロセスの仮想アドレス空間にロードするために必要な値を取得できるようになりました。
以下の表は、RawビーコンDLLのヘッダーから必要な値、それらが見つかる場所、およびその種類のリストです。
テーブルは、ビーコンDLLのロードに役立つRawビーコンDLLヘッダーからの値をリストします。
ヘッダーのすべての内容がビーコンDLLのロードに必要なわけではありません。必要な値は再パックまたは難読化できます。不要な値は削除するか、ランダム化できます。
一度SizeOfImagef
仮想ビーコンDLLのメモリー割り当てには、さまざまな方法を使用できます。また、さまざまな方法で、使用するメモリーの種類も異なります。Cobalt StrikeのデフォルトのReflective Loaderによってサポートされているさまざまなメソッドは次のとおりです。
仮想ビーコンDLLのCobalt Strikeのメモリー割り当てオプションを示す表。
UDRLでは、これをさらに一歩進めることができます。これらの関数のNTAPIバージョンを代わりに使用できます。さらに、NTAPI関数は、直接的または間接的なシステム・コールを介して呼び出すことができ、機能の強化に役立つ場合とそうでない場合があります。
アロケーション・メソッドが以下に設定されている場合、
BokuLoaderプロジェクトのコード・サンプルは、プロセスからシステム・コールがどのように検出されるかを示しています。
仮想ビーコンDLL用のメモリーを割り当てたので、ビーコンのセクションを、RawビーコンDLLに存在するRawファイル・オフセットから、相対仮想オフセットで割り当てられたメモリーにコピーする必要があります。
メモリを次のように割り当てるとREADWRITEの所在地を追跡する必要がありますセクションとそのサイズ。仮想ビーコンDLLのエントリ・ポイントを呼び出す前に、のメモリ保護を変更する必要がありますセクションを実行可能にします。
に対するメモリの割り当てによって反射型ローディングプロセスが容易になりますが、セキュリティー・ソリューションによる検知の可能性も増えます。
以下は、BootLoaderプロジェクトの簡略化されたコード例であり、これを示しています。
RawビーコンDLLから仮想ビーコンDLLにコピーされたセクションを示すBookLoaderプロジェクトのコード・サンプル。
ローディング・セクションに関するいくつかの主要な機能には次のようなものがあります。
パブリックな保護プロジェクトでは、ビーコンDLLのヘッダーはRawビーコンDLLから仮想ビーコンDLLにコピーされない。現在、最初の
回避できるもう1つの可能性は、UDRL Aggressorスクリプトにセクションを暗号化させることです。このセクションは、UDRLとUDRL Aggressorスクリプトの間で共有された鍵を使用して、UDRLによってメモリー内で復号化できます。
x64 HTTP/Sビーコンは、4つのDLLに依存して適切に機能します。これらのDLLが現在プロセスにロードされていない場合は、 Reflective Loaderがそれらをロードする必要があります。
4つのDLLはHTTP/SビーコンDLLのインポート・ディレクトリーにリストされています。
ビーコンDLLのインポート・ディレクトリーからのDLLをリストするPE-Bearのスクリーンショット。
組み込みのCobalt Strike Reflective Loaderは、DLLロードにkernel32.LoadLibraryA APIを使用します。
DLLのロードは、運用上のセキュリティー上の考慮事項もさまざまですが、さまざまな方法で実行できます。次のような方法があります。
DLLがプロセスにすでに存在する場合は、上記のWindows APIを引き続き使用してDLLベースのアドレスを取得できますが、これにより不要な検知アラートが発生する可能性があります。
あるいは、PEBは以下へのポインターを保持します
<a title="https://learn.microsoft.com/jp-ja/windows/win32/api/winternl/ns-winternl-peb_ldr_data"href="https://learn.microsoft.com/jp-ja/windows/win32/api/winternl/ns-winternl-peb_ldr_data">_PEB_LDR_DATA</a>
構造。内部には、プロセスで読み込まれたすべてのDLLとその関連情報があります(
)。BokuLoaderはこれを活用してDLL情報を発見し、不要なAPI呼び出しを避けます。
DLLが存在しない場合は、
Reflective Loaderは一般にDLLをプロセスに登録しないため、ネストされたリフレクティブ・ローディングはDLL依存関係のロードに簡単に使用できません。DLLの外部コードは、反射的に読み込まれたDLLを適切に使用できません。DarkLoadLibraryプロジェクトは、カーネルイメージロードイベントをトリガーせずにDLLを適切にメモリーにロードできる可能性があります。
InMemoryOrderModuleTextを実行することで、読み込まれたDLLの基本アドレスを解決する方法を示すサーバー・プロジェクトのコード・サンプル。
必要なDLLがプロセスにロードされたら、インポート・ディレクトリーにリストされているAPIを解決する必要があります。その後、APIアドレスを仮想ビーコンDLLのインポート・アドレス・テーブル(IAT)に書き込む必要があります。このようにして、ビーコンは次のようなAPIを呼び出す必要があるときにジャンプすべきアドレスを把握します。
インポート・エントリーは、序数または名前文字列を使用して解決する必要があります。
以下の画像では、Cobalt StrikeビーコンDLLがインポート・エントリーに序数と名前文字列の組み合わせを使用していることがわかります。
序数によって解決する必要があるビーコンDLLの一部のインポート・エントリーを示すPE-Bearのスクリーンショット。
内蔵のCobalt Strike Reflective Loaderは
APIアドレスを解決するためのいくつかの回避方法は次のとおりです。
のカスタム・コード実装GetProcAddress
NTDLL.LdrGetProcedureAddress
BokuLoaderはのカスタムコード実装を使用していますGetProcAddress
このは名前文字列と序数の両方を処理することもできます。Import Entryの返されたアドレスが別のDLLへのフォワーダーである場合、BookLoaderはデフォルトで
IATを作成する際に、意図したAPIのアドレスではなく、実装したフック関数のアドレスを作成することでフックを実装できます。IATのアドレスが呼び出されたときに期待されるアウトプットがビーコンに返される限り、ビーコンに戻る前に追加のコードを実行できます。今後の投稿とBokuLoaderの公開リリースでは、高度な主要な機能にIATフックを活用する方法を紹介する予定です。
最近のリリースで、公開されているBokuLoaderプロジェクトはカスタム実装を備えたCobalt Strike C2プロファイルの主要なPE機能。マスキングキーを変更することでBokuLoader.cna
運用上のセキュリティーに関しては、パターン・マッチング・エンジンがシングル・バイトXORマスクを総当たり攻撃で実行できることを知っておくことが重要です。今後の投稿では、Cobalt Strikes Aggressorスクリプト機能を使用して独自のMalleable PEエンジンを作成し、ビーコンを難読化してパターン・マッチングを克服する方法を紹介します。
ビーコンDLLには、実行前に解決して仮想ビーコンDLLの基本再配置テーブルに書き込む必要がある再配置が多くあります。
PE-Bearでは、デフォルトのビーコンDLLのイメージ・ベース・アドレスがあることが確認できます
PE-Bearのスクリーンショットで、ビーコンDLLの画像ベース・アドレスを示しています。
再配置の書き込みを開始する前に、仮想ビーコンDLLの基本アドレスとハードコードされた基本アドレスの間の差分を計算する必要があります。
例えば、仮想ビーコンDLLの基本アドレス
次に、基本再配置テーブル内の各再配置エントリーの仮想アドレスを決定するために、ハードコードされた再配置エントリー・アドレスに基本アドレス・デルタを追加して、仮想ビーコンDLL 内の再配置を決定します。
以下の画像では、ビーコン再配置エントリーがリトル・エンディアン形式で逆に書かれていることがわかります。
PE-Bearのスクリーンショットには、一部の再配置エントリーがリトルエンディアン形式で存在していることが示されています。
この再配置エントリーのハードコード化されたアドレスは次のとおりです
このアドレスをベース・アドレス・デルタに追加して、仮想ビーコンDLLに存在する再配置の仮想アドレスを取得します。
再配置のエントリーごとに、タイプが次のとおりであることを確認する必要があります。
<a title="https://learn.microsoft.com/jp-ja/windows/win32/debug/pe-format"href="https://learn.microsoft.com/jp-ja/windows/win32/debug/pe-format">IMAGE_REL_BASED_DIR64(0xA)</a>
。これが偽の場合は、再配置の作成をスキップします。
仮想ビーコンDLL内に存在する再配置の仮想アドレスを決定すると、ハードコード化された再配置エントリー・アドレスを保持するメモリー空間にそれを書き込みます。
PEの再配置方法についてもっと知りたい方は、公開されているBokuLoaderプロジェクトのdoRelocations関数コードをご覧ください。このブログ記事を公開する前に、再配置コードをアセンブリから人間が読み取れるCコードに変更しました。これは、この方法の技術的な詳細を知りたい他のユーザーを支援するためです。
ビーコンの実行は、次の3つのステップに分類できます。
仮想ビーコンDLLに割り当てたメモリーが
仮想ビーコン・メモリーを非実行型(
公開されているBokuLoaderプロジェクトでは、メモリー保護の変更は次のシステム・コールを直接呼び出すことで実行されます。
.textの変更を示すBokuLoaderプロジェクトのコード・サンプルで仮想ビーコンDLLのセクションを実行可能に変更する方法を示しています。
本
仮想ビーコンDLLを適切に実行するには、まず仮想ビーコンDLLのエントリー・ポイントを呼び出して初期化する必要があります。最初の引数は仮想ビーコンDLLのベースアドレスです。2番目の引数は
仮想ビーコンDLLを初期化するBookLoaderプロジェクトのコード・サンプル。
仮想ビーコンDLLを初期化した後、仮想ビーコンのエントリー・ポイントをReflective Loaderスタブ呼び出しに戻すか、
最初の引数である典型的なDLLとは異なり
<a href="https://learn.microsoft.com/jp-ja/windows/win32/dlls/dllmain">DLLMAIN</a>
仮想DLLのベースアドレスである場合、ビーコンはRawビーコンDLLのベースアドレスを期待します。これが供給されていない場合、一部のMalleable PE回避機能が失敗する可能性があります。
仮想ビーコンDLLを実行する2つの異なる方法を示すBokuLoaderプロジェクトのコード・サンプル
ブログ記事が、レッド・チームとブルー・チームの両方がCobalt Strikeとリフレクティブ・ローディング・プロセスをより深く理解する上で役立つことを願っています。リフレクティブ・ローディングを通じて実現できる回避の機会はまだたくさんあります。これらの概念をより深く理解することで、組織はサイバー脅威に対する防御を成功させるための準備を強化できます。
このシリーズの今後の投稿では、UDRLと現在のCobalt Strikeの回避主要な機能の統合、公開されているBokuLoaderにすでに存在する文書化されていない回避主要な機能の掘り下げ、そしてまだ公開されていない高度な主要な機能に焦点を当てます。UDRL開発でCobalt Strikeゲームを高めるための詳細な情報やテクニックを、今後お伝えしてまいりますので、どうぞご期待ください。