脅威リサーチ

失われた魂の探索:SoulSearcherマルウェアの進化を解明する

投稿者 Rotem Sde-Or | 2022年3月29日

FortiGuard Labs Research

影響を受けるプラットフォーム: Windows
影響を受けるユーザー:     Windowsユーザー
影響:             機密情報の収集、悪意あるモジュールのさらなる実行
深刻度:            クリティカル

Symantec社が2021年10月に発行した脅威レポートは非常に興味深いものでした。このレポートでは、新しいカスタムマルウェアを使って東南アジアでスパイ活動を行っている、未知の脅威アクターが報告されています。最も好奇心をそそられたのは、レジストリから読み込まれたDLLペイロードに言及した部分です。これは、今まで発見されていなかったペイロードです。

このペイロードのローダーを分析した結果、このモジュールが検知されにくい理由が明らかになってきました。このモジュールは、カスタムヘッダーを使った圧縮BLOBとしてレジストリに保存されます。ディスクには書き込まれないため、VirusTotalなどのデータセットに表示される可能性はほとんどありません。

そこで我々は、この失われたモジュールの探索を開始しました。現時点で、モジュールのサンプルと大量のコンポーネントおよび亜種が、2017年までさかのぼって解明されています。サンプルをリバースエンジニアリングすることで、このマルウェアの数年間にわたる進化を観察できました。カスタムコードが徐々に追加されていき、コンポーネントがアップグレードされて機能が向上するとともに、コードが巧妙化し、モジュール性が高まりました。

本ブログでは、このマルウェアのさまざまなコンポーネントと時系列の変化を検証し、それに基づいてSoulマルウェアフレームワークの進化を読み解いていきます。

進化論

きわめて初期の段階では、攻撃者はオープンソースツールのGh0st RATとNetBot Attackerのコード(かなり改造されてはいますが)を組み込んだバックドアを使用していました。このバックドアは、圧縮BLOBとしてドロッパー実行ファイルに埋め込まれ、ドロッパーがそれをディスクに書き込んで実行します。

このバックドアのコードは、1年の間にリファクタリングされてカスタムコードが追加され、我々がSoulモジュールと呼んでいる形へと変化を遂げました。我々がSoulSearcherと名付けたローダーも、同じく変化しています。ディスクにペイロードが書き込まれる代わりに、圧縮モジュールはレジストリに保存され、メモリに読み込まれます。

2020年初頭以降には、複雑化したSoulSearcherの亜種が見つかりました。そのうちのいくつかは、複数のモジュールをレジストリから読み込むことができます。これらの亜種は時間を経て大きく変化しており、そのコンフィギュレーションアーティファクトはSoulモジュールの機能を解明するヒントになります。

バックドアのほかにも、キーロガーやカスタムコンパイルされた7zrツール(軽量版のスタンドアロン7-zip)などが使用されていました。

次の図は各種コンポーネントの全体的なタイムラインです。2017年の最初のキーロガーとバックドアから、2021年11月に発見された最新のSoulSearcher亜種までを示しています。

図1:Soulマルウェアフレームワークのタイムライン

注記:このタイムラインは、コンパイルのタイムスタンプを基準にしています。このマルウェアフレームワークの場合、改ざんされている可能性はありますが、ここではこれらのタイムスタンプを真正であると見なします。収集したサンプルの時間分布と、我々が認識しているコンポーネントの機能および実際の被害の目撃例の間に、相関関係が認められることがその理由の一つです。さらには、関連するサンプル(ローダー、ペイロードなど)が数秒間で次々とコンパイルされていたからです。

発見されたすべてのコンポーネントには、以下のような共通の特徴があります。

  • 悪名高いHacking Team社から漏洩したソースコードのDynamiCallインポート難読化
  • RCSバックドア
  • スタック文字列
  • 類似するデータ構造(コンフィギュレーションの構造体など)
  • 暗号化と圧縮のアルゴリズム
  • ミューテックス、イベント、およびファイルマッピングの名前
  • 近接するコンパイルのタイムスタンプ

オリジナルSoulバックドア

これは最も初期の段階に脅威アクターが使用したバックドアです。このバックドアは2017年10月にコンパイルされ、以下のようなパブリックリポジトリのコードや、ネット上に流出したその他のマルウェアのコードを改変したものが使用されていました。

  • DynamiCall
  • Gh0st RAT
    • ファイル操作関数
    • CMDシェルコード
    • 通信メッセージおよび構造体
  • HTran(オープンソースの接続バウンサーツール)
  • 7zip

バックドアは、単純なドロッパーによってディスクに書き込まれるDLLです。ドロッパーは、共有しているバックドアおよびコンフィギュレーションのLZMA圧縮データを解凍します。次に、コンフィギュレーションで指定されたパスにバックドアを書き込み、そのコンフィギュレーションをオーバーレイとしてバックドアに追加します。ドロッパーに渡されるコマンドライン引数に応じて、LoadLibraryまたはrundll32.exeでバックドアが実行されます。最後に、ドロッパーはディスクから自分自身を削除します。

コンフィギュレーション

バックドアはファイルオーバーレイからコンフィギュレーションを読み取り、0x13を使った各バイトの減算およびXOR演算によってそれを復号します。

