メモリ解析によるCobalt Strikeの撃沈

Conceptual image representing evasive malware such as Cobalt Strike

This post is also available in: English (英語)

概要

本稿ではUnit 42のリサーチャーがCobalt Strikeコンポーネントを組み込んだ複数のマルウェアサンプルを検証します。実行上の重要ポイントにおけるプロセスメモリ内の差分から得られたアーティファクトを分析し、これらサンプルを捕捉する方法を解説します。またこれらの脅威が使う回避戦術など、解析上問題となるポイントについても説明します。

Cobalt Strikeはレッドチーム演習用の敵対的シミュレーションフレームワークの1つですが、長年にわたり検出エンジンを悩ませてきた回避型マルウェアの典型的特徴を備えていることから、その人気はレッドチームにとどまらず、脅威アクターの多くが悪意のある目的に利用しています。

ツールキットそのものは実践的セキュリティテストを行いたい信頼すべき団体だけに販売されているのですが、ソースコードがリークしたことから、そのさまざまなコンポーネントが、ランサムウェアグループから国家支援型攻撃グループにわたる、幅広い脅威アクターたちの兵器庫へと流れつくことになりました。2020年に発生したあのSolarWindsのインシデントでも、Cobalt Strikeを悪用するマルウェア作者が暗躍しました。

関連するUnit 42のトピック Cobalt Strike, Sandbox

目次

Cobalt Strikeの概要
KoboldLoader SMBビーコン
メモリ内での回避
MagnetLoader
LithiumLoader
LithiumLoader検出上の問題
メモリ解析を通じたCobalt Strikeの捕捉
ペイロードの自動抽出
関数ポインタデータ
OSの構造体の変更
ページパーミッション
結論
IoC
付録

Cobalt Strikeの概要

Cobalt Strikeが広く愛される理由はその性能の高さにあります。同製品はレッドチームがセキュリティベンダに先んじてペイロードを強化できるよう一から設計されたもので、定期的に新たな回避技術を取り入れてその優位性を維持しています。

Cobalt Strikeの大きなメリットの1つは、初期ローダーを実行した後はほぼメモリ内でのみ動作することです。悪意のあるペイロードが静的に兵器化されていて、メモリ内にしか存在せず、実行されることを拒むようなケースでは、これが検出上の問題となります。セキュリティソフトウェアの多くはこうした課題を抱えています。メモリのスキャンは簡単なものではないのです。

これらの理由から、標的ネットワークへの初期アクセス確保には、自然とCobalt Strikeが選ばれることが多くなります。脅威アクターは、さまざまなデプロイオプションや難読化オプションを備えたビルダーを使い、カスタマイズ可能なテンプレートをもとに最終ペイロードを作れます。

このペイロードは通常、暗号化ないしエンコードされた状態でファイルローダーに埋め込まれます。被害者がこのファイルローダーを実行すると、ペイロードがメモリ内に復号ないしデコードされて実行されます。このペイロードはメモリ内で元の状態のままで存在することから、ある種の特徴にもとづいて容易に検出できます。

マルウェアを調査していると、「これは興味深いものかもしれない」と思われたマルウェアのサンプルが単なるCobalt Strikeローダーであることがわかるケースも多々経験します。また、そうしたローダーがレッドチームが作成したものなのか実際の脅威アクターが作成したものなのかがわからないケースも多く、その分、アトリビューションが難しくなっています。

以下のセクションでは3種類のCobalt Strike Loaderのサンプルを詳しく見ていきますが、これらの検出は、私たちが設計した新しいハイパーバイザベースのサンドボックス上で行いました。このサンドボックスを使えば、とくに設定をしなくとも、メモリ内のアーティファクトを分析してくれます。各サンプルは、SMB Beacon、HTTPS Beacon、Stager Beaconという異なる種類のインプラントをロードするもので、私たちはそれぞれをKoboldLoader、MagnetLoader、LithiumLoaderと名付けました。本稿ではまた、これらペイロードの検出に使える手法をいくつか解説していきます。

KoboldLoader SMB Beacon

今回確認するサンプルは弊社のお客様のインシデントで検出されたものです。

SHA256:7ccf0bbd0350e7dbe91706279d1a7704fe72dcec74257d4dc35852fcc65ba292

