
2026/08/25 12:26
スリープウォーカー:独自の命令言語を持つ受動的なバックドア
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
最も重要な発見点は、SLEEPWALKER が、正当な ESET Management Agent(ERAAgent.exe)をサイドローディングして偽装するための洗練されたパッシブバックドア DLL として機能していることです。これらは不活性状態に留まり、静的 AES-256-CCM 暗号化および複雑なネットワーク検証チェック(CRC-32 チェックサムの例を含む)を利用し、TCP、UDP、ICMP、SMB ネイムパイプ、VMware VMCI などの複数の隠蔽されたトランポートを通じて特定のトリガーパケットを待機します。活性化されると、明文化テキストではなく固有の内部バイトコードインタプリタを使用して 23 指令に制限されたマルウェア命令を実行します。これは復号化キーを取得した後も言語を逆変換する必要を生じます。ステルス性と永続性を維持するためには、SLEEPWALKER は正当なファイルメタデータ(バージョンリソース)を偽造し、存在しない DLL(例:dpapisvc.dll)へのスタブを動的に解決し、誤ってアクセスされた場合、自身の終了を引き起こします。さらに、ホストレジストリーキー(EveryoneIncludesAnonymous、NullSessionPipes)を変更して、認証不要のネイムパイプアクセスを可能にします。分析は frontier AI モデルによって支援されましたが、バイトコードのセマンティクスと検出論理については手動確認が必要でした。今後のビルドでは、DNS トリガーサポートを含むアクティベーションベクトルの拡大が行われる可能性があります。組織は、標準認証をバイパスするこのサイドローディング偽装攻撃から深刻なリスクに直面しています。ただし、提供された YARA ルールと PowerShell スクリプトを使用して、疑わしいレジストリー変更を検出、ファイル存在(サイズ~59,904 バイト)を確認し、暗号化ハッシュを一致させることで、悪意のあるコードを実行せずにこれらの脅威を緩和することができます。
本文
SLEEPWALKER:独自の命令言語を持つ受動的なバックドア
年初に VirusTotal Intelligence へのアクセスを失ったことは、意外にも生産的でした。VirusTotal Intelligence のマルウェア探索ができず、「TODO」リストも増えないため、 backlog をすべて処理しました。その結果、BeheMOF の詳細な検証や今回発見したマルウェアの確認に至りました。
調査を進めるにつれ、一見特筆すべきではなかったサンプルが、内部構造を覗くと独自の設計を持っていることが明らかになりました。それが受動的なバックドアであり、明らかなリスニングポートを開かず、ペイロードも含まないものです。特定のネットワークパケットが届くまで何もしない状態を保ち、これを**「SLEEPWALKER(眠行者)」**と呼んでいます。
公開価値のある点は、このマルウェアが受け取るコマンドの内容です。それは読み取れるテキストコマンドではなく、バックドア独自の設計による命令言語で書かれた短いプログラムです。
- 指令数: 23 件の指令
- 機能範囲: スケジュール、データの移動方法数種、段階的なファイル配信、直接メモリ内のコード実行
- 復号化の難易度: 暗号化鍵の取り戻しだけではプログラムを解読できません。内部の命令言語もリバースエンジニアリングが必要です。
SLEEPWALKER の特徴:
- 設計: リバースエンジニアリングの観点からは「クールな設計」
- 弱点: 実装上にいくつかの弱点があり、最高レベルのマルウェア工学とは言えません(初期バージョンの可能性)
- 公開内容: ファイルのロード・起動方法、ネットワーク隠匿方法、コマンド保護、内部命令言語の動作
- 補足: IOC セクションと YARA ルールおよび読み取り専用スクリプト
エグゼクティブサマリー
SLEEPWALKER は独自の命令言語を持つ受動的なバックドアです。固定された C2 アドレスに連絡せず、機密トリガーパケットを検出するためにネットワークをスニッフします。
ライフサイクルの概要:
- サイドローディング: ファイルは署名しておらず、ESET のファイル情報をコピーし、DLL サイドローディングを通じてロードされます。
- アクティベーションチェック: プロセス名が
(ESET Management Agent)の場合のみ活性化します。ERAAgent.exe - トリガー機構: サーバーには連絡せず、特定の一つの暗号化されたネットワークパケットが届くまで待ち続けます。
- コマンド実行: トリガー後に、読み取り可能なテキストではなくバイトコードとして到着したプログラムを実行します。
- ペイロード配送: ファイル自体には既製ペイロードは含まず、後からネットワーク経由で到着します。
- ホスト操作: ローカル Windows の設定を変更し、認証されていないネットワーク接続を可能にします。
図 1: サイドローディングから実行までのパス:一致する一つのパケットが届くまで何も実行されません。
キーポイント
- ファイルは署名されておらず、DLL サイドローディングを通じてロードされます。
- プロセス名
にチェックのみを行います。ERAAgent.exe - 固定サーバーへの接続はなく、特定の暗号化パケットでトリガーされます。
- 実行されるプログラムはカスタム命令言語(バイトコード)です。
- ファイル自体に悪意のあるペイロードは含まれていません。
- 認証されていないネットワークアクセスを可能にする設定変更を行います。
ファイル特性
サンプルは Windows GUI サブシステム用の署名されていない 64 ビット DLL です。
- サイズ: 59,904 バイト
- コンパイルタイムスタンプ: UTC 2024-06-10 09:18:27
ハッシュ値:
- SHA-256:
d347170752a28e2b8c4b8b9f3cab2e3a6541ba11682c94498d26eb9002779d60 - SHA-1:
2ec8aa9661a33bccc002150ce1ed02d90c3986ff - MD5:
2318327b29bb1c0e2d2b5f0211fc7fac - Imphash:
4e2dbfa7e3efd4cca2f3662797df9735
擬装とバージョン情報
ファイルは ESET の真の Management Agent からコピーされたバージョンリソースを持っています。
| フィールド | 値 |
|---|---|
| CompanyName | ESET |
| ProductName | ESET Management Agent |
| FileDescription | ESET Management Agent Module |
| InternalName | ERAAgent |
| OriginalFilename | dpapi.dll |
| File / Product version | 11.2.2076.0 |
| LegalCopyright | Copyright (c) ESET, spol. s r.o. 1992-2024. |
データ保護関数の挙動
ファイルは真の
dpapi.dll と同じ名前と、以下の 7 つの関数をエクスポートします:
CryptProtectDataNoUICryptProtectMemoryCryptResetMachineCredentialsCryptUnprotectDataNoUICryptUnprotectMemoryCryptUpdateProtectedStateiCryptIdentifyProtection
これらすべての関数は、ポインタテーブルをジャンプする小さなスタブです。これらのどれかを初めて呼び出す際、共有レジバーは
LoadLibraryW で dpapisvc.dll をロードしようとします。真の関数を見つけ、アドレスを書き込むことで呼び出しを進めます。
- 注意点:
に搭載されるWindows
という名前のファイルはありません(近いのはdpapisvc.dll
ですが無関係)。単なるdpapisrv.dll
の参照でも失敗するため、悪意のあるファイルはすでにホストプロセス内でその名前を占有しているためです。ロードが失敗した場合、DLL はホストプロセス全体を終了します。dpapi.dll
初期化および起動シーケンス
他の処理を行う前に、DLL はロードしたプロセスの名前をチェックします。
- プロセス名チェック:
でない場合、不活化のまま(デバッガーやサンドボックスでは実行されません)。ERAAgent.exe - パスチェック: シグネチャやパスはチェックせず、名前のみをチェックします。
このチェックがパスすると、バックドアを起動する以下の手順を実行します:
- ESET のコードとは別々に、新しいバックグラウンドスレッドを開始。
- 128 KBのメモリブロックを予約(後からピースごとに到着するプログラム用)。
- ファイル内に格納されている一つの指令を復号化。
- Windows ネットワーキングを用意し、復号化された指令を内部インタープリターに渡す。
インタープリターの再利用
このインタープリターは一度だけ使用されません。後からトリガーが次のプログラムを配送する際にも同じ関数を実行するため、命令言語全体(スケジュール、段階的なファイル配信、メモリ内コード実行)を別のコンポーネントに組み込む必要がありません。
起動パスとフォールバック
7 つのエクスポートされたデータ保護関数のいずれかを呼ぶ初回の回に、進み前に同じチェック・シーケンスが再び実行されます。これにより、バックドアに2 つの起動機会が与えられます。
| パス | 条件 |
|---|---|
| パス 1 | DLL が にロード () |
| パス 2 | 最初の呼び出しが 7 つの転送された DPAPI エクスポートのいずれか |
両方のパスは独立して以下の動作を行います:
- ホストプロセス名をチェック
- 同じ起動シーケンスを実行(バックグラウンドスレッド開始、バッファー予約、ブートストラップ指令復号化、インタープリター起動)
重複ワーカー問題: どのパスがすでに実行されたかがチェックされません。これが後述する重複ワーカー問題の根源です。
- プロセス終了リスク:
において停止フラグを設定しますが、動的アンロードを保証しません。スレッドヘルパーは直ちにハンドルを閉じますが、detach パスは完了を待たないため、DLL がアンマップされる際にワーカーが実行中である可能性があります。DLL_PROCESS_DETACH
認証されていない名前付きパイプアクセスとネットワーク機能
SLEEPWALKER はホストを積極的に弱体化します:
- 匿名 SMB アクセスを有効に。
およびEveryone
に権限を与えた名前付きパイプを作成。Anonymous Logon- 暗号化は、静的にリンクされた mbedTLS コピーによって提供されます(ランタイムロードなし)。
自律的なビーコンニングや固定サーバーなし
SLEEPWALKER は開始後すぐに C2 サーバーを連絡しません。ドメイン、IP アドレス、URL もビルトインされていません。
- 正当な
は通常、ESET PROTECT とチェックインするため、バックドアが不活性の間にも ESET トラフィックは生成されます。ERAAgent.exe
トリガーパケットの検出メカニズム
バックドアはプロミスクアスモードにネットワークカードを設定し、すべてのパケットをチェックします。特定のパターン(計算されたチェックサム、符号化された長さ値、暗号化されたデータブロック)のみを認識します。これらを「魔法のパケット」と呼びます。
復号化手順表
| ステップ | チェック内容 | 失敗した場合の処理 |
|---|---|---|
| 1 | パケットが少なくとも 48 バイトか? | 無視 |
| 2 | 最後の 2 つの 16 ビット値を XOR し、結果に 0xAAAA を XOR(候補長取得) | N/A |
| 3 | 候補長が有効範囲内か? | 無視 |
| 4 | の位置にあるバイトペアが、尾部値の合計と一致するか? | 無視 |
| 5 | 候補長を指すブロックが自身の CRC-32 チェックを通過するか? | 無視 |
| 6 | AES-256-CCM で復号化し、結果をコマンドとして扱う | N/A |
- 処理: どのステップでも失敗すればパケットは反応なしでドロップされます。すべてのステップをクリアするパケットのみがコマンドとして扱われます。
- プロトコル独立性: チェックは生コンテンツレベルで行われるため、特定のプロトコルではなくほぼあらゆる IP トラフィックの中を通過できます。
- インターフェース数: 最大 8 つのネットワークインターフェースを見守ります(ループバックインターフェースを除く)。
- 遅延: 成功したトリガー後、少なくとも 3 秒待ちます(繰り返し試みをブロックするため)。
暗号化と構成
ファイル自体に含まれている構成には、単一の指令のみが含まれています:制限時間なしですべてのネットワークインターフェース上で、一致パケットのために待ちます。後から到達するアクションはすべてすでに暗号化されています。
鍵情報:
- AES-256 キー:
0x746531ff378dbb4bb51d2aa2b1d38d905350a959583186baf4c690f5f316b3ae - Config nonce:
0x3a6d357fb9bc51eacc8b8509
コンテンツの保護と方向性
| コンテンツ | 方向 | エンコードまたは暗号化 | 説明 |
|---|---|---|---|
| トリガー、TCP/UDP、パイプ、VMCI を通じたタスクプログラム | SLEEPWALKER 内へ | AES-256-CCM | コマンドバイトコードは解釈する前に暗号化および認証されています。 |
| DNS ラベルに運ばれたタスクプログラム | SLEEPWALKER 内へ | Base32 over AES-256-CCM | Base32 がエンベロープを DNS ラベルに適しているようにします。 |
でロードされたプログラム | ローカル | AES-256-CCM | ファイルは解釈する前に暗号化されたタスクエンベロープを含みます。 |
で使用されるネストプログラム | 内部 | AES-256-CCM + XOR | プログラムは暗号化され、スケジュール実行間で XOR 保護されます。 |
| TCP/UDP/ICMP/PIPE SEND のデータ | SLEEPWALKER から外へ | 自動的暗号化なし | 指令は暗号化で到着しますが、データをそのまま送信します。 |
| メタデータ(ヘッダー、フレミング、CRC など) | タスク配送を伴う | 可視メタデータ | 輸送・認識・検証用です。平文コマンドコードを暴露しません。 |
バイトコード形式
復号化後、コマンドはテキストではなく、特定の順序で読み取るまで意味のある短い生のバイトのシーケンスです。
コンパクトな設計
- 最も簡単な形式:直接追跡可能な純粋なテキストと数字(検出も容易)。
- より高度な形式:暗号化された保護レイヤーを持つ(鍵回復前に解釈不可能)。
レーディングルール
- オペコード: 各指令は 1 つのバイトで始まり、23 種類のどれかを示します。
- 固定サイズデータ: 有効なバイトセットを使用して書かれます(先頭バイトが最重要)。
- 可変サイズデータ: テキストブロックや任意長さのデータは、後続するバイトのカウントとして書かれ、リーダーはピースの終了と次の開始を正確に把握する必要があります。
例 1: SNIFF_MAGIC_PACKET (5 バイト)
87 01 2A 00 00
: コマンド = SNIFF_MAGIC_PACKET (ネットワークの隠れたトリガー見守り)87
: 長さカウント = 1 バイトが来る01
: データ =2A
(すべてのインターフェース)*
: 期限 = 0 秒(制限なし)00 00
木構造:
- コマンド: SNIFF_MAGIC_PACKET (0x87)
- interface_filter: 長さ
, データ01* - deadline_seconds:
(制限なし)0
- interface_filter: 長さ
例 2: CRON_SCHEDULE (22 バイト)
0E 00 00 00 00 00 00 00 01 00 00 02 00 FF FF FF FE 3E 03 9D FD C1
- スケジュール: 毎週平日 09:00 に実行
- ネストプログラム: 内側に別の指令が含まれる(XOR 保護付き)
木構造:
- コマンド: CRON_SCHEDULE (0x0E)
- minute_bitmask: 分
0 - hour_bitmask: 時
9 - day_of_month_bitmask: 任意の日
- weekday_bitmask: 月〜金 (
)0x3E - xor_masked_script (長さ
, データ03
)9D FD C1- XOR 解除後:SLEEP_RANDOM_SECONDS (上限 60 秒)
- minute_bitmask: 分
ネスト構造の特性
- 復号化は一時的: コードはネストプログラムのバッファーとキーで XOR され、実行後に再暗号化されます(復号化→実行→再暗号化)。
- 内部 XOR レイヤー:
に固有であり、スケジュール実行間でのみ有効です。CRON_SCHEDULE
コマンド言語リファレンス
初期トリガー後のバックドアは以下の 23 件の指令によって制御されます。これらは組み合わせて多数の異なる振る舞い(スケジュール、ネットワークリスナーなど)を可能にします。
指令リファレンス表
| 指令 | カテゴリ | 動作内容 | パラメータ |
|---|---|---|---|
| EXIT | 基本制御 | プロセス停止フラグを設定せず、プログラムの終了を指示しない(ファイルのループがチェックして止める)。 | なし |
| SPAWN_THREAD_SCRIPT | 基本制御 | 現在のスレッドと独立した第二のプログラムを起動。第一のスレッドは続行可能。 | 実行するネストプログラム (blob) |
| SLEEP_SECONDS | タイミング | 固定秒数の間停止。 | 継続時間、秒 (u16) |
| SLEEP_RANDOM_SECONDS | タイミング | 選択された上限までのランダム秒数で待機(ジッターあり)。 | 上限、秒 (u16) |
| CRON_SCHEDULE | スケジュール | 分・時・日・曜日のパターンに一致した際、内側プログラムを実行。 | マスク (u64/u32/u8)、ネストプログラム (blob) |
| REPEAT_N | スケジュール | より小さなプログラムを固定回数連続で実行。 | 繰り返し回数 (u16)、ネストプログラム (blob) |
| LOOP_FOREVER | スケジュール | 制限なしでより小さなプログラムを繰り返し実行(バックドア停止まで)。 | ネストプログラム (blob) |
| TCP_SEND | データ送信 | 選択されたアドレスとポートに TCP 接続を開き、データを送信(返事なし)。 | ローカル/リモートアドレス、ポート、データ、デッドライン |
| UDP_SEND | データ送信 | 選択されたアドレスとポートに UDP で単一データブロックを送信(返事なし)。 | ローカル/リモートアドレス、ポート、データ、デッドライン |
| ICMP_SEND | データ送信 | ピング要求の中にデータブロックを隠し、ターゲットに送信。 | ソース/リモートホスト、データ、デッドライン |
| PIPE_SEND | データ送信 | 選択された PC の Windows 名前付きパイプにデータを書き込む(認証オプションあり)。 | サーバー名、パイプ名、認証情報、データ、デッドライン |
| TCP_CONNECT_RECV | インバウンド受信 | 選択されたアドレスとポートにアウトバウンド接続し、次のプログラムを受信。 | ローカル/リモートアドレス、ポート、デッドライン |
| TCP_LISTEN_RECV | インバウンド受信 | TCP ポートを開放して接続を受け付け、次のプログラムを受信。 | バインドアドレス、ポート、デッドライン |
| UDP_BIND_RECV | インバウンド受信 | UDP ポートを開放し、単一インバウンドデータブロックを受信。 | バインドアドレス、ポート、デッドライン |
| PIPE_CLIENT_RECV | インバウンド受信 | 選択された PC の名前付きパイプに接続して次のプログラムを受信。 | サーバー名、パイプ名、認証情報、デッドライン |
| PIPE_SERVER_RECV | インバウンド受信 | ローカルに名前付きパイプを作成し、接続を待機。 | パイプ名、未使用フィールド、デッドライン |
| STAGE_WRITE | プログラム構築 | 128 KB ワークエリアのオフセットにプログラムピースのコピーを行う。 | オフセット (u32)、データチャンク (blob) |
| STAGE_VERIFY_EXEC | プログラム構築 | 収集されたピースの SHA-256 で検証し、一致すれば実行。 | 長さ (u32)、SHA-256 指紋 (blob) |
| DECOMPRESS_RUN | プログラム実行 | 圧縮されたプログラムを展開し、その後実行。 | 展開サイズ (u32)、lzma_properties, 圧縮データ (blob) |
| RUN_SHELLCODE | プログラム実行 | 生のマシンコードブロックを直接メモリ内で実行(書き込み後実行可能化)。 | マシンコード (blob) |
| RUN_FILE_SCRIPT | プログラム実行 | ローカルディスクのファイルを復号化し、結果を実行。 | ファイルパス (string) |
| SNIFF_MAGIC_PACKET | トリガー検出 | 前述の隠れたトリガーパケットを検出。 | インターフェース (string)、デッドライン |
| SNIFF_MAGIC_PACKET_DNS | トリガー検出 | DNS ベースのトリガーも有効化(分析ファイルには存在せず)。 | インターフェース、デッドライン |
基本制御の詳細例
- EXIT (0x06): バックドアを終了。DLL アンロードパスで使用される共有フラグを設定し、すべてのリスナーを停止。
- SPAWN_THREAD_SCRIPT (0x0B): 例:
(トリガーリスナーのバックグラウンドコピー実行)0B 05 87 01 2A 00 00
タイミングとスケジュールの詳細例
- SLEEP_SECONDS (0x0C): 60 秒待機。
- 例:
0C 00 3C
- 例:
- SLEEP_RANDOM_SECONDS (0x0D): 0〜299 秒のランダム待機。
- 例:
(上限 300 秒)0D 01 2C
- 例:
- CRON_SCHEDULE (0x0E): 毎週平日 09:00 に実行し、その後ランダム待機(内蔵ネストコマンド)。
データ送信の詳細例
- TCP_SEND (0x29): ポート 443 に
にテキスト送信。ワイルドカード (192.168.1.10
) を使用可能。*- 例:
29 01 2A 01 2A ...
- 例:
- UDP_SEND (0x2A): ポート 53 に
に "ping" 送信。10.0.0.9 - ICMP_SEND (0x2B): データを disguised ping にして
へ送信。8.8.8.8 - PIPE_SEND (0x2C): サーバー名
のDC01
パイプに "beacon" 書き込み(認証付き)。spoolss
インバウンドタスク受信の詳細例
- TCP_CONNECT_RECV (0x6F): VMCI チャネル (
) を通じてアウトバウンド接続し、ポートvm:2
で待機。9000 - TCP_LISTEN_RECV (0x70): ローカル任意アドレスでポート
でリスニング。8443 - UDP_BIND_RECV (0x73): ローカル任意アドレスでポート
でリスニング。5353 - PIPE_CLIENT_RECV (0x7D): ワークステーション上のパイプ "mojo" に接続(現在のログイン使用)。
- PIPE_SERVER_RECV (0x7E): ローカルにパイプ "mojo_pipe" を作成し接続を待ち。
プログラムの構築と実行の詳細例
- STAGE_WRITE (0x32): 6 バイトのデータチャンクをワークエリアにコピー(オフセット指定)。
- 例:
32 00 00 00 00 06 ...
- 例:
- STAGE_VERIFY_EXEC (0x33): 収集されたピースの SHA-256 で検証。一致すれば実行。
- 例:
33 00 00 00 06 A0 A0 D4 5F ...
- 例:
- DECOMPRESS_RUN (0x1F): LZMA アルゴリズムで圧縮されたプログラムを展開し実行。
- 例:
1F 00 00 08 00 ...
- 例:
- RUN_SHELLCODE (0x65): メモリ内シェルコード実行(VirtualProtect で保護)。
- 例:
(xor rax, rax ; ret)65 04 48 31 C0 C3
- 例:
- RUN_FILE_SCRIPT (0x66):
を読み取り実行。C:\ProgramData\d.dat
トリガー検出の詳細例
- SNIFF_MAGIC_PACKET (0x87): 分析ファイル内に格納されている指令(生パケット見守り)。
- 例:
87 01 2A 00 00
- 例:
- SNIFF_MAGIC_PACKET_DNS (0x88): DNS ベースのトリガーも有効化(分析ファイルには存在せず)。
代替トリガーチャネルと輸送手段
VMware VMCI チャネル
5 つのネットワーキング指令は、アドレスが
vm: で始まる場合に VMware の内部チャネル (VMCI) を使用します。
- 機能: ゲストとホスト間、または同じホスト上の 2 つのゲスト間でコマンドを通過可能。
- 特徴: 物理ネットワークアダプターに触れず、外部からはパケットキャプチャ不可。
DNS ベースのトリガー
通常の DNS ルックアップの中に隠された第二の方法。
- 形式: DNS ラベル内に暗号化データ(AES-256-CCM)を Base32 符号化して埋め込む。
- 構造:
+マーカ文字
+Base32 ペイロード
(チェックサム付き)。マーカ文字 - 検出: CRC-8 チェックサムにより、通常のラベルと区別し、特定のラベルのみを処理。
- 例:
mqfoceywmw4etcjdp2nptitil.example.com
DNS トラフィックの暗号化例
- 暗号化済み (14 バイト):
81 5C 22 62 CC B7 09 31 24 6F D3 5F 34 4D- Nonce: 7 バイト, Tag: 4 バイト, Ciphertext: 3 バイト
- Base32 符号化 (23 文字):
mqfoceywmw4etcjdp2nptitil- CRC-8:
→ マーカは0x65
とml
- CRC-8:
復号化後、トリガーパケットの内容と同じようにインタープリターに渡されます。
6 つの基礎輸送
| 輸送 | メカニズム | 備考 |
|---|---|---|
| TCP | ソケット / 接続 / リスナー | で解決。クライアント/サーバー両方可能。 |
| UDP | sendto / recvfrom | ワンショット送信とバインド-受信。 |
| ICMP | IcmpSendEcho | データはピングリクエストペイロード内に密輸。 |
| SMB 名前付きパイプ | Named Pipes | サプライされた資格情報でリモート共有へのサイドステップ移動可能。 |
| VMware VMCI | API | 物理アダプターを介さず、VM ファブリック内で通信。 |
| Raw / promiscuous | Raw socket | プロミスクアスモードで隠れたトリガーパケットを受信。 |
ネットワーク到達可能性と攻撃者の位置
チャネル比較表
| チャネル | インターネット | ファイアウォール/NAT | 内部ネットワーク | ターゲットホスト |
|---|---|---|---|---|
| 生のトリガー (最初) | ブロック | ブロック | 到達 | 到達 |
| DNS トリガー (実装済み) | 到達 | 到達 | 到達 | 到達 |
| VMCI | - | - | - | 同じ VMware ホストのみ |
| アウトバウンド開始 (トリガー後) | 到達 | 到達 | 到達 | 到達 |
| インバウンド受信 (トリガー後) | ブロック | ブロック | 到達 | 到達 |
- 「ブロック」: 境界ファイアウォールで通常停止されることを意味するが、例外もある。
配信とアクセスの特性
- 最初の命令(トリガー): 生パケットは境界ファイアウォールでブロックされやすい。
- 例外: パブリック IP、NAT/ポートフォワード、またはパブリック DNS サーバーを実行するホストへの到達可能。
- 内部ルート: ゲートウェイや VPN サーバーを介してのトラフィックキャプチャが可能(SIO_RCVALL オプション)。
- DNS トリガー: ファイアウォールを横断するのに適したチャネル(パケットがインターフェースに到達する必要があるため、生パケットとは異なる経路)。
- タスク実行後:
- アウトバウンド送信 (
,TCP_SEND
など): NAT やファイアウォールの背後から動作可能。UDP_SEND - インバウンド受信 (
など): 生トリガーと同様の到達可能性要件(ブロックされやすい)。TCP_LISTEN_RECV
- アウトバウンド送信 (
結論
- DLL サイドローディングは SLEEPWALKER を
内に永続化させる。ERAAgent.exe - ターゲット: ESET Management Agent がインストールされた管理された 64 ビット Windows エンドポイント。
- 設計思想: 標的型で資源のある操作(機会主義的ではない)。単一のカラフルなパケットで目覚める受動的インプラント。
ホスト構成変更
認証されていない名前付きパイプアクセスを容易にするため、バックドアは以下の設定を変更します:
をEveryoneIncludesAnonymous
に設定(匿名トークンへの権限適用)。1- パイプ名に
を追加。NullSessionPipes
これにより、認証されていない呼び出し者がパイプチャネルに到達可能になります。コードは後で変更を取り戻そうとしますが、元の構成を完全に復元する保証はありません。クリーンアップ時に既存のエントリが削除される可能性があります。
- 権限エスカレーションなし: UAC バイパスやより高い権限の獲得を試みません。
- 永続化: サイドローディング自体のみを使用。
AI 使用について
SLEEPWALKER は Windows PE マルウェアのリバースエンジニアリング比較のために使用したサンプルの一つです。初期分析は手動で行い、詳細分析・検証に AI を活用しました。
- テストモデル: Claude Opus 5, GPT-5.6-Sol, Claude Opus 4.8, Sonnet 5 など(Kimi K3 は待機中、Fable はフィルタ制限で除外)。
- パフォーマンス: 広範囲に似た結果。Claude と GPT はそれぞれ得意分野があったが、モデル家族は常に最良ではなかった。
- 例外:
の解析では、3 つの試みのうち Claude が機能同一を誤認した一方、GPT は重要違い(0x87 生パケットのみ vs 0x88 DNS も有効)を識別。SNIFF_MAGIC_PACKET_DNS
- 例外:
- 安全性制限: GPT-5.6-Sol は安全拒否なしで全テスト完了。Claude Opus/Sonnet は早期および大進捗後に拒否に遭遇(調査継続を妨げた)。
- 結論: AI は詳細な解剖を分数の時間で可能にする強力なツールですが、技術的検証と慎重なレビューは依然として必要です。AI はノート整理や草案作成を助け、最終的な校正・技術検証を経てレポート化されます。
未解明のもの
この分析は一つの SLEEPWALKER バイナリに基づいており、以下の重要な点は不明です:
- サンプル起源および被害者: 業界、国、または影響を受けた組織を特定できません。
- 初期アクセスおよび配送: ドロッパーやエクスプロイトなし。管理者権限取得方法不明。
- 同伴コンポーネント:
のフォワード依存関係は別のコンポーネントの存在を示唆しますが、サンプル内にはありません。dpapisvc.dll - 実際に受信されたコマンド: 唯一の実行指令は生パケットリスナーのみ。他のペイロードが実行されたかは不明。
- 実際に使用されたチャネル: DNS、VMCI、ICMP、パイプなどの実装はないものの、実際には使われたか証明できません。
- インフラストラクチャおよび攻撃者の位置: ハードコーディングされたサーバーや識別子なし。
- 帰属とキャンペーン: 特定のグループへの帰属または広範な展開の証拠なし。
SLEEPWALKER を標的化されたと信じるか、サンプルを遭遇した場合はご連絡ください。検出ツール(YARA ルールなど)は作成済みです。
結論
SLEEPWALKER は受動的なバックドアであり、C2 サーバーに連絡せず、
ERAAgent.exe への DLL サイドローディングを通じて実行されます。
- 機能: スケジュール、6 つの輸送手段、SHA-256 検証付き段階配送、メモリ内実行の実装。
- 特徴: 単一のパケットで目覚め、VMCI や ESET 管理コンポーネントを利用した標的型攻撃の一部である可能性が高い。
補足
ファイルダウンロード
SLEEPWALKER はここからダウンロード可能です (パスワード: "sleepwalker_infected"):
sleepwalker.zip
インジケーターオブコンプロマイス (IOC)
- SHA-256:
d347170752a28e2b8c4b8b9f3cab2e3a6541ba11682c94498d26eb9002779d60
の隣に予期せぬERAAgent.exedpapi.dll- 同ディレクトリ内の予期せぬ
dpapisvc.dll - レジストリ値:
がEveryoneIncludesAnonymous
に設定される1 - レジストリ値:
の予期せぬエントリNullSessionPipes
YARA 検出ルール
import "pe" rule sleepwalker_backdoor { meta: author = "Dominik Reichel" description = "Detects the SLEEPWALKER passive backdoor." sha256 = "d347170752a28e2b8c4b8b9f3cab2e3a6541ba11682c94498d26eb9002779d60" date = "2026-08-11" reference = "https://r136a1.dev/2026/08/24/sleepwalker-a-passive-backdoor-with-its-own-command-language/" strings: // Static AES-256 key used for every authenticated task envelope $aes_key = { 74 65 31 FF 37 8D BB 4B B5 1D 2A A2 B1 D3 8D 90 53 50 A9 59 58 31 86 BA F4 C6 90 F5 F3 16 B3 AE } // 12-byte nonce for the embedded-bootstrap task envelope $config_nonce = { 3A 6D 35 7F B9 BC 51 EA CC 8B 85 09 } // Trigger-packet validation logic: length check, then XOR the packet's // last two 16-bit values together and XOR again with 0xAAAA to get a // candidate length, checked against a minimum of 0x1C (28). This is // the backdoor's own protocol code. $magic_packet_algo = { 49 83 FC 30 // cmp r12, 0x30 0F 82 ?? ?? ?? ?? // jb ... 47 0F B7 44 25 FC // movzx r8d, word [r13+r12-4] 47 0F B7 4C 25 FE // movzx r9d, word [r13+r12-2] B8 AA AA 00 00 // mov eax, 0xAAAA 41 0F B7 C8 // movzx ecx, r8w 66 41 33 C9 // xor cx, r9w 66 33 C8 // xor cx, ax 66 83 F9 1C // cmp cx, 0x1C } // Non-existent DPAPI service DLL $dpapi_svc = "dpapisvc.dll" wide condition: uint16(0) == 0x5A4D and uint32(uint32(0x3C)) == 0x00004550 and ( any of ($aes_key, $config_nonce, $magic_packet_algo) or ( pe.version_info["OriginalFilename"] contains "dpapi.dll" and ( pe.version_info["FileDescription"] contains "ESET Management Agent Module" or $dpapi_svc ) and pe.exports("CryptProtectDataNoUI") and pe.exports("CryptProtectMemory") and pe.exports("CryptResetMachineCredentials") and pe.exports("CryptUnprotectDataNoUI") and pe.exports("CryptUnprotectMemory") and pe.exports("CryptUpdateProtectedState") and pe.exports("iCryptIdentifyProtection") ) ) }
PowerShell 検出スクリプト
(スクリプト本文は提示されていません)