コンフィギュレーションは特定のバイトシーケンスで始まっています。その重要度は不明ですが、我々が発見したすべてのサンプルで同じです。その他のフィールドは、バックドアのファイル名またはフルパス、C2アドレス、およびリトルエンディアン形式のポートなどです。このコンフィギュレーションには、未使用のサービス名と説明も含まれています。あるサンプルでは、文字列「NetBot」がファイル名としてコンフィギュレーションされています。

図2:バックドアのコンフィギュレーション

別の2つのフィールド、すなわちDWORD配列とフラグ(オフセット0x1f0で強調表示)は、バックドアがコマンド関連の通信を抑制するかどうかと、その時期を指定します。

DWORD配列の値は、コマンドを受け入れる日時を指定します。このサンプルでは、値はすべて2です。各インデックスは、特定の曜日と時間を示しています。あるインデックスの値が0の場合、対応する曜日と時間に、コマンドの要求は保留されます。

フラグは、以下の条件に基づいて、マシン上でアクティビティが実行されている間に受信コマンドを抑制するかどうかを決定します。

  • 現行セッション以外に、システム内でアクティブなコンソールセッションがある。
  • 現行セッション以外に、システムでアクティブな、または接続されているRDPセッションがある。

セッションは、WTSRegisterSessionNotificationWTSEnumerateSessions APIsを使用して監視されます。

コンフィギュレーションに応じて、バックドアはクライアントとしてアクティブモードで、あるいはサーバーとしてパッシブモードでコマンドを受信できます。各モードに1つずつ、合計2つのポート番号があります。

  • サーバーポートが0でない場合、バックドアはサーバーに接続してコマンドを受信します。
  • リスニングポートが0でない場合、バックドアはそのポートでリッスンし、着信接続からのコマンドを待ちます(一度に有効にできる接続は1つだけです)。

通信

C2サーバーへのメッセージ(コマンドの要求など)には、固定の構造体が使用されます。サーバーへの各要求は、ハードコードされたHTTPヘッダーで構成されます。このヘッダーは、taboola[.]comへの正当なネットワークトラフィックを偽装しています。

図3:サーバーへの要求で送信される固定HTTPヘッダー

サーバーに送信されるHTTP本文の構造体は次のとおりです。CompressedBufferはzlib圧縮データです。

1
2
3
4
5
6
7
struct BackdoorRequest {
	DWORD MessageType;
	DWORD DecompressedBufferSize;
	DWORD DecompressedBufferSize;
	DWORD CompressedBufferSize;
	BYTE  CompressedBuffer[CompressedBufferSize];
};

図4:バックドアが送信するメッセージ本文のフォーマット

バックドアがMessageType 0x11000000を使用して、マシンに関する情報をサーバーに送信すると、コマンドの受信が開始されます。

  • ホスト名
  • IPアドレス(複数可)
  • CPUアーキテクチャ
  • RAMサイズ

サーバー応答の構造体は、要求の構造体と似ています。

1
2
3
4
5
6
7
struct ServerResponse {
	DWORD CommandType;
	DWORD DecompressedBufferSize;
	DWORD DecompressedBufferSize;
	DWORD CompressedBufferSize;
	BYTE  CompressedBuffer[CompressedBufferSize];
};

図5:バックドア要求のサーバー応答メッセージ本文のフォーマット

バックドアは、別のスレッドでMessageType 0x1100000Bを使用して、コマンド受診抑制が現在有効かどうかをサーバーに通知する場合があります。

コマンド

サーバーが送信するコマンドは、下表に示すいずれかのCommandTypeの値です。CompressedBufferフィールドは空です。バックドアは、所定のコマンドに従って指定されたMessageTypeの値を使用して、コマンドのパラメータの追加要求を送信します。

タイプ

名前

0xFFFFFFFF

実行するコマンドはありません。

0x20000000

ソケットを閉じ、コマンドの受信を中止します。

0x21000000

ファイルの移動、コピー、削除、ダウンロード、アップロードなどのファイル操作関数。

0x23000000

インタラクティブCMDシェルを開きます。攻撃者は、「Exit」コマンドを送信してシェルを終了するまで、CMDコマンドを実行できます。

0x38000000

HTranのtransmitdata関数。

図6:バックドアによって実装されるコマンド

バックドアがパッシブモードで動作する場合も同様です。ただし、対象はファイル操作、CMD、close socketコマンドの処理に限定されます。

Soulを探し求めるローダー

SoulSearcherは第2段階のローダータイプであり、2018年11月以降にその存在が観測されています。我々が発見したすべてのサンプルは、同様の動作フローを使ったDLLです。これらのサンプルはSoulモジュールのペイロードを実行し、そのコンフィギュレーションをパースします。

SoulSearcher亜種の間の主な違いは、ペイロードに渡されるコンフィギュレーションのタイプと、コンフィギュレーションとペイロードの保存場所です。

コンフィギュレーションフォーマット

最も古いサンプルの日付

コンフィギュレーションの保存場所

ペイロードの保存場所

バイナリ

2018年11月

  • オーバーレイ+レジストリ
  • ファイル
  • オーバーレイ
  • ファイル

XML

2020年4月

  • レジストリ
  • ファイルマッピング
  • ファイル

レジストリ

セミコロン区切り

2021年8月

SoulSearcherに埋め込み

レジストリ

図7:SoulSearcherのタイプ

バイナリSoulSearcher