この64ビットのKoboldLoaderの実行ファイルは、さまざまな既知の策略を弄してサンドボックス回避や解析時間引き伸ばしをはかります。

ネイティブのAPI関数だけを呼び出すことで、高レベルなユーザーモードの関数のみをフックするサンドボックスを回避します。平文文字列を使わず、ハッシュを使って動的に関数を解決することでアナリストの負荷を高めます。このマルウェアには、以下の関数を呼び出すコードが含まれています。

  • NtCreateSection
  • NtMapViewOfSection
  • NtCreateFile (未使用)
  • NtAllocateVirtualMemory (未使用)
  • RtlCreateProcessParameters
  • RtlCreateUserProcess
  • RtlCreateUserThread
  • RtlExitUserProcess

このマルウェアは関数ハッシュと関数アドレスをペアにしたテーブルを2つ、個別に作成します。1つめのテーブルにはすべてのネイティブの関数につき1つのペアが含まれ、2つめのテーブルにはNt*関数に限定したペアが含まれています。

使用されているRtl*関数の場合、1つめのテーブルをループして関数のハッシュを検索し、関数アドレスを取得します。使用されているNt*関数の場合、2つめのテーブルをループしてそれと同時にカウンタ変数を増加させます。

対象ハッシュが見つかると、このハッシュが対となるカウンタ変数の値(ネイティブ関数のシステムコール番号に相当)を受け取り、カスタムのsyscallスタブに移ります。この方法だと、たとえ高レベルのネイティブ関数の代わりに低レベルの組み込み関数がフックされた場合でも、多くのサンドボックスを効果的に回避できます。

ローダーの全般的な機能はわりあいにシンプルで、ペイロードの実行にはマッピングインジェクションが使われています。Windowsツールのsethc.exeの子プロセスを生成してから新しいセクションを作成し、復号されたCobalt Strike Beacon Loaderをその中にマッピングします。RtlCreateUserThreadを呼び出すことでCobalt Strike Loaderが最終的に実行され、Cobalt Strike LoaderがSMB Beaconをロードします。

復号されたBeaconの設定データは付録のセクションで確認してください。

メモリ内での回避

私たちが新たに作成したハイパーバイザーベースのサンドボックスは、復号されたCobalt Strike SMB Beaconをメモリ内でうまく検出してくれました。このBeacon Loaderにはいくつかメモリ内での回避機能が使われていますが、これは奇妙なタイプのキメラファイルを作成します。このキメラファイルは実際にはDLLなのですが、PEのマジックナンバー「MZ」と後に続くDOSヘッダが、短いローダーのシェルコードで上書きされているのです(図1)。

Cobalt Strike Beacon Loaderを逆アセンブルして得たシェルコードの解説図
図1. Cobalt Strike Beacon Loaderのシェルコードを逆アセンブルしたもの

このシェルコードローダーはエクスポートされた関数DllCanUnloadNowにジャンプし、この関数はメモリ内のSMB Beaconモジュールを準備します。この準備にあたって同関数はまずWindowsのpla.dllライブラリをロードし、同ライブラリのコードセクション(.text)内のある領域のバイトをすべてゼロにします。その後、ゼロにした領域にBeaconファイルを書き込み、インポートアドレステーブルを修正することで、実行可能なメモリモジュールを作成します。

このファイルを解析してみると、使われていたメモリ内での回避機能をいくつかを把握できました(表1)。

