サイバー脅威
AIを駆使した自動脅威ハンティング:闇に潜んでいたマルウェア「GhostPenguin」を発見
AIを駆使した脅威ハンティングとマルウェア解析により、これまで未検知で報告のなかったLinux型バックドア「GhostPenguin」が発見され、その性質が細部にわたって解明されました。
- GhostPenguinはC++言語で作られたマルチスレッド型のLinux用バックドアであり、攻撃者にリモートシェルやファイル操作の手段を提供します。通信にはUDPプロトコルを使用し、RC5で主要データを暗号化します。
- このバックドアは、遠隔操作サーバとの間で独自仕様のセッションを確立し、マルチスレッドによって登録処理やハートビート通知、指示対応を並列的に行います。さらに、受信チェックや自動再送の仕組みを備えています。
- GhostPenguinは、VirusTotalに置かれていた未検知のLinuxファイルであり、「Trend™ Research」によるAI駆動の自動脅威ハンティングを通して発見されました。その過程では、マルウェアのキー情報を蓄積したデータベースの作成、VirusTotalのクエリ作成、AIによる自動プロファイリングを行い、未検知状態のファイルを詳細分析にかけました。
- 本手法により、数千に及ぶマルウェア検体のキー情報を抽出し、GhostPenguinのように未検知の脅威を発見する上で有効なYARAルールやVirusTotalクエリを作成することが可能となりました。
- GhostPenguinにはデバッグ情報や未使用の関数も含まれ、その開発は現在なお進行中と考えられます。これが未検知であったことを踏まえると、AIや自動化技術が脅威の発見にいかに効果的かつ重要であるかがうかがえます。
- セキュリティプラットフォーム「Trend Vision One™」では、本稿で取り上げた「IoC(侵入の痕跡)」を的確に検知、ブロックするとともに、GhostPenguinに関わるハンティング用クエリや脅威レポートを提供しています。
はじめに
高度なマルウェアのハンティングには、相応の労力が伴います。特に、もともと検知率の低い検体(サンプル)を扱う場合、その手間と難易度は著しく増大します。日々、膨大な数のファイルが「VirusTotal」などのプラットフォームに提出されていますが、本当に重要なものは、大多数のノイズに埋もれがちです。また、対象マルウェアがいちから作られたもので、検知率が低く、関連情報も少ない場合、特定作業は一層難しくなります。そこに目をつけた攻撃者は、検知回避やハンティング妨害を念頭に、あえて公開ライブラリやGitHubの既存コード、既知のマルウェアコードを利用せず、全く新たなサンプルを作り出す可能性があります。
この場合、攻撃者はマルウェアを極力地味で無害なものに見せかけるため、コードやネットワーク通信を注意深く作り込みます。例えば、保護された通信チャネルと多段階の処理アーキテクチャを組み合わせ、攻撃者の期待する通信手順に乗らない限り、次段階の手口を明かさないように工夫します。結果、感染端末と遠隔操作(C&C:Command and Control)サーバ間のデータ通信はごく少量に限られ、検知や解析に必要な情報が不足しがちになります。
前回Trend™ Researchでは、近代的なマルウェア開発のエコシステムに焦点を当て、攻撃的なGitHubプロジェクトやレッドチーム向けオープンソースツールが悪用されていること、それがまた、防御側にとっても検知パターンや脅威ハンティングの改善に役立っていることを述べました。さらに同報告では、防御側でAI(人工知能)や自動化技術を活用することで、新規マルウェアファミリの出現や、オープンソースコードの流用を高速かつ高精度に検知できるという展望を示しました。
本稿では、AIを活用してVirusTotalから検知率の低い検体を発見する方法や、実際にLinux型バックドア「GhostPenguin」を特定、解析した際の道筋を解説します。
脅威ハンティングの手法
はじめに、過去の攻撃事例やレポートを元手に多くのマルウェア検体を収集し、その性質を解析することに焦点をあてました。ここでの目的は、新規または未検知の脅威を発見する際に役立つ情報を入手することです。
ハンティングの手順
1. 「キー情報」の収集
過去の攻撃事例やレポートを元手に多数のマルウェア検体を収集する。次に、その中から「キー情報」となる文字列やAPI呼び出し、関数名、変数名、定数定義、挙動を抽出し、結果をデータベースに格納する。さらに、各検体に対し、検索や比較のためのタグ付けや分類を行う。
2. VirusTotal用のハンティングクエリを構築
抽出したキー情報を元手にVirusTotal用のハンティングクエリを作成し、それを未検知の検体に対して実行する。候補の検体が見つかった場合、以降に示す「プロファイリングと解析」のステージに回す。
3. プロファイリングと解析
バイナリファイルについては、「IDA Pro(Hex-Rays)」の逆コンパイル処理にかけ、追加のキー情報を取得する。また、ツール「CAPA」を通して機能識別を行う(今回は、抽出済みのキー情報を元手にカスタムルールを作成した)。一方、スクリプトやコードなどの非バイナリファイルについては、直接「プロファイラー」に回し、特徴抽出を行う。これにより、各ファイルのプロファイル情報がJSONの統一形式で作成される。
次に、JSON形式のプロファイルをAIエージェント「Quick Inspect」に渡し、内容をチェックする。本エージェントは、キー情報をもとに不正判定用のスコアを算出する。そのスコアが閾値に満たない場合は、対象ファイルをレビュー用リストに追加しておく。
一方、閾値を超えたファイルに対しては、「不正」のタグ付けを行った上で、エージェント「Deep Inspector」の詳細分析にかける。本エージェントは、先の逆コンパイルで得られたコードやメタデータを含むプロファイル情報を精査し、コード解析レポートとして下記の内容を出力する。
- 概要ノート
- 特定された機能
- コードの実行フロー
- 技術分析の結果
- MITRE ATT&CKとの対応付け
実際に上記の手順を実行した結果、VirusTotalから未検知状態のバックドア型マルウェア「GhostPenguin(トレンドマイクロによる呼称)」が発見されました。当該検体は2025年7月にVirusTotalに提出されたものであり、4ヶ月以上に渡って未検知のままとなっていました。
補足事項として、圧縮/難読化ファイルについては、通常、YARAスキャナーやAIモデルによって特定可能です。こうしたファイルが見つかった場合は、展開用のパイプラインに引き渡すように、MCPサーバを設定できます。展開用パイプラインでは、自動化スクリプトや手作業を通して、対象ファイルの圧縮/難読化を解除します。なお、単純な圧縮/難読化方式ならばAI側でも直接展開できますが(AI固有のリソルバーやAI作成のスクリプトによる)、複雑な方式であれば、外部の自動化スクリプトや手作業で対応する方が望ましいでしょう。
以降では、本調査の流れを、より具体的に解説します。
ハンティングの第1フェーズ
第1フェーズでは、新規または未知の脅威を発見する上で必要な情報をできる限り多く収集し、それをデータベースに格納し、検体毎の詳細データを作成する必要があります。データベースの内容として、収集したマルウェア検体のメタデータやカテゴリ、タグ、機能、MITRE技術(Techniques)、文字列に加え、MBC(Malware Behavior Catalog)に基づく挙動情報が含まれます。こうしたデータベースは重要な価値を持ち、AIモデルのファインチューニングやコンテキストベースのAI検索、RAGワークフロー、知識ベースの構築、マルウェアの類似性照合、APT(Advanced Persistent Threat:標的型攻撃)の帰属判定など、さまざまな形で利用できます。
はじめに、ハンティングのワークフローに関わる主要なカテゴリを定義しました。また、ツール「Google Magika」を利用し、ファイルを自動分類できるようにしました。
- 対象OSのカテゴリ
- Windows
- Linux
- MacOS
- ファイル形式のカテゴリ
- バイナリ
- スクリプト
バイナリファイルについては、「IDA Pro」の逆コンパイルによってコードを抽出し、それをAIモデルの処理にかけました。このAIモデルは、関数の名前変更や処理内容に関するコメントの記載、概要ノートの作成、機能の特定、タグ付け、ネットワークの通信パターン分析などを行います。
さらに、対象検体をCAPAやFLOSS、YARAなどの分析ツールにかけました。こうして得られた全ての結果は、JSON形式で記載されます。続いて、JSONパーサによって関連フィールドを取り出し、データベース内に格納しました。元のJSONファイルについても、後の調査や処理に利用できるように、個別で保存しました。
一連の脅威情報収集システムの概要を、図1に示します。留意点として、この図は可読性や明確性のために簡略化されたものであり、実際には、さまざまな追加モジュールやコンポーネントが組み込まれています。
ハンティングの第2フェーズ
本調査の主目的は、未検知のLinux型バックドアを発見することであるため、データベースから全Linuxバイナリを抜き出し、頻度の高いAPI呼び出しや文字列、挙動情報を特定しました。次に、その結果に基づいてVirusTotalのハンティングクエリを作成することで、未検知または未知のマルウェアを正確に検索できるようになりました。こうしたクエリは、VirusTotalのRetroHuntやLiveHuntに供するYARAルールとして利用できる他、手動検索クエリとして用いることも可能です(図2)。GhostPenguinは図3の通り、この検索結果に含まれていたものです。
ハンティングの第3フェーズ
ハンティングクエリによって見つかった不正なファイル候補に対し、第3フェーズでは、各種処理やランク付けを行います。今回はELFバイナリに焦点をあてているため、該当ファイルの全てを逆コンパイルのパイプラインに流し込みました。このパイプラインでは、自動化スクリプトが対象ファイルをIDA Proの逆コンパイルにかけ、得られたコードをAIモデル「gemini-3-pro」によって分析しました(図4)。
GhostPenguinはC++言語で作られたマルチスレッド型のバックドアであり、Linuxを標的としています。「登録」のステップでは、システム情報としてIPアドレスやゲートウェイ、OSバージョン、ホスト名、ユーザ名などを取得し、C&Cサーバに送信します。続いて、C&Cサーバからの指示を受け取り、実行するようになります。指示内容に応じてGhostPenguinは、「/bin/sh」経由のリモートシェルを提供する他、ファイルやディレクトリの作成、削除、名前変更、読み込み、書き込み、タイムスタンプ編集、拡張子検索などを行います。
全てのC&C通信は、UDPのポート53番上で行われます。通信の初期段階としてGhostPenguinは、C&Cサーバから16バイトのセッションIDを取得します。以降、それをRC5アルゴリズムの暗号鍵として扱い、全ての通信データを暗号化します。また、接続を維持するために、定期的にハートビート通信を送信します。二重起動を防止する手段として、ユーザのホームディレクトリ内に「.temp」という名前のファイルを作成し、自身のプロセスID(PID)を書き込みます。
GhostPenguinの動作
技術解析
GhostPenguinは、起動するとまず、自身の実行環境について把握するため、カレントユーザのホームディレクトリや、起動パスの全体を取得します。ホームディレクトリの取得には関数「getpwuid()」を、起動パスの取得にはコマンド「readlink("/proc/self/exe")」を利用します。取得した情報をもとに、PIDファイルのパス(例:{ホームディレクトリ}/.temp)を決定します。
次に、自身の別インスタンスがすでに起動中であるかを判別します。そのために、PIDファイルがすでに存在し、かつ、そこに少なくとも4バイト(32ビットのPIDを表すのに十分なサイズ)が含まれているかを確認します。この条件を満たす場合は、PIDを読み取った上で、コマンド「kill({PID}, 0)」を実行し、当該プロセスがアクティブであるかをテストします(図7)。アクティブな場合(PIDがアクティブなプロセスに紐づく)、GhostPenguinの別インスタンスがすでに稼働中であると見なし、処理を中止します。それ以外の場合は、すでに存在していたPIDファイルを削除し(過去のインスタンスによるもので、すでに終了したものと判断)、処理を続行します。
この後GhostPenguinは、メインのループに入り、グローバルの終了フラグ「g_bIsClientExit」が「1」に設定されるまで、処理を継続します。ループ内では、グローバルな構造体「g_lpLinuxClientHostCfg」に格納されたC&Cサーバのアドレスを1件ずつ取り出し、通信セッションの確立を試みます。当該構造体の定義を、図8に示します。
特記事項として、バイナリ内には、デバッグ設定「g_szConfigDebug」が残されていました。このグローバル変数には、未使用のドメインやIPアドレスが含まれており、開発テスト時のデータが残留したものと見られます(図9)。
また、永続化を意図した2つの関数(ImpPresistence、ImpUnPresistence)が含まれており、完全に実装されているにも関わらず、まったく呼び出されていないことが分かりました。以上を踏まえると、本マルウェアの開発は、現在なお進行中であると考えられます。
さらに本マルウェアには、以下のような誤植が見られます。
- ImpPresistence:「Persistence」の誤記
- Userame:「Username」の誤記
- IsPorecessExistByPID:「Process」の誤記
GhostPenguinのメインループに相当するコードを、図10に示します。C&Cサーバのリスト内を一件ずつ取り出し、通信セッションの確立を試みます。成功した場合は、非同期通信用(ハートビート、データ受信、送信)のスレッドを起動し、当該サーバからの指示を待ち受けます。メインの親スレッドはアイドル状態に入り、接続が切れるか、終了の指示を受信するまで待機します。
マルウェアのネットワーク通信
GhostPenguinとC&Cサーバ間における通信の流れを、図11に示します。
GhostPenguinとC&Cサーバ間でやり取りされるパケットの構造を、以下に示します。
truct C2Packet {
unsigned short totalLength; // パケットサイズ
unsigned char sessionID[16]; // セッションID(RC5暗号鍵として利用)
unsigned char commandType; // 処理種別
unsigned char subCommand; // 処理方向およびACK確認フラグ
unsigned short taskID; // タスクID
unsigned int taskInstanceID; // インスタンスID
unsigned int taskSequenceNum; // シーケンス番号
unsigned char paddingLen; // パディングサイズ
unsigned char payload[]; // ペイロード + パディング
};
C&C通信における最初のステップは、セッションIDを取得することです(図12)。このためにGhostPenguinは、関数「GetSessionUDFromServer」を呼び出してスレッド「ThreadProcGetSessionIDFromServer」を起動し、セッションIDの取得が完了するまで最大5秒間待機します(図13)。本スレッドは、34バイトのUDPパケットを作成し、処理種別として「4:セッションIDの要求」を指定した上で、C&Cサーバに送信します。この初期パケットに関しては暗号化がなく、プレースホルダーのセッションIDには仮の値が埋め込まれます。今回、マルウェアの機能を再現してネットワーク通信を監視するために、解析環境内でC&Cサーバを立ち上げ、感染端末を仮想マシン(VM)として用意しました。さらに、感染端末からの通信トラフィックがC&Cサーバのホスト元サーバに転送されるように、設定を行いました。
GhostPenguinは、セッションID取得用のリクエストを送信した後、34バイトの応答パケットを待ち受けます(図14)。有効な応答パケットを受信し、その処理種別が「4:セッションIDの要求」である場合、16バイト分のセッションIDを取り出し、グローバル変数「g_szSessionID」に格納します。このセッションIDは、以降の通信を暗号化する際のRC5鍵として機能します。
セッションIDを取得した後、GhostPenguinはデータ受信用のスレッド「ThreadProcDataReceiver」を起動します。
このスレッドは無限ループで動作し、C&CサーバからのUDPパケットを待ち続けます。パケットを受信すると、バリデーション処理として、以下の事項をチェックします。
- パケットサイズ(フィールド名「totalLength」)が、実際に受信したパケットサイズと同一であること。
- セッションIDが、取得済みの値と同一であること。
- 暗号化されたセクションの長さが8の倍数であること。
上記の全条件が満たされた場合、暗号化されたセクション(オフセット18以降)を独自のRC5実装(MyRC5::EncDecRC5)によって復号します。この際のRC5鍵として、16バイトのセッションIDを利用します。次に、復号後のパケットを関数「OnReceivedPacket」に渡し、後続の処理を実行します。なお、RC5の暗号化アルゴリズムは、8バイトのブロック単位に適用されます。この理由から、暗号化セクションの長さは8の倍数に限定されます。
データ受信用スレッドを起動した後、GhostPenguinは感染端末をC&Cサーバに登録するために、関数「RegisterSelfToServer」を呼び出します。この関数は、登録用のスレッド「ThreadProcRegisterSelfToServer」を起動し、その処理が完了するまで最大10秒間待機します。登録用スレッドは、クラス「CBasicInfoGather」のインスタンスを作成し、下記を含むシステム情報を収集します。
- LANのIPアドレス
- デフォルトゲートウェイ(Netlinkのソケットから取得)
- OSディストリビューションに関する情報(「/etc/redhat-release」や「/etc/os-release」から取得)
- ホスト名
- カレントユーザ名(コマンド「whoami」によって取得)
- OSアーキテクチャ(「X64」か「X86」)
- プロセスID(PID)
- プロセスのビット区分(64ビットにハードコーディングされている)
- クライアントのアーキテクチャID(Linux x86の場合は「32」、Linux x64の場合は「33」)
収集したデータは、シリアライズ化され、バッファ内に格納されます。続いて登録用スレッドがループ処理に入り、バッファ内のデータを埋め込んだパケットを1秒毎にC&Cサーバに送信します。その処理種別には「1:新規タスク」を、タスクIDには「1:ステータスを初期化中に設定」を指定します。また、オフセット18以降のセクションに対しては、先のセッションIDをRC5鍵とする暗号化を施します。
C&Cサーバ側では、登録処理が完了すると、タスクIDが「3:ステータスをアクティブに設定」のパケットをクライアント(GhostPenguin)側に返却します(図17)。これを受け取ったGhostPenguinは、実際に内部的なクライアントステータスの値を「初期化中」から「アクティブ」に切り替え、C&Cサーバからの指示を待ち受ける体制に入ります。
GhostPenguinが用いる通信プロトコル「UDP」は、送信したデータの到着を確認、保証するものではありません。そのため本マルウェアは、実行結果などを含む通信データが消失しないように、独自の仕組みを設けています。具体的には、実行結果やファイルデータを含む全ての送信パケットについて、そのコピーをグローバルな確認待ちリスト「g_ListPacketToSend」に保存しておきます。続いて、専用のバックグラウンドスレッドが当該リストをチェックし続け、C&Cサーバから「ACK(受信確認)」の応答が得られない限り、パケットの再送を定期的に繰り返します。ACKの応答は、処理種別「3:ACK確認」のパケットとして届きます。
ACKのパケットが届くと、GhostPenguinは関数「AckPacket」を呼び出し、そのタスクID、インスタンスID、シーケンス番号をチェックした上で、該当パケットのエントリを確認待ちリストから削除します。こうした手続きにより、ネットワーク上でパケットが消失した際にも、C&Cサーバ側でのデータ受信を担保します。
登録処理の完了後、GhostPenguinは、さらに2つのスレッド「ThreadProcHeartBeat(図18)」、「ThreadProcDataSender」を起動します。 スレッド「ThreadProcHeartBeat」は、34バイトの暗号化されたハートビート用パケット(処理種別:0)を定期的にC&Cサーバに送信し、自身がオンラインであることを通知します。送信間隔は変更可能であり、デフォルト値は500ミリ秒となっています。
一方、スレッド「ThreadProcDataSender」は、定期的に先述の確認待ちリスト(g_ListPacketToSend)からパケットデータを取り出し、セッションIDを鍵として暗号化した上で、C&Cサーバに送信します。また、リトライ用のメカニズムを備えており、リトライ回数の上限に達するまで、パケットをリスト内に再格納します。なお、期限切れセッションに属する古いパケットが見つかった場合は、それを削除します。
こうしたスレッドが稼働する間、大元のメインスレッドは待機状態に入り、クライアントステータスが「アクティブ」以外に切り替わるまで、一秒間隔のスリープを繰り返します。
C&Cサーバからのパケット対応
C&Cサーバから来るパケットへの対応は、主に関数「OnReceivedPacket」を通して行われます。本関数は、C&Cサーバからパケットを受信したタイミングで、必要に応じてACK確認パケット(処理種別:3)を返します。続いて、受信した処理種別に応じて、後続の処理を振り分けます。特に処理種別が「1:新規タスク」の場合は、関数「OnReceivedPacketNewTask」を呼び出し、そこからタスクID別のswitch分岐によって適切な関数に繋げます。
こちらの表2に示すように、GhostPenguinはさまざまな種類のタスクをサポートしています。
上表の通り、ファイルやディレクトリ関連の機能はひととおり網羅されており、一覧取得、読み込み、書き込み、作成、削除、名前変更、検索、タイムスタンプ編集の全てに対応しています。なお、ファイルの読み込みやディレクトリ一覧の取得に大規模なデータ転送が必要となる場合は、UDPのペイロード上限に従い、複数パケットに分割して送信する仕組みとなっています。
図20に、C&Cサーバが送信するタスクID「20:ディレクトリ情報を取得」のパケットを、図21に、GhostPenguinが返却するパケットを示します。
GhostPenguinがタスクID「9:クライアント切断」の指示を受けた場合、C&Cサーバに確認応答を3回送信した上で、フラグ「_bIsClientExit」に「1」を設定し、自身のステータスを「CLIENT_STATUS_OFFLINE(オフライン)」に変更します。これによって大元のメインループが終了し、停止処理に移行します。この停止処理では、全スレッドをキャンセルし、リソースを解放した上で、関数「SelfDel()」を通してGhostPenguinの実行ファイルをディスクから削除します。最後に、作成済みのPIDファイルも削除した上で、プロセスを完全に停止します。
まとめ
GhostPenguinのように検知率の低いマルウェアを特定するためには、従来の検知手法に固執することなく、新手の脅威にも対処できるように、柔軟なアプローチを取り入れる必要があります。今回示したように、AIによる自動化、構造化された脅威データベース、高度なプロファイリング技術を組み合わせることで、膨大なデータの森をかき分け、全く目立たないようなマルウェアさえも、体系的に特定、分析することが可能になります。
バックドア型マルウェアに着目した本調査では、キー情報の自動抽出、詳細な逆コンパイル、階層的なAI解析を組み合わせた多段階のワークフローにより、通常ならば見逃される脅威さえも発見し、そのアーキテクチャや通信手法を解明することに成功しました。
今回のケーススタディは、マルウェアの複雑化や巧妙化に対処する上で、脅威ハンティングの戦略を刷新し続けることがいかに有効かつ重要であるかを示すものです。人間が持つ専門知識と新規のテクノロジーを融合させることにより、高度な攻撃手法にも打ち勝つことが可能です。攻撃手法が進化し続ける中、GhostPenguinのような脅威に対する強靭性(レジリエンス)を確保するためには、プロアクティブかつ高度な情報に基づく防衛戦略を取り入れることが、重要な鍵となります。
Trend Vision One™を活用したプロアクティブなセキュリティ対策
「Trend Vision One™」は、AIを駆動したエンタープライズ・サイバーセキュリティプラットフォームであり、サイバーリスク露出管理やセキュリティ運用を一元化することで、オンプレミス、ハイブリッド、マルチクラウド環境を網羅する多層かつ堅牢な防衛体制を実現します。
Trend Vision One™ Network Security
46704: UDP: Backdoor.Linux.GhostPenguin.A Runtime Detection(ランタイム検知)
トレンドマイクロによる脅威情報の活用
進化する脅威に備え、トレンドマイクロのお客様は、 「Trend Vision One™ - Threat Insights(現在プレビュー版)」にアクセスすることで、最新の脅威や攻撃グループに関するトレンドリサーチの分析をご確認いただけます。
Trend Vision Oneのアプリ「Threat Insights」
Emerging Threats: Hunting the Invisible: How utilize AI to Unmasked a "Zero-Detection" Linux Backdoor GhostPenguin(高まる脅威:「過去に未検知」のLinux型バックドア「GhostPenguin」をAIによって発見)
Trend Vision Oneのアプリ「Intelligence Reports(IOC Sweeping)」
Hunting the Invisible: How utilize AI to Unmasked a "Zero-Detection" Linux Backdoor GhostPenguin(「過去に未検知」のLinux型バックドア「GhostPenguin」をAIによって発見)
脅威ハンティングのクエリ
Trend Vision Oneのアプリ「Search」
Trend Vision Oneをご利用のお客様は、アプリ「Search」の機能を用いることで、ご利用中の環境を解析し、本稿で挙げた不正な活動の兆候を検知、照合できます。
Linux型GhostPenguinのC&Cサーバを発見するためのクエリ
eventSubId:204 AND ((dst:"65.20.72.101" AND dpt:53) OR (dst:"124.221.109.147"))
侵入の痕跡(IoC:Indicators of Compromise)
本稿に関連する侵入の痕跡はこちらで確認できます。
参考記事:
AI-Automated Threat Hunting Brings GhostPenguin Out of the Shadows
By: Aliakbar Zahravi
翻訳:清水 浩平(Platform Technology Marketing, Trend Micro™ Research)