私たちの手元には、最も古いSoulSearcherのサンプルがあります。サンプルの中にはペイロード、すなわちSoulモジュールが埋め込まれているものもあります。どのサンプルも2つの関数、DumpAnalyzeDumpAnalyzeExをエクスポートします。

SoulSearcherはまず、オーバーレイデータまたはディスク上のファイルに含まれているモジュールとコンフィギュレーションを探します。それらが見つかったら、モジュールをレジストリに保存します。続いてSoulSearcherは、レジストリからペイロードを取得して反射的に読み込み、コンフィギュレーションを引数としてペイロードに渡します。

コンフィギュレーションはオーバーレイの最後に配置されており、SUB-XOR 0x13を使用して復号されます。コンフィギュレーションのフォーマットはオリジナルSoulバックドアと同じですが、オーバーレイ内の圧縮Soulモジュールのサイズを決定するフィールドが追加されています。HKCU\Software\OIfkO2i1レジストリの値から、コンフィギュレーションの別の部分が取得され、SUB-XOR 0x79を使用して復号されます。それが存在しない場合は、他のユーザーのレジストリハイブでもこのパスがクエリされます。

SoulSearcherのエクスポートに引数「-h <HANDLE>」が渡されていた場合は、オーバーレイではなくsdc-integrity.datからコンフィギュレーションとペイロードが取得されます。取得する方法は前述のとおりです。入力された引数はDLLのハンドルであり、.datファイルが格納されたディレクトリパスの取得に使用されます。

いずれの場合も、モジュールはHKCU\Software\kuhO6Ba0kTのレジストリに保存されます。

XML SoulSearcher

すべてのXML SoulSearcherは、まず、未知のコンポーネントによって事前に書き込まれたコンフィギュレーションを取得します。大半のサンプルは、レジストリからコンフィギュレーションを取得します。一部のサンプルは、ファイルマッピングオブジェクト、またはディスク上のファイルから取得先を選択します。

たとえばあるサンプルは、それがサービスとして動作しているかどうかに応じて、次のいずれかからコンフィギュレーションを取得します。

  • HKLM\SYSTEM\CurrentControlSet\Services\<ServiceName>\Parametersのサービスパラメータの下にあるGUID形式の値の名前
  • Global\CacheDataMappingという名前のファイルマッピングオブジェクト

取得されたバイナリデータの構造体は次のとおりです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
struct StoredConfiguration {
	DWORD Magic;
	DWORD Unused;
	BYTE  LzmaProperties[5];
	DWORD ConfigSize;
	DWORD CompressedConfigSize;
	BYTE  ConfigMD5[0x21];
	BYTE  CompressedConfigMD5[0x21];
	BYTE  CompressedConfig[CompressedConfigSize];
};

図8:レジストリから取得されたコンフィギュレーションの構造体


この構造体は以下のように処理され、XMLコンフィギュレーションが取得されます。

  1. CompressedConfigのサイズがCompressedConfigSizeと等しいことを確認する。
  2. CompressedConfigSizeConfigSizeが0でないことを確認する。
  3. MD5の両方のチェックサムが0でないことを確認する。
  4. Magicがバイトシーケンス86 AE 00 00を保持していることを確認する。
  5. 圧縮されたコンフィギュレーションのMD5チェックサムを検証する。
  6. コンフィギュレーションのLZMA圧縮データを解凍する。
  7. 解凍したコンフィギュレーションのMD5チェックサムを検証する。

ある亜種では、AES-256 CBCを使用してレジストリデータを復号するために、さらにもう一つの手順が実行されます。鍵はハードコードされた2つのパスのいずれかから取得されます。

取得した文字列を逆シリアル化するために、古いサンプルはAPIのCreateXmlReaderを使用し、新しいサンプルはオープンソースライブラリのTinyXMLを使用します。XML属性名は、レジストリから読み込まれたSoulモジュールの解明に役立ちます。

セミコロンSoulSearcher

2021年8月に出現したSoulSearcherの亜種から、レジストリのXMLコンフィギュレーションではなく、ハードコードされたセミコロンで区切られたコンフィギュレーションが使用され始めました。このタイプの最初の亜種は、Symantec社のレポートが発表されるわずか1ヵ月前にコンパイルされました。

図9:セミコロンで区切られたコンフィギュレーションの例

このコンフィギュレーションには、XMLコンフィギュレーションに見られるようなわかりやすいXML属性名がないため、ツールの解明はより難しくなります。しかしながら、これらのフィールドについては以下のようなことが考えられます。

  • 最初のフィールドdo5Kc1diLHgq5f6は、コンフィギュレーションのタイプを表しています。XMLコンフィギュレーションでは、文字列X6bmLMbAL29AlxBでタイプが表されます。
  • いずれかの値は、SoulSearcherがサービスとしてインストールされているかどうかを示しています。インストールされている場合、コンフィギュレーションにはサービスの詳細、たとえば名前などを示すフィールドが含まれます。
  • いくつかの値によって、読み込むべきSoulモジュールが指定されています。
  • いずれかのフィールドに、Soulモジュールを読み込むレジストリパスが含まれている可能性があります(他のモジュールはハードコードされたパスから読み込まれます)。

Soulを見つけた場合

古いタイプのSoulSearcher亜種は、単一のSoulモジュールを読み込みます。一方、最新のXMLおよびセミコロンSoulSearcherは、最大4つのモジュール(コンフィギュレーションにより異なります)を読み込むことができます。