回避機能 説明 このサンプルで使われていたかどうか
allocator BeaconのReflectiveLoaderがエージェントのメモリをどのように割り当てるかを設定する。オプション: HeapAlloc, MapViewOfFile, VirtualAlloc いいえ
cleanup Beaconを初期化した反射型DLLパッケージに関連するメモリの解放を試みるようBeaconに依頼する はい
magic_mz_x64 Beaconの反射型DLLの最初のバイト(MZヘッダを含む)を上書きする。有効なx86命令が必要。CPUの状態を変更する指示の後につづけてその変更を打ち消す指示を出す。 はい
magic_pe BeaconのReflectiveLoaderが使うPEのマジックナンバーを別の値で上書きする いいえ
module_x64 VirtualAllocでメモリを確保する代わりに、指定されたライブラリをロードしてその領域を上書きするようにx86反射型ローダに依頼する はい
obfuscate 反射型DLLのインポートテーブルを難読化し、未使用のヘッダコンテンツを上書きし、ReflectiveLoaderに対してDLLヘッダなしで新しいメモリにBeaconをコピーするよう依頼する はい
sleep_mask スリープの前にBeaconとそのヒープをメモリ内で難読化する いいえ
smartinject Beaconエージェントをブートストラップするさい、組み込みの関数ポインタヒントを使い、kernel32のExport Address Table(EAT)は調べない いいえ
stomppe Beaconペイロードのロード後に、ReflectiveLoaderに対し、MZ、PE、e_lfanewの値を上書きするよう依頼する いいえ
userwx ReflectiveLoaderに対し、メモリ内のBeacon DLLに対する読み取り/書き込み/実行(RWX)パーミッションの使用または回避を依頼する いいえ

表1 使用されていたCobalt Strikeの回避技術

結論から言うとBeacon LoaderとBeacon本体は同一ファイルです。PEヘッダの一部はエクスポートされた関数にジャンプするシェルコードに使用されていて、この関数がWindows DLL内に自身のモジュールを作成します。最後にこのシェルコードはBeaconモジュールのエントリポイントにジャンプし、メモリ内でモジュールを実行します。

したがって、実行中のメモリ内部を覗けないかぎり、KoboldLoaderサンプルのBeaconをうまく検出する方法はありません。

MagnetLoader

本稿で確認する2つめのローダーは、正規ライブラリを模した64ビットDLLです。

SHA256: 6c328aa7e0903702358de31a388026652e82920109e7d34bb25acdc88f07a5e0

このMagnetLoaderのサンプルは、以下の似た機能をもたせることで、Windowsファイルのmscms.dllにいくらか似せようとしています。

  • ファイルの説明が同じ
  • エクスポートテーブルに同一関数名を多数含む
  • リソースがほぼ同一
  • ミューテックスが酷似

これらの特徴を図2に示します。ここではマルウェアファイルと正規のmscml.dllとを対比しています。

EXE Explorerを使って左右に並べて比較した画像。マルウェアファイルと正規のmcml.dllとの対比。左がMagnetLoader、右がmsmcl.dll。ファイルの説明、エクスポートテーブル、リソースを並べて比較している。
図2. EXE Explorerを使ってMagnetLoader(左)とmscml.dll(右)のファイルの説明、エクスポートテーブル、リソースを比較したところ

MagnetLoaderは正規Windowsライブラリを静的に模倣するだけでなく、ランタイムにも模倣しようとします。

エクスポートされたMagnetLoaderの関数はすべて、内部では同一のメインルーチンを呼び出します。これらいずれかの関数が呼び出されると、最初にDLLのエントリポイントが実行されます。このエントリポイント内で、同マルウェアはオリジナルのmscms.dllをロードし、これがすべての偽関数を解決します。

これらオリジナルの関数アドレスは保存されて、偽メソッドの実行後に呼び出されます。このように、エクスポートされたMagnetLoaderの関数のいずれかが呼び出されると、そのつどマルウェアのメインルーチンが実行されてからオリジナルのmscms.dllの関数が呼び出されます。

マルウェアのメインルーチンはわりあいにシンプルです。最初に、mscms.dllが作成するオリジナルのものに酷似したSM0:220:304:WilStaging_02_p1hというミューテックスが作成されます。

Cobalt Strike Beacon Loaderは、既知の策略の助けを借りてメモリバッファ内に復号され、実行されます。このさい、Beacon Loaderを直接呼び出さず、Windows API関数EnumChildWindowsを使って実行します。

この関数は3つのパラメータを持ちますが、そのうちの1つがコールバック関数です。このパラメータを悪用すると、マルウェアはコールバック関数経由で間接的にアドレスを呼び出すことで実行フローを隠蔽できます。

これについても、復号されたBeaconの設定データは付録のセクションで確認してください。

LithiumLoader

最後のCobalt StrikeサンプルはDLLサイドローディングの攻撃チェーンの一部として使われていたもので、このなかではある種のセキュリティソフトのカスタムインストーラが使用されていました。DLLサイドローディングは正規のアプリケーションを乗っ取って別の悪意のあるDLLを実行させる技術を指します。

