
CobaltStrike BOFを使用して、DLLアプリケーションディレクトリハイジャッキングによりBeaconを起動する
DropSpawnは、比較的知られていないDLLハイジャックの手法を用いて追加のBeaconを起動するためのCobaltStrike BOFです。x86-x86、x64-x64、x86-x64/その逆の組み合わせで動作します。プロセスインジェクションの代替手段として使用してください。
Windows実行ファイルは、絶対パスが指定されていないDLLを読み込む際にDLL検索順序に従います:

DLLハイジャックには通常、以下のいずれかの条件が必要です:
A. ユーザーが、実際のDLLが存在するフォルダよりも検索順序の優先度が高いフォルダに対して書き込み権限を持っている
または
B. 対象のDLLがシステム上のどこにも存在せず、ユーザーの%PATH%変数内のユーザー書き込み可能なフォルダ(%USERPROFILE%\appdata\local\microsoft\windowsappsなど)に配置できる。
これらの要件により、C:\Windows\System32に存在する実行ファイルに対するDLLハイジャックはほぼ不可能です。なぜなら、これらの実行ファイルが読み込むほとんどすべてのDLLもSystem32に存在するからです。System32の実行ファイルをユーザー書き込み可能な場所にコピーしてそこで実行する方法もありますが、代替の場所から実行されるSystem32バイナリは識別が容易なため、OPSEC的に安全ではありません。
DropSpawnは、「アプリケーションが読み込まれるディレクトリ」を任意のユーザー指定の場所に偽装することで、System32の実行ファイル(および他の非ユーザー書き込み可能なフォルダにある実行ファイル)を使用したDLLハイジャックを可能にします。
公開版のDropSpawnは非公開版とは若干異なります。非公開版は独自のペイロードジェネレータを活用しており、オペレーターにとってよりシームレスな操作体験を提供します。公開版は、ユーザーがそれぞれ独自の方法でDLLハイジャック互換ペイロードを生成することを考慮して若干変更されています。DropSpawnの統合と武器化を支援するために、Python3スクリプトとデモ用DLLのソースコードが含まれています。
絶対パスを指定せずにDLLを読み込もうとする対象の実行ファイルを特定します。これは、exeをユーザー書き込み可能なディレクトリにコピーし、Procmonで監視しながら実行することで行えます。この例では、通常C:\Windows\System32\WerFault.exeに存在するWerFault.exeを使用します。

上記の例では、cryptsp.dll、wer.dll、dbghelp.dll、bcrypt.dllはすべて、WerFault内で絶対パスが指定されていないため、実行可能な候補です。その結果、WerFaultはDLL検索順序の残りを参照する前に、まずアプリケーションディレクトリからそれらを読み込もうとします。通常これは問題になりません。なぜならWerFaultのアプリケーションディレクトリはSystem32そのものだからです。
対象システムからハイジャック可能なDLLの1つをダウンロードします。
これは、そのエクスポートを抽出してペイロードDLLに含めるために必要です。DLLはWindowsのバージョンによって異なるため、DropSpawnを使用する予定の同じマシンからハイジャック可能なDLLを取得することが重要です。さらに、x86ビーコンを実行していてDropSpawnを使用してx64ビーコンを起動したい場合は、'C:\windows\system32...'の代わりに'C:\windows\sysnative...'を指定して、実際のDLLのx64バージョンをダウンロードしてください。
ダウンロードしたDLLと希望するペイロードアーキテクチャを指定して、generate_dll.pyを実行します。Generate_dll.pyはこのスクリプトの修正版です。指定されたDLLを解析し、DLLのエクスポートを含む.defファイルを作成し、MingWを呼び出してデモ用ペイロードDLLをコンパイルします。起動されたプロセスが偽装されたDLL内の実際の関数を呼び出そうとすると、ペイロードDLLはSystem32にある実際のDLLに呼び出しを転送し、ホストプロセスがクラッシュしないようにします。