1
2
3
4
5
6
7
struct StoredModule {
	DWORD Unused;
	QWORD ModuleSize;
	QWORD CompressedModuleSize;
	BYTE  ModuleMD5[0x21];
	BYTE  CompressedModule[CompressedModuleSize];
};

図10:レジストリから取得したペイロードの構造体

すべてのモジュールは、コンフィギュレーションと同様の方法でレジストリから取得されます。

  1. CompressedModuleのサイズがCompressedModuleSizeと等しいことを確認する。
  2. モジュールのLZMA圧縮データを解凍する。
  3. 解凍したモジュールのMD5チェックサムを検証する。
  4. モジュールのアーキテクチャとSoulSearcherのアーキテクチャが一致することを確認する。

この手順は、バイナリSoulSearcherを除くすべてのSoulSearcherサンプルで同じです。バイナリSoulSearcherは構造体が若干異なります。

SoulSearcherは、メモリ内のモジュールを反射的に読み込み、Constructエクスポートを呼び出します。初期の亜種は、モジュールのそれ以外のエクスポートも呼び出します。

生まれ変わったSoulバックドア

我々は、2018年11月以降のバイナリSoulSearcherサンプルの一つに、ペイロードが埋め込まれていることを発見しました。

このSoulモジュールは、機能面ではオリジナルバックドアと非常によく似ていますが、コードが一段と巧妙化しています。詳細な検証の結果、オリジナルバックドアのコードがさまざまなエクスポートに改変されていることが判明しました。たとえば、HTTPメッセージを送受信するコードは、SendMsgエクスポートとRecvMsgエクスポートに分割されていました。

図11:Soulバックドアモジュールのエクスポート関数

コンフィギュレーション

SoulSearcherは、このコンフィギュレーションを引数として使用し、モジュールのBeginConnectエクスポートを呼び出します。このコンフィギュレーションは、オリジナルバックドアのコンフィギュレーションと同じくバイナリフォーマットですが、サービス関連のフィールドがありません。

図12:オリジナルバックドア(左)と新しいバックドアモジュール(右)のコンフィギュレーション

通信

オリジナルバックドアと異なり、このSoulモジュールはクライアントとしてのみコマンドを受け取ります。

gethostbyname APIでサーバーアドレスを解決できなかった場合、バックドアはDnsQuery APIの文書化されていない機能を使用して、ハードコードされた2つのDNSサーバーにクエリを試行します。

  • 193.0.14.129(DNSルートサーバー)
  • 8.8.8.8(Google Public DNS)

要求の固定ヘッダーは、s-microsoft[.]comへのトラフィックを偽装するよう改変されており、GetSubInfoエクスポートがマシンの情報を収集します。

図13:サーバーへの要求で送信される新しい固定HTTPヘッダー

コマンド

メッセージの構造体はオリジナルバックドアと同じです。下表に示すとおり、オリジナルバックドアにはなかった新しいコマンドコードがいくつかあります。バックドアは、名前の付いた5つのコマンドのいずれかを受け取ると、サーバーからDLLをダウンロードして実行します。コマンド名はバイナリで表示され、引数の一部としてコマンドDLLに渡されます。DLLそのものについては不明であるため、我々はその名前と、オリジナルバックドアのコードでの同じコマンドタイプの実装に基づいて、DLLの機能を推測するしかありません。

タイプ

名前

0xFFFFFFFF

実行するコマンドはありません。

0x20000000

ソケットを閉じ、コマンドの受信を中止します。

0x21000000

File

0x23000000

Cmd

0x38000000

Htran

0x39000000

レジストリ内のコンフィギュレーションを更新します。サーバー応答バッファはADD-XOR 0x79で、レジストリ(ハードコードされたパス)に書き込まれる前に暗号化されています。

0x3A000001

コマンド構造体を空にし、コマンド関連のミューテックスを解放します。

0x3B000000

MemoryLoader

0x3C000000

UsbNtf

図14:バックドアモジュールによって実装されるコマンド

サーバーからコマンドDLLをダウンロードするために、追加のソケット接続が確立されます。まず、バックドアは定数値0x4096C083を格納したバッファを使用して、メッセージタイプ0x1100000Cを送信します。すべての要求と同様に、このメッセージは上記のBackdoorRequest構造体に示したSendMsgによって送信されます。次に、同じタイプのメッセージをもう一つ送信します。ただし、今回はバッファが以下のような構造になっています。Architectureフィールドには、バックドアのアーキテクチャに応じて32または64の値が格納されます。

1
2
3
4
struct CommandRequest {
	DWORD CommandType;
	BYTE  Architecture[6];
};

図15:サーバーへのコマンドDLL要求の構造体

サーバーは以下の構造体を使用してバックドアに応答します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
struct CommandResponse {
	DWORD Unused0;
	BYTE  Unused1[6];
	QWORD ModuleSize;
	QWORD CompressedModuleSize;
	BYTE  ModuleMD5[0x21];
	BYTE  CompressedModuleMD5[0x21];
	QWORD Unused2;
	BYTE  CompressedModule[CompressedModuleSize];
};

図16:コマンドDLLに対するサーバー応答の構造体