SHA256: 8129bd45466c2676b248c08bb0efcd9ccc8b684abf3435e290fcf4739c0a439f

この32ビットのLithiumLoader DLLは攻撃者がカスタムで作成したFortinet VPNインストールパッケージに含まれているもので、VirusTotalにFortiClientVPN_windows.exe (SHA256: a1239c93d43d657056e60f6694a73d9ae0fb304cb6c1b47ee2b38376ec21c786)として提出されています。

なお、攻撃者が作成した自己解凍型RARアーカイブであるFortiClientVPN_windows.exeのなかにはFortiVPN.exeというファイルが含まれていますが、このFortiVPN.exeは署名済みの正規インストーラであって悪質なものではなく、侵害もされていません。FortiVPN.exeは署名されているので、攻撃者はこれを利用してアンチウイルス検知を回避していました。

このインストーラは自己解凍型のRARアーカイブで、以下のファイルを含んでいます。

ファイル名 説明
FortiVPN.exe 正規の署名のついたFortiClient VPNオンラインインストーラ v7.0.1.83
GUP.exe 正規の署名のついた WinGup for Notepad++ ツールの v5.2.1.0
gup.xml WinGupの設定ファイル
libcurl.dll LithiumLoader

表2aFortiClientVPN_windows.exe ファイルの内容。

自己解凍型スクリプトコマンドは以下の通りです。

RARファイルの自己解凍スクリプトコマンドのスクリーンショット。コードは全部で5行。
表2b. 自己解凍型スクリプトコマンドの一覧

インストーラを実行するとこれらすべてのファイルがローカルの%AppData%フォルダにひそかにドロップされ、両方の実行ファイルが起動します。FortiClient VPNインストーラが実行される間、WinGupツールはlibcurl.dllのLithiumLoaderマルウェアをサイドローディングします。このマルウェアは、図3に示すように、libcurlライブラリの正規のコピーから以下の関数をインポートしているのでこのような動作になります。

WinGub.exeのインポートアドレス。左列のlibcurl.dll(4)、右列のcurl_easy_setopt、Ordinal、Addressがハイライト表示されている。
図3. WinGup.exeのインポートアドレステーブル

この脅威はまた、PowerShell経由でWindows Defenderの除外リストに%AppData%フォルダのパスを追加しようとします。

GUP.exeの起動時は、上の図3で示した関数を静的にインポートして悪意のあるlibcurl.dllファイルがプロセス空間にロードされます。4つのlibcurl関数はすべて実行されますが、curl_easy_cleanupだけが、このライブラリの新たなバージョンのコンパイル時にインジェクトされた悪意のあるルーチンを含んでいます。したがって、私たちがここで相手にしているのは、正規のDLLにパッチを適用したものではありません。他のマルウェアでは悪意のあるルーチンの挿入後にコードが壊れることが多いですが、これならコードは壊れないのでよりクリーンな方法といえます。

このcurl_easy_cleanup関数は通常1つのサブルーチン(Curl_close)のみを含み、戻り値はありません(GitHub上のソースコードに記載済み)。変更後の関数は図4のようになります。

変更されたcurl_easy_cleanupエクスポート関数の9行分のコードを示したスクリーンショット。int __cdel curl_easy_cleanup(Curl_easy *data)の行をハイライト表示している
図4. libcurl.dllのcurl_easy_cleanupエクスポート関数が修正されている

load_shellcode関数はXORと鍵0xAを介してシェルコードを復号します(図5)。

28行のコードを示したスクリーンショット。BOOL load_shellcode()がハイライトされている。この関数は、14行目と22行目でXORと鍵0xAを介してシェルコードを復号している
図5. シェルコードローダーの関数load_shellcode()

この関数は、Cobalt Strikeのステージャーのシェルコードに直接ジャンプするのではなくEnumSystemGeoID経由で間接的に実行します。このWindows API関数にはパラメータが3つありますが、最後の1つがLithiumLoaderの悪用するコールバック関数です。

Cobalt StrikeのステージャーのシェルコードはMetasploitから借用したものです。これはリバースHTTPシェルペイロードで、以下のAPI関数を使います。

  • LoadLibrary
  • InternetOpenA
  • InternetConnectA
  • HttpOpenRequestA
  • InternetSetOptionA
  • HttpSendRequestA
  • GetDesktopWindow
  • InternetErrorDlg
  • VirtualAllocStub
  • InternetReadFile