生成されたペイロードDLLを使用してdropspawnを呼び出します。
dropspawn <ペイロードDLL> <x86|x64> <起動するプログラム> [書き込み可能なターゲットフォルダ] [親プロセス]
ペイロードDLL - 生成されたDLLペイロードへのフルパス。
アーキテクチャ - 起動したいプロセスのアーキテクチャ
起動するプログラム - 起動したいプロセスの名前/パス。このプロセスがSystem32(またはsyswow64)に存在する場合は、名前のみを指定できます。それ以外の場合は、フルパスを指定してください。プロセスにコマンドライン引数を渡すこともできます。パスにスペースが含まれる場合や引数を使用する場合は、全体を引用符で囲んでください。
書き込み可能なターゲットフォルダ - 任意。空白のままにすると、dropspawnはBeaconの現在のディレクトリを使用しようとします。パスにスペースがある場合は引用符を使用してください。
親プロセス - 任意。新しく起動されたプロセスでPPID偽装に使用するプロセスの名前。異なる権限レベルの複数の実行インスタンスを持つプロセス(例:svchost.exe)が指定された場合、dropspawnはPPID偽装に使用できるものを特定しようとします。
例:dropspawn /root/dbgcore.dll x64 "WerFault.exe -u -p 4352 -s 160" C:\users\user\appdata\local\temp explorer.exe
これにより、ペイロードDLL 'dbgcore.dll'が'c:\users\user\appdata\local\temp\dbgcore.dll'としてディスクに配置され、コマンドライン引数'-u -p 4352 -s 160'を持つx64のWerFault.exeプロセスがexplorer.exeを親プロセスとして起動されます。


クリーンアップは簡単です。ディスクに配置されるペイロードDLLに自己削除機能を含めることで、新しいプロセスが起動してDLLを読み込むとすぐに削除されます。これは画期的なことです。通常、DLLを読み込んだプロセスが実行し続ける限り、DLLはディスク上でロックされるためです。自己削除技術が何らかの理由で失敗した場合(またはプロセスの起動に失敗した場合)、DropSpawnはディスクからペイロードDLLの削除を試み、いずれの場合も操作の結果をユーザーに通知します。
プロセスインジェクションは通常、リモートプロセスのオープン → リモートメモリの割り当て → リモートメモリへの書き込み → リモートメモリの実行というチェーンに従い、最初に既存のプロセスを使用する代わりに新しいプロセスを起動するオプションがあります。DropSpawnは新しいプロセスを作成するだけです。新しく起動されたプロセスがシェルコードの割り当て、書き込み、実行を担当するため、リモートプロセスインジェクションに通常関連する多くのIOCを回避できます。
この技術はもちろん、DLLペイロードの品質に左右されます。しかし、Windowsが何を見ているかを確認できます(この次のセクションでは、プライベート版のDropSpawnを使用し、Beaconを起動しています)。
イベントビューアに関しては、すべてが正常に見えます:

MDEでは確認できるものはほとんどありません。
dropspawnの実行:

MDEログ:
PPID偽装あり:

PPID偽装なし:

どちらの場合も、元のビーコンプロセス(これもwerfault)がdbgcore.dllをディスクに配置し、新しいWerFault.exeプロセスを作成し、新しく起動されたプロセスがdbgcore.dllを読み込み、その後それを名前変更(削除)しているのが確認できます。重要なのは、DLLハイジャックに伴うことの多いdbgcore.dllへの追加の精査がないことです。なぜなら、頻繁にハイジャックされる場所に書き込んでいるわけではなく、WerFault.exe(または選択したプロセス)はWmiPrvSE.exeなどのようにDLLハイジャックと関連付けられていないからです。
興味深いことに、PPID偽装を使用した場合の方が、使用しない場合よりもほぼ可視性が高くなります。ただし、これはセキュリティ製品によって異なる場合があります。
前述のとおり、ユーザーはDropSpawnを使用する予定のターゲットマシンから実際のDLLをダウンロードすることが不可欠です。DLLの誤ったバージョンを使用すると、存在しない関数を呼び出そうとした場合に起動されたプロセスがクラッシュする可能性があります。
DropSpawnはSystem32以外の実行ファイルでも使用できます。ただし、プロセスが実際のアプリケーションディレクトリから追加のDLLを読み込もうとした場合に問題が発生する可能性があることに注意してください。アプリケーションディレクトリを別の場所に偽装しているため、実際のアプリケーションディレクトリがDLL検索順序を通じて到達可能でない場合、プロセスは必須のDLLを見つけられずにクラッシュまたは起動に失敗します。本番環境で使用する前に、必ず開発マシンで潜在的なハイジャックをテストしてください!
この研究は、プロセスが最終的なDLL検索順序をどのように組み立てるかを調査していた際に始まりました(実行ファイルが異なるディレクトリに存在すること、現在のディレクトリが検索パスの一部であることなどにより、実行時に決定する必要があるため)。私の調査はこのフォーラム投稿にたどり着き、この技術の中心となる2つの重要な非公開APIの起源となりました。
これらはすでにリンクされていますが、ローダーロックの回避に関するこの投稿、DLLプロキシ用の.defファイルを生成するこのスクリプト、および実行中の実行ファイルの自己削除を可能にするこの研究は、DropSpawnに適した効果的な武器化されたDLLペイロードを生成するために不可欠です。
この技術をTwitterで最初に公開したとき、他の数人が会話に参加してPOCを制作しました。SecurityAndStuffはこれを制作し、Snovvcrashはこちらに彼のものを公開しています