バックドアはこの構造体を使用して、以下の方法でコマンドDLLを読み込みます。

  1. 圧縮されたモジュールのMD5チェックサムを検証する。
  2. 圧縮されたモジュールのLZMA圧縮データを解凍する。
  3. 解凍したモジュールのMD5チェックサムを検証する。
  4. 手順2または3が失敗した場合は、サーバーに要求を再発行する。
  5. メモリ内のモジュールを反射的に読み込む。
  6. 以下のような引数を使用して、モジュールのConstructエクスポートを呼び出す。
    1. 定数値0x4096C083(先にサーバーに送信した値と同じ)
    2. コマンドの名前(「File」、「UsbNtf」など)
    3. バックドアのコンフィギュレーション
    4. サーバーから受信したCommandResponse構造体

いくつかのSoul

前述したように、各XML SoulSearcherはXML形式のコンフィギュレーションをパースします。このコンフィギュレーションには、わかりやすい名前が付けられた属性が含まれています。それらのアーティファクトを基に、我々は入手したさまざまなサンプルのペイロードと推測されるものを分類することができました。

バックドア

以下のSoulSearcherサンプルは、それぞれのペイロードと密接に連動するため、単なるローダーというよりも高度なオーケストレーターとして機能します。サンプルはコンフィギュレーションをパースするほか、Soulモジュールの複数のエクスポート関数を呼び出して、詳細なバックドアロジックを作成します。コンフィギュレーションフィールドとインポート関数名は、リモートシェルの機能やDropboxの利用状況を示しています。

コンフィギュレーションフィールド

エクスポート名

  • Ip
  • Dns
  • CntPort
  • LstPort
  • Blog
  • DropboxBlog
  • SvcName
  • SvcDisp
  • SvcDesc
  • SvcDll
  • OlPass
  • OlTime
  • SelfDestroy
  • Construct
  • ConnectHost1
  • ForceCloseSocket
  • CopyReserveMem
  • Recv
  • RecvEx
  • Send
  • SendEx
  • BindShell
  • Accept
  • TransmitData_htran
  • KillChildenProcessTree
  • ExtractIPToConnect
  • ExtractIPToConnect1
  • GetDeviceInfoString1
  • GetPseudoSocketInfo
  • Decrypt_ByteToByte

図17:古いSoulSearcherバージョンのコンフィギュレーションフィールドとインポート関数名

高度なRAT

あるSoulSearcherは、以下のようにバックドアとは異なる多数のコンフィギュレーションフィールドをパースします。

  • AesPass
  • ClipBoardMntEnable
  • DestroyDate
  • DestroyDay
  • DestroyMode
  • DestroyWiFiName
  • DestroyWiFiSearchMinu
  • DirDiskInternal
  • DropboxAppToken1
  • DropboxAppToken2
  • DropboxAppToken3
  • EnableDropbox
  • EnableFileMnt
  • EnableHijack1
  • EnableKeyLog
  • EnableService
  • ExcludeDir
  • FileExt
  • FileSizeMb
  • Hijack1DllPath
  • Hijack1RegSubKey_MemMod1
  • Hijack1RegValueName_Cfg
  • Hijack1RegValueName_MemMod1
  • IncludeDir
  • RecDataPath
  • RegKey_Exist
  • RegKey_Rec
  • RegSubKey_Exist
  • RegSubKey_Rec
  • RegValueDataSz
  • RegValueName_Exist
  • RegValueName_Rec
  • SaveInFile
  • SaveInReg
  • ScreenMngEnable
  • ServiceDescription
  • ServiceDisplayName
  • ServiceDllPath
  • ServiceHide
  • ServiceImagePath
  • ServiceName
  • ServiceRegValueName_Cfg
  • ServiceRegValueName_MemMod1
  • ServiceRegValueName_MemMod2
  • ServiceRegValueName_MemMod3
  • ServiceSessionIsolationBypass
  • TriggerTime
  • UsbExt
  • UsbExtMode
  • z7zPass
  • z7zSizeMb
  • z7zStoreDir

 

図18:あるSoulSearcherサンプルで見つかったコンフィギュレーションフィールド

EnableDropbox属性がtrueに設定されると、SoulSearcherはServiceRegValueName_MemMod3で指定されたパスからモジュールを読み込みます。EnableKeylogが設定されている場合は、ServiceRegValueName_MemMod1で指定されたパスからモジュールが読み込まれます。

プロキシ

次のサンプルのコンフィギュレーションは、HTTPおよびHTTPSでのプロキシ機能と、CMDコマンドを実行する機能を示しています。

  • CmdPrefix
  • CmdSuffix
  • EnableHttps1
  • Port
  • Port2
  • ProxyIP1
  • ProxyIP2
  • ProxyPort1
  • ProxyPort2
  • ProxyUserName1
  • ProxyUserName2
  • ProxyUserPass1
  • EnableHttps2
  • Interval
  • MachineGUID
  • ProxyUserPass2
  • RegPath
  • RegRootKey
  • RegValueName_Cfg
  • RegValueName_Svr32
  • RegValueName_Svr64
  • URL2
  • Url

図19:プロキシ機能に関連するコンフィギュレーションフィールド

その他のコンポーネント

第1段階のローダー

前述したように、SoulSearcherは第2段階のコンポーネントです。我々は、バイナリSoulSearcher亜種の第1段階のローダーも特定しました。