このシェルコードはあるタイ国内の大学のIPアドレスに接続していました。

LithiumLoader検出上の問題

本解析執筆時点ではすでにこのCobalt Strike Beaconのペイロードは入手できなくなっています。API呼び出しの実行レポートからペイロードか調査に使える情報を拾えないと、サンドボックスによるサンプルの悪性度判定は難しいことが多いです。このサンプルそのものには悪性と分類すべき機能はありません。

メモリ解析を通じたCobalt Strikeの捕捉

これら3つのサンプルには、通底する検出上の課題があります。これらのサンプルは通常のサンドボックス環境では実行されません。ただし前述のとおり、関数ポインタ、ローダーのデコード段階、その他もろもろのアーティファクトなど、実行中のメモリ内部を調べれば検出に使える情報は豊富にあります。

長らくサンドボックスシステムの標準的な使い方といえば実行中のプログラムの活動計測や観察でしたが、この間私たちが学んだことがあるとするならそれは「高度に回避的なマルウェアに対してはそれだけでは不十分」ということでした。そのためここ数年、この手の高度に回避的なマルウェアをさらに徹底して処理する方法を見つけ出す努力を重ねてきました。

そして、高度に回避的なマルウェアを正確に検知するには、システムAPIの利用に加え、サンプル実行時のメモリ調査が重要な機能の1つとなることがわかりました。

図6. 高次で見たAdvanced WildFireの検出戦略
図6. 高次で見たAdvanced WildFireの検出戦略

マルウェアの検出では、実行時の重要ポイントにおけるメモリの差分を調べることで、意味のある情報やアーティファクトを引き出す方法が有効でした。私たちのシステムで扱うサンプル数は膨大なので、これをスケールしつつ実現するのはそうたやすいことではなかったのですが、マルウェア解析に特化した主力カスタムハイパーバイザーに、エンジニアリング上のさまざまな工夫が加わって、このアイデアを実現することができました。

以下のセクションでは、私たちが現在、検出支援のためにメモリから収集している主なデータの種類を詳しく説明します。このデータはアナリストによる手動のシグネチャ作成にも機械学習パイプラインにも活用できます(これについては今後また別のブログで解説します)。

なお本稿はメモリに焦点を当ててはいますが、決して「API呼び出しの処理やログ収集は検知には役に立たない」と言いたいわけではありません。私たちは、実行ログとメモリ解析データを合わせれば、それらを個別に見るより大きな結果を出せると考えています。

ペイロードの自動抽出

先にも触れましたが、マルウェア作者による初期ペイロードの難読化は常態化してきています。ファイルを圧縮・難読化できる実行形式パッカーを使ってこれをやるのであればとくに珍しくもないのですが、これが回避策と組み合わさった場合、正確な検知に使える静的・動的データがないことから問題となります。

エンコード、圧縮、暗号化、実行用追加ステージのダウンロードなど、戦略の組み合わせは無限にあります。こうしたペイロードに対応するシグネチャの作成能力が重要なことは明らかで、それを使えばアナリストがCobalt Strikeのようなフレームワークからのさまざまなマルウェアコンポーネントを検出できるようになります。メモリ内でマルウェアが捕捉できれば、最終的にそのマルウェアが実行停止の判断をしたって問題にはなりません。

この図7の簡略図は、実際には初期実行ファイルに存在していなかった複数のステージで、その後おそらく確認されることになっていたであろう内容を示したものです。

パックされたマルウェア実行ファイルに含まれていた可能性のあるステージをハイライトした簡略図。左側にあるのが実行可能イメージの中に含まれるシェルコードのステージ。矢印でスタックを経てヒープに至るようすを示している。シェルコードはスタックからPEへと移動していく。
図7 パックされたマルウェアの実行ファイルで見られる典型的ステージ