このローダーは、SntpServiceという単一のエクスポート関数を保持するDLLであり、すでにディスク上にあると予想されるSntpService.dllというユーティリティDLLに依存します。これらの名前は、Sophos社の同じ名前の正規のセキュリティソフトウェア製品に見せかけるために使用されていると思われます(こちらを参照)。

ローダーは、新しいスレッドでSntpServiceを実行する前に、プロセス名がMSDTC.exeであるかsvchost.exeであるかを確認します。後者である場合は、DBWinMutex_1という名前のミューテックスが作成されます(これはSoulモジュールでも使用されます)。

ローダーは2つの処理を実行します。まず、ディレクトリにある2つの.datファイルを復号し、その出力をレジストリに保存します。

  • HKCR\.rat\PersistentHandler\TypeFacesdc-integrity.datが書き込まれます。
  • HKCR\.rat\PersistentHandler\MagicNumberscs-integrity.datが書き込まれます。

復号スキームはAES-256 CBCで、ハードコードされた値のSHA256ハッシュが鍵として使用されます。このあと、2つのファイルはディスクから削除されます。つまり、この手順は最初の感染時、または更新版が展開されたときのみ実行されます。

次に、TypeFace値のデータを使用してSoulSearcherを読み込みます。この構造体には、バッファとそのサイズが格納されています。バッファの最後の0x3d0バイトはローダーのコンフィギュレーションであるため、ローダーはこれをスキップし、それ以外のバッファをSntpService.dllDecrypt_ByteToByte関数に渡します。出力はPEです。ローダーはこれを反射的に読み込み、そのDumpAnalyzeエクスポートを呼び出します。ローダーは、文字列形式のポインタ(「-h <HANDLE>」)を指定して、自分自身のハンドルを引数としてSoulSearcherに渡します。

 SntpService.dllのもう一つのエクスポートも解決されます。

図20:SntpService.dllからインポートされた関数

我々は、VirusTotalにアップロードされたユーティリティDLLの亜種に、Kaspersky AntivirusのAvpCon.dllの名前が付けられていることを発見しました。Sophosの場合と同じく、これも正規の製品を装うためと思われます。エクスポート名が「Encrypt」や「Decrypt」であるにもかかわらず、実際にはすべての関数がLZMA圧縮または解凍を実行します。これには、暗号化ではなく圧縮されていることが判明したバイナリSoulSearcherサンプルが関係しています。

図21:AvpCon.dllのエクスポート

キーロガー

キーロガーは2017年中頃~2020年末にコンパイルされました。すべてのキーロガーは非常によく似たコードを共有しており、この期間中にほとんど変更は加えられていません。Symantec社が報告したキーロガーとは別に、我々は2020年9月にサンプルをもう一つ発見しました。このサンプルは、キーロギングの関数は他のサンプルと同じですが、それ以外のコードが大きく違っています。

キーロガーは、.dllの拡張子がない同名のファイルからコンフィギュレーションを読み取ります。ただし、我々が見つけたサンプルはレジストリに格納されたコンフィギュレーションを使用します。このファイルはキルスイッチの役割を果たすため、これが存在するとキーロガーは終了します。このサンプルには、これまでのサンプルにはないスタック文字列とDynamiCall難読化も含まれています。

このキーロガーは、Explorer.exe内で動作していることを確認し、自分自身の最後の0x208バイトを読み取ってコンフィギュレーションを取得し、それを復号します。定数値を使って各バイトの加算およびXOR演算を行うことで、データが復号されます。次に、HKCU\Software\F32xhfHXにあるレジストリに、暗号化されたコンフィギュレーションがセットされます。後日実行する際には、このキーからコンフィギュレーションが取得されます。このコンフィギュレーションには以下の2つのパスが格納されています。

  • キーロガーモジュールファイル:C:\Windows\SndVolSSO.DLL
  • キーロガー出力ファイル:C:\users\minh\AppData\Local\OneDrive\Cache.dat

興味深いことに、出力ファイルのパスにユーザー名が含まれています。これは、このサンプルが特定のマシンを標的にしていた可能性があることを示唆しています。

キーロガーは、クリップボードのデータとGetRawInputDataを利用してキーストロークを監視し、出力ファイルに平文で記録します。この出力ファイルには、感染したマシンのsvchost.exeと一致するようにタイムスタンプが付けられます。GetRawInputDataから返されたエラーは、C:\ProgramData\Users.infに記録されます。キーロガーは、一部のアジア言語をサポートするIME仮想キーコードも記録します。

図22:キーロガー出力ファイル「Cache.dat」の例

コマンドライン実行サービス

これは、レジストリキーHKCR\.c\Type\Type00からCMDコマンドを実行する、軽量のサービスDLLです。午後8時にシステムでpowershell.exeというプロセスがアクティブではない場合にコマンドを実行します。これはDynamiCall難読化を使用してコンパイルされています。

7zr.exe

カスタムコンパイルされたこの7zr実行ファイルは、DynamiCall難読化を組み込むように改変されています。

結論

Soulマルウェアフレームワークは2017年から活発に利用されており、脅威アクターは今日に至るまで、自分たちのツールと能力を着実に進化させています。特に注意すべき点は、初期のツールはオープンソースコードに依存していたにもかかわらず、その時にはすでにカスタムのキーロガーが使用されていたということ、そしてそれ以来、カスタムコードは大きな進化を遂げているということです。モジュール式で多段階かつ反射的に実行されるペイロードは、高い技術を誇り敵対的であり、攻撃者グループに潤沢なリソースがあることを示唆しています。現在のところ攻撃者の身元は不明ですが、我々はおそらく国家の後ろ盾があると見ています。

本レポートで公表している情報は、大量のサンプルの詳細な分析に基づいています。しかしながら、我々はこれが氷山の一角であり、グループはさらに多くのペイロードや機能を保有し、それらが今後出現するのではと危惧しています。

フォーティネットのソリューション

FortiEDRは、使用開始直後から以下のような脅威を検知しブロックします。予備知識や特別なコンフィギュレーションは必要ありません。そのために、実行後対策エンジンを使用して不正なアクティビティを特定します。

図23:FortiEDRによるSoulバックドアとC2サーバー間の通信遮断

FortiGuard Webフィルタリングのブロックリストには、すべてのネットワークIOC(Indicator of Compromise:侵害指標)が掲載されています。

フォーティネットのFortiGate、FortiMail、FortiClient、およびFortiEDRソリューションには、FortiGuardアンチウイルスサービスエンジンが組み込まれています。FortiGuardアンチウイルスは以下のマルウェアに対応できます。

W64/SoulSearcher.B7D1!tr
W32/SoulSearcher.B7D1!tr
W64/SoulSearcherKeyLogger.B7D1!tr.spy
W32/SoulSearcher.B7D1!tr 
Data/SoulSearcher.B7D1!tr

さらに、Cyber Threat Allianceのメンバーシップの一環として、これらの脅威情報はリアルタイムで他のメンバーと共有され、お客様向けのより強力な保護対策の実施に役立てられています。

付録A:MITRE ATT&CK攻撃手法

ID

説明

T1569.002

システムサービス:サービスの実行

T1055

プロセスインジェクション

T1112

レジストリの変更

T1567

Webサービスを介したデータ流出

T1041

C2チャネルを介したデータ流出

T1132

データのエンコーディング

T1082

システム情報の検知

T1083

ファイルとディレクトリの検知

T1140

難読化解除 / ファイルまたは情報の解読

T1071.001

アプリケーション層プロトコル:Webプロトコル

T1056.001

入力キャプチャ:キーロギング

T1059.003

コマンドおよびスクリプトインタープリタ:Windowsコマンドシェル

T1115

クリップボードのデータ

T1592

被害者のホスト情報の収集

T1090.001

プロキシ:内部プロキシ

T1070.006

ホストでのインジケータの削除:タイムスタンプ

付録B:IOC(Indicator of Compromise:侵害指標)

IOC

タイプ

詳細

1af5252cadbe8cef16b4d73d4c4886ee9cecddd3625e28a59b59773f5a2a9f7f

SHA-256

SoulSearcher

a6f75af45c331a3fac8d2ce010969f4954e8480cbe9f9ea19ce3c51c44d17e98

SHA-256

SoulSearcher

c4efb58723fd75d51eb92302fbd7541e4462f438282582b5efa3c6c7685e69fd

SHA-256

SoulSearcher

edb14233eccb5b6e2d731831e7b18b8b17ea6a3f8925fb5899ce2ef985a66b68

SHA-256

SoulSearcher

fdf0db7f6b60d7563268c15c634adb47e8eec34adfcbf9b10e973916c7517157

SHA-256

SoulSearcher

c7481d6975646b605aba3fb11686e34ee205f7e280069e9d5bf0c1c2eca79be8

SHA-256

SoulSearcher

0f7af0cad4aade0e7058051a449059b35358ddda075d88b2d289625adc02deef

SHA-256

SoulSearcher

3cb4887bec169c75f58bc4ed1c6fd3703cc46512596e62186cf8329448dbb47b

SHA-256

SoulSearcher

cb954f06c94493c87f25651271657aeb1e3e24f26b6552d3e616bbc2dc660679

SHA-256

SoulSearcher

78feb564c4f6c240ddb17dd0f49ae96df04ee594ed24df81f583136fccf60c1d

SHA-256

SoulSearcher

bc91a4fb16f14fb1c436c2bdc7c80b87a02caa5de17897614d07bc7bda200590

SHA-256

SoulSearcher

7edd7d406159ab0eecb22ddbd6060de7c24a4eb0b61fa527935310b94d3b9db4

SHA-256

SoulSearcher

b02b8b6c3d517c6b8652b898963068ba12cd360b5cdcf0aad5fe6ff64f0e9920

SHA-256

SoulSearcher

ec164902cbe8daaa88ae923719c5dac900715f3e32d4cea6e71ca04c7cecf3e2

SHA-256

SoulSearcher

bac4b50727c69ca7cc3c0a926bb1b75418a8a0eabd369a4f7118bb9bba880e06

SHA-256

SoulSearcher用の第1段階のローダー

69a9ab243011f95b0a1611f7d3c333eb32aee45e74613a6cddf7bcb19f51c8ab

SHA-256

オリジナルSoulバックドア

579fa00bc212a3784d523f8ddd0cfc118f51ca926d8f7ea2eb6e27157ec61260

SHA-256

オリジナルSoulバックドア

8ff18b6fb5fe4f221cd1df145a938c57bdd399dc24e1847b0dc84a7b8231458f