図の左側はシェルコードステージの例です。もともと「シェルコード」という言葉は、標的システム上でシェルを起動するためにエクスプロイトが使うハンドメイドのアセンブリを指していましたが、いまでは不正目的で書かれたカスタムアセンブリ一般を指すようになっています。マルウェアのステージのなかには、はっきりそれとわかる実行可能構造を持たないカスタムアセンブリのかたまり、といったものもあります。このアプローチをとるマルウェア作者でよく見られるのが、すべての関数ポインタを動的に解決してテーブルを作成してアクセスしやすいようにする、というパターンです。

図の右側はもっと後のステージの例で、この段階では実行ファイルの形式が整ってきています。マルウェアのステージやペイロードのなかに、きちんとした実行形式を持つものが見られます。これらのステージやペイロードは、システムAPIを介してOSにロードさせる場合もありますが、マルウェア作者が検出の回避を狙っている場合は、独自のPEローダーを使って、APIを呼び出さずにすませることもあります。

関数ポインタデータ

メモリから抽出できるもうひとつの豊富なデータセットが動的に解決される関数ポインタで、私たちはこれを検出に使い始めています(図8)。マルウェアの作者たちは、使いたいWINAPI関数をぜんぶインポートテーブルから明示的に呼び出してしまうとそれが仇となることをずいぶん前に学んでいます。ですので、マルウェアやそのステージで使用する関数を隠すことがいまでは標準的手順となっています。

シェルコードのハッシュ化もよく見られるステルス戦略で、文字列なしで関数ポインタを解決するのに使われます。

メモリセグメント内で見られる、動的に解決されるWINAPIポインタの概念図。左はAPIポインタのデータを示すブロック。右が対象となるOSのライブラリ。
図8. メモリセグメント内で動的に解決されるWINAPIポインタの例

Advanced WildFireでは、検出ロジックにおいてどのWINAPI関数ポインタが解決されたかについての情報を選択的に検索・利用するようになりました。

OSの構造体の変更

メモリの分析によって得られるもう1つの有用な検出データソースが、Windowsが状態管理用に使っている構造体(マルウェア作者はこれらをいじるのが大好き)へのあらゆる変更の探索です。これらの構造体はOSによるプロセスの状態管理に重要で、これを使ってOSは「どのライブラリがロードされたか」、「実行可能イメージはどこにロードされたか」、「後で知る必要のあるプロセスの特徴とはどのようなものか」を管理しています。これらのフィールドの大半は決して変更されるべきではないものですが、マルウェアサンプルがいつ・どのようにこれらのフィールドを操作したかを追跡すると有益な情報を得られる場合が多いです。

図9は、あるマルウェアサンプルが、LDR_MODULEのリストからロードしたモジュールをアンフックする手口の1つを示したものです。モジュールのアンフックはそのモジュールの存在記録がなくなるということを意味します。そのため、たとえばこの処理後には、Windowsのタスクマネージャーには表示されなくなります。

この図はこれまでに私たちが目にしたさまざまなOSの構造体改ざんの1例に過ぎませんが、マルウェアの検出上生じる問題への対応に使えるOS構造体の改ざんが数多く存在することを教えてくれます。

この画像は左の3つのフィールド (実行中のスレッド情報を保持する構造体Thread Information Block (TIB)、実行中のプロセスの情報を保持する構造体Process Environment Block (PEB)、対象プロセス用にロードされたモジュールの情報を保持するPEB_LDR_DATA構造体) へと進むようすを表している。矢印が1本伸びておりPEB_LDR_DATA構造体からLDRモジュール群への進行を示している。LDR_MODULEのntdll.dllがLDR_MODULEのkernel32.dllへと進み、マルウェアからkernel32.dllをアンフックして、someOtherLib.dllに置き換えている。
図9 LDR_MODULEのリストからモジュールがアンフックされるようすを描いた例

ページパーミッション

最後に紹介する有用な検出データソースは、ページパーミッションに加えられた全変更の完全なログです。パックされたマルウェアの作者は、続くステージを正常にロード・実行する上でメモリのパーミッションを変更せねばならないことが多いので、メモリのどのページのパーミッションが変更されたかを理解すれば、コードのロード・実行位置についての重要な知見が得られ、検出に役立つことがあります。

結論

Cobalt Strikeは何年も前から存在していますが、その検出はいまだ多くのセキュリティソフトウェアベンダを悩ませています。その原因は、このツールがほぼメモリ内だけで活動し、初期ローダーをのぞいてはディスクにさわらないことにあります。