SHA-256

オリジナルSoulバックドア

f97161aaa383e51b2b259bb618862a3a5163e1b8257832a289c72a677adec421

SHA-256

オリジナルSoulバックドアドロッパー

d3647a6670cae4ff413caf9134c7b22b211cb73a172fc1aa6a25b88ff3657597

SHA-256

オリジナルSoulバックドア

f5cd13b2402190ec73c526116abea5ebab7bd94bcdb68cc2af4f3b75a69ba9c5

SHA-256

キーロガー

a15eda7c75cf4aa14182c3d44dc492957e9a9569e2d318881e5705da2b882324

SHA-256

キーロガー

967e8063bd9925c2c8dd80d86a6b01deb5af54e44825547a60c48528fb5f896d

SHA-256

キーロガー

64f036f98aad41185163cb328636788a8c6b4e1082ae336dad42b79617e4813d

SHA-256

キーロガー

7b838fcad7a773bfd8bc26a70f986983553d78b4983d0f2002174f5e56f7f521

SHA-256

Soulバックドア

40fda8137d8464d61240314b6de00ae5c14ed52019e03e4dcadfc00b32c89d23

SHA-256

コマンドライン実行サービス

5dee99beb0b6ba1ebdb64515be1d9307262d9b57b0900310d57290dca40bb427

SHA-256

7zr.exe

6b70ad053497f15b0d4b51b5edabeced3077dddb71b28346df7c7ea18c11fcdf

SHA-256

7zr.exe

852c98a6fbd489133411848775c19a2525274eac9a89a09a09d511915c7cbafc

SHA-256

AvpCon.dll

gmy.cimadlicks[.]net

ネットワーク

-

app.tomelife[.]com

ネットワーク

-

community.weblives[.]net

ネットワーク

-

23.91.108[.]12

ネットワーク

-

Global\vQVomit4

ミューテックス

-

Global\mFNXzY0g

ミューテックス

-

Global\DefaultModuleMutex

ミューテックス

-

Global\DBWinMutex_1

ミューテックス

-

Global\DBWinMutex_2

ミューテックス

-

Global\VirusScanWinMsg

イベント

-

Global\3GS7JR4S

イベント

-

Global\SecurityEx

イベント

-

Global\CacheDataMappingFile

ファイルマッピング

-

C:\Windows\System32\wlbsctrl.dll

ファイル名

-

C:\Windows\System32\ikeext2.dll

ファイル名

-

C:\Windows\System32\d6w48ttth.dll

ファイル名

-

C:\Windows\System32\shsvc.dll

ファイル名

-

C:\Windows\System32\netcsvc.dll

ファイル名

-

C:\Windows\System32\fc2qhm7r9.dll

ファイル名

-

C:\Windows\SndVolSSO.DLL

ファイル名

-

SvrLdr_xpsservices.dll

ファイル名

-

timedateapi.dll

ファイル名

-

msfte.dll

ファイル名

-

wsecapi.dll

ファイル名

-

C:\Programdata\Microsoft\svchost.exe

ファイル名

-

NvStreamer.dll

ファイル名

-

Helpsvc32.dll

ファイル名

-

SVCLDR64.dll

ファイル名

-

DataOper64.dll

ファイル名

-

C:\ProgramData\Users.inf

ファイル名

-

%LOCALAPPDATA%\OneDrive\Cache.dat

ファイル名

-

C:\ProgramData\Security_checker\sc.dll

ファイル名

-

C:\ProgramData\Xps viewer\xpsservices.dll

ファイル名

-

C:\Program Files (x86)\Common Files\System\ado\msado28.dll

ファイル名

-

C:\ProgramData\networks.dat

ファイル名

-

C:\ProgramData\Microsoft\Crypto\RSA\Keys.dat

ファイル名

-

SntpService.dll

ファイル名

-

sdc-integrity.dat

ファイル名

-

sds-integrity.dat

ファイル名

-

HKCR\.z\OpenWithProgidsEx

レジストリ

-

HKCR\.z\OpenWithListEx

レジストリ

-

HKCR\.sbr\Order

レジストリ

-

HKCR\.sbr\StartOverride

レジストリ

-

HKU\<any_key>\Software\kuhO6Ba0kT

レジストリ

 

HKU\<any_key>\Software\OIfkO2i1

レジストリ

-

HKU\<any_key>\Software\7QAEGXJc

レジストリ

-

HKCR\.c\Type\Type00

レジストリ

-

HKR\Software\Microsoft\EventSystem\8C345CCE-5C37-446E-9E36-B57A54FC9C45

レジストリ

-

HKLM\SYSTEM\CurrentControlSet\Services\<service>\Parameters\8C345CCE-5C37-446E-9E36-B57A54FC9C45

レジストリ

-

HKR\.kci\PersistentHandler

レジストリ

-

HKCR\.3gp2\Perceived-Type

レジストリ

-

HKCR\.3gp2\Content-Type

レジストリ

-

HKCR\.rat\PersistentHandler\MagicNumber

レジストリ

-

HKCR\.rat\PersistentHandler\TypeFace

レジストリ

-

HKCU\Software\Microsoft\FTP\MostRecentApplication

レジストリ

-

HKCU\Software\Microsoft\FTP\UserInfo

レジストリ

-

HKCU\Software\F32xhfHX

レジストリ

-