本稿では、新たなローダー3種について解説し、さまざまな手法による検出を紹介しました。これらの検出技術は、弊社の新たなハイパーバイザーベースサンドボックスに搭載済みです。

図10はKoboldLoaderの検出理由を示したものです。

マルウェアを特定しているスクリーンショット。判定、検出理由1、検出理由2、振る舞い(内容は削除済み)、メモリ解析による振る舞い(内容は削除済み)を一覧した図。検出理由として、当該のマルウェアがCobalt Strikeとその亜種、そのシグネチャが識別されたことがあげられている。また、Cobalt Strike Beaconとシェルコードローダーも検出している。
図10 KoboldLoaderサンプル解析レポート

パロアルトネットワークス製品をご利用中のお客様はこれらの脅威から以下の方法で保護されています。

  • Advanced WildFireはCobalt Strike Loader/Beaconを「malicious(悪意のあるもの)」として識別します。
  • Cortex XDRはエンドポイントを保護し、Cobalt Strike Loaderを「malicious(悪意のあるもの)」として識別します。

IoC

KoboldLoader

7ccf0bbd0350e7dbe91706279d1a7704fe72dcec74257d4dc35852fcc65ba292
6ffedd98d36f7c16cdab51866093960fe387fe6fd47e4e3848e721fd42e11221
fc4b842b4f6a87df3292e8634eefc935657edf78021b79f9763548c74a4d62b8
062aad51906b7b9f6e8f38feea00ee319de0a542a3902840a7d1ded459b28b8d
a221c7f70652f4cc2c76c2f475f40e9384a749acd1f0dbaefd1a0c5eb95598d2

MagnetLoader

6c328aa7e0903702358de31a388026652e82920109e7d34bb25acdc88f07a5e0

LithiumLoader

8129bd45466c2676b248c08bb0efcd9ccc8b684abf3435e290fcf4739c0a439f
82dcf67dc5d3960f94c203d4f62a37af7066be6a4851ec2b07528d5f0230a355

LithiumLoaderインストーラ

a1239c93d43d657056e60f6694a73d9ae0fb304cb6c1b47ee2b38376ec21c786
cbaf79fb116bf2e529dd35cf1d396aa44cb6fcfa6d8082356f7d384594155596

付録

KoboldLoader Beaconの設定データ:

BeaconType - SMB
Port - 4444
SleepTime - 10000
MaxGetSize - 1048576
Jitter - 0
MaxDNS - 0
PublicKey_MD5 - 633dc5c9b3e859b56af5edf71a178590
C2Server -
UserAgent -
HttpPostUri -
Malleable_C2_Instructions - Empty
PipeName - \\.\pipe\servicepipe.zo9keez4weechei8johR.0521cc13
DNS_Idle - Not Found
DNS_Sleep - Not Found
SSH_Host - Not Found
SSH_Port - Not Found
SSH_Username - Not Found
SSH_Password_Plaintext - Not Found
SSH_Password_Pubkey - Not Found
SSH_Banner - Not Found
HttpGet_Verb - Not Found
HttpPost_Verb - Not Found
HttpPostChunk - Not Found
Spawnto_x86 - %windir%\syswow64\dfrgui.exe
Spawnto_x64 - %windir%\sysnative\dfrgui.exe
CryptoScheme - 0
Proxy_Config - Not Found
Proxy_User - Not Found
Proxy_Password - Not Found
Proxy_Behavior - Not Found
Watermark_Hash - Not Found
Watermark - 666
bStageCleanup - True
bCFGCaution - True
KillDate - 0
bProcInject_StartRWX - True
bProcInject_UseRWX - False
bProcInject_MinAllocSize - 35485
ProcInject_PrependAppend_x86 - b'\x90\x90\x90\x90\x90\x90\x90'
b'\x90\x90\x90\x90\x90\x90\x90'
ProcInject_PrependAppend_x64 - b'\x90\x90\x90\x90\x90\x90\x90'
b'\x90\x90\x90\x90\x90\x90\x90'
ProcInject_Execute - ntdll.dll:RtlUserThreadStart
NtQueueApcThread
NtQueueApcThread-s
SetThreadContext
RtlCreateUserThread
kernel32.dll:LoadLibraryA
ProcInject_AllocationMethod - NtMapViewOfSection
bUsesCookies - Not Found
HostHeader - Not Found
headersToRemove - Not Found
DNS_Beaconing - Not Found
DNS_get_TypeA - Not Found
DNS_get_TypeAAAA - Not Found
DNS_get_TypeTXT - Not Found
DNS_put_metadata - Not Found
DNS_put_output - Not Found
DNS_resolver - Not Found
DNS_strategy - Not Found
DNS_strategy_rotate_seconds - Not Found
DNS_strategy_fail_x - Not Found
DNS_strategy_fail_seconds - Not Found
Retry_Max_Attempts - Not Found
Retry_Increase_Attempts - Not Found
Retry_Duration - Not Found

MagnetLoader Beaconの設定データ:

BeaconType - HTTPS
Port - 443
SleepTime - 3600000
MaxGetSize - 1402498
Jitter - 70
MaxDNS - Not Found
PublicKey_MD5 - 965fe5c869f3eea5e211fa7ee12130d3
C2Server - tileservice-weather.azureedge[.]net,/en-au/livetile/front/
UserAgent - Microsoft-WebDAV-MiniRedir/10.0.19042
HttpPostUri - /en-CA/livetile/preinstall
Malleable_C2_Instructions - Remove 1380 bytes from the end
Remove 3016 bytes from the beginning
Base64 URL-safe decode
HttpGet_Metadata - ConstHeaders
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Cache-Control: max-age=0
Connection: keep-alive
Host: tileservice-weather.azureedge[.]net
Origin: https://tile-service-weather.azureedge[.]net
Referer: https://tile-service.weather.microsoft[.]com/
Metadata
base64url
append "/45.40,72.73"
uri_append
HttpPost_Metadata - ConstHeaders
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Cache-Control: max-age=0
Connection: keep-alive
Host: tileservice-weather.azureedge[.]net
Origin: https://tile-service-weather.azureedge[.]net
Referer: https://tile-service.weather.microsoft[.]com/
ConstParams
region=CA
SessionId
base64url
parameter "appid"
Output
base64
print
PipeName - Not Found
DNS_Idle - Not Found
DNS_Sleep - Not Found
SSH_Host - Not Found
SSH_Port - Not Found
SSH_Username - Not Found
SSH_Password_Plaintext - Not Found
SSH_Password_Pubkey - Not Found
SSH_Banner -
HttpGet_Verb - GET
HttpPost_Verb - POST
HttpPostChunk - 0
Spawnto_x86 - %windir%\syswow64\conhost.exe
Spawnto_x64 - %windir%\sysnative\conhost.exe
CryptoScheme - 0
Proxy_Config - Not Found
Proxy_User - Not Found
Proxy_Password - Not Found
Proxy_Behavior - Use IE settings
Watermark_Hash - Not Found
Watermark - 1700806454
bStageCleanup - True
bCFGCaution - False
KillDate - 0
bProcInject_StartRWX - False
bProcInject_UseRWX - False
bProcInject_MinAllocSize - 17500
ProcInject_PrependAppend_x86 - b'\x90\x90'
Empty
ProcInject_PrependAppend_x64 - b'\x90\x90'
Empty
ProcInject_Execute - CreateThread
SetThreadContext
ProcInject_AllocationMethod - NtMapViewOfSection
bUsesCookies - False
HostHeader -
headersToRemove - Not Found
DNS_Beaconing - Not Found
DNS_get_TypeA - Not Found
DNS_get_TypeAAAA - Not Found
DNS_get_TypeTXT - Not Found
DNS_put_metadata - Not Found
DNS_put_output - Not Found
DNS_resolver - Not Found
DNS_strategy - round-robin
DNS_strategy_rotate_seconds - -1
DNS_strategy_fail_x - -1
DNS_strategy_fail_seconds - -1
Retry_Max_Attempts - Not Found
Retry_Increase_Attempts - Not Found
Retry_Duration - Not Found

設定データ復号にはSentinelOneのCobalt Strike Parserを使用しています。

追加リソース

EXE Explorer
Cobalt Strike Parser

2022-12-08 10:30 JST 英語版更新日 2022-12-06 09:05 PST の内容を反映