チェック・ポイントのリサーチ・チームは、独自の調査活動の一環として、北朝鮮の国産アンチウイルス・ソフトウェア「SiliVaccine」の解明調査を進めてきました。このソフトウェアの最大の特徴は、コードの大部分を、日本のセキュリティ企業トレンドマイクロが提供するアンチウイルス・ソフトウェアからそっくりそのままコピーしている点です。

 

背景情報

調査を開始するきっかけとなったのは、北朝鮮のテクノロジー動向を追跡するフリー・ジャーナリストMartyn Williams氏から、非常に珍しいSiliVaccineの提供を受けたことです。

Williams氏は、2014年7月8日、「Kang Yong Hak」を名乗る人物から、同ソフトウェアのダウンロード・リンクが記載された不審なメールを受け取りました。この人物のメール・アドレスはその後、不達となっています。チェック・ポイントのリサーチ・チームがこのSiliVaccineを詳しく分析したところ、興味深い事実が判明しました。

日本のエンジニアと思われる「Kang Yong Hak」氏から送られてきた奇妙な電子メールには、Dropbox上のZipファイルへのリンクが記載されていました。Zipファイルには、SiliVaccineソフトウェア、その使用方法を韓国語で説明したreadmeファイル、ソフトウェアのパッチとされる不審なファイルが含まれていました。

 

トレンドマイクロのソースコード

SiliVaccineのエンジン・ファイルに対し、チェック・ポイントのリサーチ・チームが詳細なフォレンジック分析を実施したところ、そのコードのかなりの部分がトレンドマイクロのアンチウイルス・エンジンのコードと完全に一致することが判明しました。さらに、この部分のコードは、SiliVaccineの開発者によって巧妙に隠蔽されていました。トレンドマイクロは日本の企業です。そして日本と北朝鮮の間には、正式な外交関係や政治的関係が存在しません。この2点を踏まえると、トレンドマイクロのコードが北朝鮮製のアンチウイルス・ソフトウェアに使用されているのは意外に思えます。

アンチウイルス・ソフトウェアの目的は、言うまでもなく、シグネチャが存在する既知のマルウェアをすべてブロックすることです。しかし、SiliVaccineを詳しく分析したところ、同ソフトウェアは、通常ならブロックされるべき1つのシグネチャ(実際にトレンドマイクロの検出エンジンではブロックされるシグネチャ)を見逃すように設計されていることが分かりました。このシグネチャがどのマルウェアに対応したものであるかは明らかになっていませんが、北朝鮮政府が、そのマルウェアの存在をユーザに知らせたくないと考えているのは確かでしょう。

 

バンドルされたマルウェア

また、Williams氏が受け取ったSiliVaccineには、JAKUマルウェアが含まれていることも分かりました。このマルウェアは、SiliVaccineに必須のコンポーネントではなく、Williams氏のようなジャーナリストを攻撃する目的で同梱されていた可能性があります。

JAKUは、耐障害性に優れたボットネットの構築に利用されるマルウェアで、主に不正なBitTorrentファイル共有を介して約1万9,000台のコンピュータに感染しています。また、韓国や日本の特定個人、例えば、国際的な非政府組織の職員、エンジニアリング企業の社員、学者、科学者、政府機関の職員などの攻撃、追跡にも使われています。

JAKUのファイルは、「Ningbo Gaoxinqu zhidian Electric Power Technology Co., Ltd」という組織宛に発行された証明書で署名されていましたが、同じ組織による証明書は、「Dark Hotel」という著名なAPT攻撃グループが使用していたファイルへの署名にも使われています。JAKUを使用している攻撃グループとDark Hotelのどちらも、北朝鮮の攻撃グループであると考えられています。

また興味深いことに、Dark Hotelが使用していた指令(C&C)サーバに対する以前の分析では、感染コンピュータのIPアドレスの多くが、トレンドマイクロが所有するIP範囲に含まれるアドレスであった事実が判明しています。

 

日本との関係

チェック・ポイントの調査では、SiliVaccineが日本人を名乗る人物から送られてきた点以外にも、日本との結びつきが見つかっています。

その1つが、SiliVaccineの開発元と見られる企業の中に、PGI(Pyonyang Gwangmyong Information Technology)とSTS Tech-Serviceという名前がある点です。北朝鮮の企業と思われるSTS Tech-Serviceですが、過去には、「Silver Star」や「Magnolia」など、日本に拠点を置く企業と協働していた事実が確認されています。

日本と北朝鮮の間に正式な国交はなく、両国は対立関係にあるにもかかわらず、SiliVaccineを巡っては、両国の結びつきを示す証拠が見つかっているのです。

 

まとめ

SiliVaccineに関する今回の調査は、北朝鮮のITセキュリティ製品やその事業の正当性および目的に対する疑念を引き起こす結果になるでしょう。

サイバー・セキュリティの世界では、行為の実行者を特定することは容易ではなく、チェック・ポイントの調査でもさまざまな疑問が浮上しています。1つ確実に言えるのは、SiliVaccineの開発者とその支援者の行動は不審であり、その目的も正当なものであるとは考えにくいという点です。

以降では、今回の調査で判明した技術的な詳細について解説します。

 

内容:

アーキテクチャと概要
ファイル・スキャン・エンジン
トレンドマイクロの反応
パターン・ファイル
トレンドマイクロの検出名を変換する仕組み
マルウェアのホワイトリスト登録
カーネル・ドライバ
開発元の素性
謎のパッチ・ファイル

 

アーキテクチャと概要

SiliVaccineは、アンチウイルス・ソフトウェアとして非常に古典的なアーキテクチャを採用しています。このアーキテクチャはユーザ・モードとカーネル・モードの両コンポーネントで構成されており、各コンポーネントは、静的なマルウェア・シグネチャのリポジトリ(パターン・ファイル)を照合しながらファイルやメモリのスキャンを実施するために、連携して動作します。このアーキテクチャを採用するアンチウイルス・ソフトウェアの多くは、オンデマンド・スキャンとリアルタイム・スキャンの両方に対応しており、各スキャンではそれぞれ異なるコンポーネントが使用されます。どちらのタイプのスキャンも、製品の中核部分(エンジン)に実装された単一のロジックによって実行されます。

以下の図に、SiliVaccineを構成する各ソフトウェア・コンポーネントとその相互作用の概要を示します。各コンポーネントの詳細と目的については、図の後で解説します。

図1:SiliVaccineのアーキテクチャ

 

ライブラリ

  • SVKernel.dll – ファイル・スキャン・エンジンです。SiliVaccineの中核を担うコンポーネントであり、ソフトウェアの中で最も重要な役割を果たします。ファイルを検知、解析し、各セクションを検査してマルウェアであることを示す特徴がないかどうかを調べます。検査プロセスでは、特定のマルウェア・ファミリーや個体を識別するさまざまな特徴を記述したシグネチャを使用します。シグネチャは、SVPatt00.spf~SVPatt33.spfの計34個の一連のファイルとして保存されており、実行時にスキャン・エンジンによって読み込まれます。スキャン・エンジンが備えるすべての機能は、SVFunc001~SVFunc020の20個のDLLエクスポート関数を介して公開されており、スキャン処理を実行する実行可能ファイルによって使用されます。パターン・ファイルとスキャン・エンジン自体の詳細な分析については後述します。
  • SVRegSrv.dll – インストール・パッケージに含まれるコンポーネントで、SiliVaccineの一部コンポーネントを展開、削除する役割を担います。このDLLは、DllMain以外に3つのエクスポート関数を提供します。各エクスポート関数は、以下のようにそれぞれ異なる処理を担当します。
    • RegService:SiliVaccineのMSIインストーラによって実行され、SiliVaccineのメイン・コンポーネントを有効化するために使用されます。この処理は、SVTray.exeを実行し、SVDealer.exeをサービスとして登録し、ststdi2.sysをドライバとしてロードするという手順で実行されます。このほか、隔離したファイルを保存するディレクトリの作成、スキャン・ログの生成、SiliVaccineのその他すべてのコンポーネントが使用する重要なレジストリ値(HKLM\SOFTWARE\STS Tech-Service\SVaccine以下のAppPathキーに格納されるインストール・パスなど)の作成を実施します。
    • RemoveAllComponent:過去にインストールされたすべてのコンポーネント(実行可能ファイル、DLL、隔離用ディレクトリ、スキャン・ログ、レジストリ・キーなど)を削除します。
    • UnRegService:「SiliVaccine 4.0」、「SiliVaccine 4.0 Update」、「SiliVaccine 4.0 Patch」という名称のすべてのアクティブ・ウィンドウを探し、WM_CLOSEウィンドウ・メッセージでこれらのウィンドウを閉じます。また、ウィンドウ・クラスが「SVTRAY」であるトレイ・アプリケーションを探してシャットダウンするほか、ststdi2.sysおよびSVFilter.sysドライバをアンロードし、SVDealer.exeサービスを削除します。

図2:SiliVaccineのコンテキスト・メニュー

興味深いことに、最後の2つの関数は決して呼ばれることがありません。SiliVaccineがインストールするファイルの中に、アンインストールのためのユーティリティは含まれていないからです。

  • SVShell.dll – シェル拡張として機能するCOMクラスです。SiliVaccineのコンテキスト・メニュー・ハンドラを登録するために使用されます(以下の図を参照)。このハンドラにより、特定のファイルを右クリックしてスキャンできるようになりますが、実際にはこの操作を行ってもスキャンは実施されません。

 

サービス

  • SVDealer.exe – サービスとして登録されるユーザ・モード・コンポーネントで、リアルタイム・スキャン処理を実行します。この処理を行うため、SVDealerはSVFilter.sysというファイルシステム・フィルタ・ドライバをロードします。このドライバは、各種ファイルシステム・アクティビティをインターセプトし、SVDealerに信号を送信します。SVDealerは、この信号を受けてファイル・スキャンを実行し、スキャン結果を報告します。スキャン自体は、SVKernel.dllから対応するエクスポート関数(SVFunc018)を呼び出して実行します。詳細な分析については後述します。

 

GUI コンポーネント

  • SVTray.exe – 最も重要なGUIコンポーネントです。トレイ・アイコンとして表示され、システムに常駐します。このアイコンを右クリックして表示されるメニューから、SVMain.exeやSVUpdate.exeの実行、リアルタイム保護機能の有効化/無効化を行えます。
  • SVMain.exe – ユーザがSiliVaccineを操作する際に使用するメイン・ウィンドウです。特定のファイルやディレクトリに対するオンデマンド・スキャン、ファイルのホワイトリスト設定の変更、アップデート・スケジュールの設定を行う場合に使用します。SVUpdate.exeユーティリティを開くこともできます。
  • SVUpdate.exe –北朝鮮国内のイントラネット・サーバに接続するアップデート・ユーティリティです。新しい実行可能ファイルやパターン・ファイルが公開されていないかどうかをチェックします。 接続先のサーバは、ハードコードされた10.10.1.16/10.250.2.33を使用することも、SVMainコンポーネントで手動設定することもできます。SiliVaccineとアップデート・サーバ間の通信はHTTPで行われますが、以下の図に示すように、HTTPヘッダには、一般的に使用される「User Agent」フィールドに加えて「User-Dealer」という独自のフィールドが追加されています。

図5:アップデート・リクエストのHTTPヘッダに追加されている独自フィールド

サーバから受信したアップデート・ファイルに対しては、SVDiffUpd.exeという独自の差分チェック・ツールによる完全性の検証が行われます。

 

名前付きパイプ

  • CommWithMainPipe – SVMainのプロセスIDをSVDealerに渡すために使用されます。SVDealerは、そのプロセスIDをIOCTL経由でSVFilterドライバに渡します。SVFilterドライバはこのIDを、SVDealerのプロセスIDとともにグローバル変数として登録します。システム上のファイルへのアクセスが発生した場合、SVFilterドライバは、関連するプロセスのIDをチェックし、そのIDがSiliVaccineのコンポーネント(SVMainまたはSVDealer)のIDと一致した場合、アクセスを許可します。
  • CommWithTrayPipe – 新たに接続されたリムーバブル・メディアをトレイ・アプリケーションに通知するために使用されます。SVDealerは、GetLogicalDrives関数を使用して、現在利用可能なドライブのビットマスクを生成し、その変更を監視します。変更が検出された場合、SVDealerは、IOCTLを発行してファイルシステム・フィルタ・ドライバを新しいドライブに関連付け、RemovableMediaInsertEventというグローバル・イベントが通知されるように設定します。さらに、名前付きパイプ経由で、ドライブ・インデックスをビットマスクとしてSVTrayに渡します。パイプ・データを無期限に監視するSVTrayは、MemoryScanEventというグローバル・イベントが通知されるように設定し、新しいドライブ・インデックスのビットマスクを「SVTRAY」ウィンドウへのウィンドウ・メッセージとして発行します。

 

ドライバ

  • SVFilter.sys – リアルタイム保護サービス(SVDealer.exe)と通信するファイルシステム・フィルタ・ドライバです。ファイルシステムに対する一部のアクションはインターセプトされ、SVDealer.exeに制御が渡されて事前スキャンが行われます。スキャン結果に基づいて、そのアクションを許可するかどうかが決定されます。
  • SVHook.sys – メモリ・スキャン時にSVMainと相互作用するドライバです。メモリ・スキャンの際、SVHook.sysは、カーネル・モードでしかアクセスできないスキャン対象プロセスについてのさまざまな詳細情報を提供します。
  • ststdi2.sys – システムのTDIクライアントが送信したすべてのTCPパケットをインターセプトするTDIドライバです。このドライバは、すべての接続をデータ構造に記録します。このため別のエンティティは、IOCTL経由でこのデータ構造を照会することができます。

ここで注目する必要があるのは、上述したコンポーネントの一部(SVKernel、SVDealer、すべてのGUIコンポーネント)は、広く使用されているパッカーのThemidaとUnopixで保護されているという点です。商用ソフトウェアでThemidaを使用するのはごく一般的な行為ですが、SiliVaccineの場合は少々奇異に映ります。Themidaを使用する目的は、強固なリバース・エンジニアリング対策を実施して、著作権の侵害を困難にすることです。しかしSiliVaccineの場合、北朝鮮の国内市場にはライバル企業が存在しません。そのようなソフトウェアを強力なパッカーで保護する必要は果たしてあるのでしょうか?Themidaを使用している理由については、次の項で推測します。

 

ファイル・スキャン・エンジン

SiliVaccineを構成する中核的な要素の1つがスキャン・エンジンです。スキャン・エンジンの実体はSVKernel.dllという名前のDLLで、ファイルやプロセス・メモリに対し、不正な活動を行うかどうかを判別するための検査を実施します。ファイルに対するスキャンでは、シグネチャのリポジトリ(パターン・ファイル)に基づいて検査を実施し、不正なコードが見つかった場合は、対応するシグネチャ名で検出を報告します。スキャン・エンジンは、SiliVaccineの中で特に重要なコンポーネントであり、スキャンの実施を要請する他のユーティリティによってロードされます。

前のセクションで述べたように、スキャン・エンジンのバイナリ(およびその他の一部バイナリ)は、Themida 2.xとUnopix 0.94でパックされています。ThemidaとUnopixはどちらも、コードの一部を仮想化し、リバース・エンジニアリングを困難にする強力なソフトウェア保護ツールです。両ツールを使用した場合、インストールされたバイナリの分析はかなり難しくなりますが、SiliVaccineの場合、コードのほとんどは仮想化されておらず、保護機能もごく一部しか使用されていなかったため、チェック・ポイントのリサーチ・チームはSiliVaccineを解凍することができました。

解凍したバイナリを分析したところ、インターネットで入手したvsapi32.dllというファイルと同じ文字列が含まれていることが分かりました。このファイルは、幅広いアンチウイルス・ソリューションを提供する日本のサイバー・セキュリティ企業トレンドマイクロが開発したファイル・スキャン・エンジンです。このエンジンの目的は、SiliVaccineのスキャン・エンジンの目的とまったく同じであり、見たところ両者はかなり似通っています。

2つのファイルがどれくらい似ているかを検証するため、バイナリの差分分析を実施してみました。すると驚いたことに、コードのかなりの部分が共通であることが判明したのです。「関数のハッシュや擬似コードが同じ」などの厳格な基準で比較しても、実に1,691個の関数が完全に一致していました。この差分分析結果の抜粋を以下の図に示します。

図6:SVKernel.dllとvsapi32.dllのバイナリ差分分析の結果

またこの図からは、SVKernelの一部エクスポート関数が、vsapi32によってエクスポートされる関数と完全に一致していることが分かります。SVKernelの少なくとも17個のエクスポート関数が、vsapi32のエクスポート関数とまったく同じであるか、そのラッパー関数であることが確認されています。リサーチ・チームが確認した両ファイルのエクスポート関数の対応関係と、SiliVaccineだけに存在するごく少数の関数を以下の表に示します。

SiliVaccineの関数 トレンドマイクロの関数 説明
SVFunc001 VSRemoveVirusW ウイルス感染ファイルを一時フォルダにコピーし、ファイル形式を維持しながらウイルスの駆除を試みます。
SVFunc002 VSDecompressFile 圧縮ファイルを展開します。
SVFunc003 VSGetPatternPath パターン・ファイルのパスを スキャン設定構造体 に設定します。
SVFunc004 VSGetVSCInfo 内部設定構造体 に基づいて スキャン情報構造体 を初期化します。
SVFunc005 VSInit スキャン設定構造体のサブ構造体とフィールドを初期化します。
SVFunc006 VSQuit スキャン処理の完了時にファイルやメモリに対する各種の駆除処理を実行します。
SVFunc007 VSReadPatternInFile パターン・ファイルのオフセットから特定のパターンを取得します。
SVFunc008 VSSetCharacterEnvType スキャンの実行中に使用する文字エンコーディングを記述した グローバル変数 を設定します(ログ・ファイルの書き込みなどで使用します)。
SVFunc009 VSSetConfFlag スキャン設定構造体の1つのフラグを更新します。
SVFunc010 VSSetConfig スキャン設定構造体の複数のフラグを更新します。
SVFunc011 不明 不明
SVFunc012 特定の引数を設定してVSSetConfFlagを呼び出します。 -
SVFunc013 VSSetLogFilePath スキャン・ログ・ファイルのパスをスキャン設定構造体に設定します。
SVFunc014 特定の引数を設定してVSSetConfFlagを呼び出します。 -
SVFunc015 特定の引数を設定してVSSetConfFlagを呼び出します。 -
SVFunc016 VSSetProcessFileCallBackFunc スキャンの完了時に呼び出されるコールバック関数を設定します。コールバック・アドレスは引数として渡され、スキャン設定構造体に設定されます。
SVFunc017 特定の引数を設定してVSSetConfFlagを呼び出します。 -
SVFunc018 VSVirusScanFileW 引数で渡された特定のファイル名に対するスキャン処理を初期化します。
SVFunc019(SiliVaccineの独自関数) - .spfファイルをベースとするパターン・ファイルを読み込み、復号化します。
SVFunc020(SiliVaccineの独自関数) - パターン・ファイル・ハンドルのマッピングを解除して閉じます。

 

以下の図は、主要なエクスポート関数を構成するコードの類似性を示しています。最初のコードは、スキャン処理に必要な全パラメータを設定する関数のコードです。2つの関数のロジックは実質的に同じですが、使用している内部データ構造に、対応する構造体の割り当てサイズが異なるなどの相違点が見られます。この違いは、SiliVaccineでのエンジン実装に合わせて、構造体に若干の調整が加えられた可能性を示唆しています。

図7:SVKernel.dllとvsapi32.dllのウイルス・スキャン関数の比較

次に比較するのは、スキャン処理全体を通じて使用される内部設定構造体の各フィールドを初期化する関数です。ここで更新されているフィールドは、このスキャン処理のログ・ファイルに付与されるIDに対応したフィールドです。両者の関数には、ある大きな違いが見て取れます。SiliVaccineの関数では、memset関数とmemcpy関数をインラインで呼び出しているのに対し、トレンドマイクロのエンジンでは、libcの関数を呼び出している点です。関数のインライン化はコードの複数の箇所で行われていることから、SiliVaccineの開発者は、元のエンジンでは使用されていない最適化機能を使用してトレンドマイクロのソースコードを再コンパイルした可能性があります。

図8:SVKernel.dllとvsapi32.dllのデータ構造の初期化関数の比較

これとよく似たパターンが、内部スキャン情報構造体を初期化するSVFunc004関数に見られます。ここでも関数のインライン化が行われていますが、対象となっているのはmemcpy関数とstrcpy関数です。そして何より目を引くのは、構造体に格納されるデータです。あるフィールドには、バイナリにハードコードされたスキャン・エンジンのバージョン情報が格納されるのです。このバージョン情報から、SiliVaccineの開発者が使用したトレンドマイクロのエンジンは、バージョン8.910-1002であると推測されます。このバージョンについての情報はインターネットでも見つけることができますが、その数は非常に少なく、後継バージョン(8.95)や先代バージョン(8.87)の情報よりも入手が困難です。またバージョン8.910-1002は、2008年8月にリリースされていることが判明しています。今回チェック・ポイントのリサーチ・チームが検証しているSiliVaccineが2013年にリリースされたバージョンである点を踏まえると、当時でも非常に古いエンジンが利用されていたことになります。

図9:SVKernel.dllとvsapi32.dllのスキャン情報構造体の初期化関数の比較

最後に見ていくのは、ファイルやメモリに残るウイルスの痕跡を削除するSVFunc006のスキャン・クリーンアップ関数です。この関数にも、トレンドマイクロのコードが再コンパイルされているという推測を裏付ける証拠が見つかっています。同関数のSVKernel版を分析すると、SiliVaccineのレガシー・ドライバSVIO.sysをアンロード、クリーンアップするネイティブ関数を呼び出していることが分かります。しかしこのドライバは本バージョンのSiliVaccineには存在せず、vsapi32ともトレンドマイクロとも関係がありません。トレンドマイクロの関数にこのような呼び出しが入り込むのは、対応するソースコードに手を加えたことが原因であると考えられます。

図10:SVKernel.dllとvsapi32.dllのスキャン情報構造体の初期化関数の比較

 

トレンドマイクロの反応

チェック・ポイントは、トレンドマイクロに連絡を取り、同社の検出エンジンがSiliVaccineで盗用されていることを伝えました。同社は、チェック・ポイントの問い合わせに速やかに対応し、次のような回答を寄せてくださっています。

「北朝鮮製アンチウイルス製品『SiliVaccine』に関する貴社の調査を確認いたしました。同製品には、弊社製品で広く使用されているTrend Micro VSAPI検査エンジンの10年以上前のバージョンを元にしたモジュールが組み込まれていると考えられます。トレンドマイクロは、北朝鮮国内、および北朝鮮の組織とこれまで一切取引を行っておらず、SiliVaccineにおける弊社技術の使用は、完全に無許可で行われていると確信しています。問題のVSAPIは非常に古いバージョンであり、弊社とOEM契約を結んだセキュリティ・ベンダー各社の製品で広く使用されています。そのため、SiliVaccineの開発元がどのような手段でこの技術を入手したのかは定かではありません。トレンドマイクロは、ソフトウェアの著作権侵害行為に対して厳しく対処する考えですが、今回の不法行為が弊社のユーザに具体的なリスクをもたらすことはないと考えています」

SiliVaccineが10年以上前の古いVSAPI検査エンジンを使用している背景には、不正なOEMが関係している可能性があるというトレンドマイクロの指摘は、チェック・ポイントのリサーチ・チームが実施した、SiliVaccineの旧バージョンに対する追加の分析でも裏付けられています。今回の問題は、単発的な出来事では済まない可能性があります。

 

パターン・ファイル

SiliVaccineのマルウェア・シグネチャは、パターン・ファイルと呼ばれる一連のファイルに保存されます。このパターン・ファイルを詳細に分析すると、その実体がトレンドマイクロのパターン・ファイル(lpt$vpnファイル)であり、暗号化され、2MBのデータに分割されていることが分かります。SiliVaccineがトレンドマイクロのスキャン・エンジンを使用している事実を考えれば、これは当然といえるでしょう。

図11:SiliVaccineが使用するシグネチャ・リポジトリを構成するファイル(パターン・ファイル)の一覧

パターン・ファイルは、多少の改変を加えたSHA1ハッシング・アルゴリズムをベースにした、独自開発と思われる暗号化プロトコルで暗号化されています。この暗号化アルゴリズムを解読するのは非常に困難ですが、実際にはその必要はありません。以下の図に示すように、復号化後のパターン・ファイルをメモリから簡単にダンプできるからです。

図12:復号化されたパターン・ファイルを含むメモリ・ダンプの抜粋

復号化プロセスに関して特に興味深いのは復号鍵です。

一見すると、この復号鍵は、英語アルファベットのランダムな組み合わせで構成されているように見えます。しかし、入力言語を韓国語に設定した韓国語/英語キーボードでこの文字列を入力すると、「Pattern encryption」という英語に直訳される韓国語のフレーズになるのです。

SVKernelによってエクスポートされる関数SVFunc019は、パターン・ファイルの読み込み、復号化、解析を実施します。各ファイルを読み込んで復号化した後、その内容を、復号化したバッファ全体が格納されるグローバル・バッファに追記します。

図13:パターン・ファイルの読み込みと復号化を実施するコード

SVMainとSVDealerは、パターン・ファイルをロードして復号化するために独自関数のSVFunc019を呼び出します。その後、トレンドマイクロのコード(SVFunc007 - VSReadPatternInFile)を使用して、シグネチャ自体を解析し、ロードします。

 

トレンドマイクロの検出名を変換する仕組み

前述のように、SiliVaccineでは、トレンドマイクロのパターン・ファイルを使用しますが、このファイルにはトレンドマイクロのシグネチャ名が含まれています。しかし、このシグネチャ名がエンドユーザの目に触れることはありません。SiliVaccineは、検出したマルウェア名を内部で変更、つまりトレンドマイクロにおける検出名をSiliVaccine独自の検出名に変換するからです。この変換処理は、SVMainおよびSVDealerの専用の関数によって実行されます。これらの関数は、SVKernelのエクスポート関数SVFunc016(VSSetProcessFileCallBackFunc)の呼び出しによってコールバックとして設定され、ファイル・スキャンの実行直後に実行されます。スキャン時にマルウェアが検出された場合は、対応する検出名がパターン・ファイルから取得され、以下に示す手順でSiliVaccine独自の検出名に変換されます。プログラム内で使われるのは変換後の検出名のみとなります(詳細については、「マルウェアのホワイトリスト登録」を参照してください)。

検出名の変換処理は以下のように行われます。

  • 1. 区切り文字「-」、「_」、「.」を切れ目にして、パターン・ファイルの検出名(SVKernelによるスキャンで報告された検出名)を分割します。
  • 2. 一般的にマルウェアのタイプやカテゴリを示す先頭部分(接頭辞)は、以下の表のとおりに置換されます。
トレンドマイクロの接頭辞 SiliVaccineの接頭辞
PE W32
WORM Wrm
BKDR Bkd
Cryp Crp
TROJ Trj
TSPY Spy
Possible Poss
Html Htm

これ以外の接頭辞はそのまま使用されます。接頭辞を置換するコードを以下の図に示します。

図14:検出名の接頭辞を置換するコード

  • 3. 検出名が3つ以上の要素で構成されている場合、末尾部分(接尾辞)は以下の表のとおりに置換されます。
トレンドマイクロの接頭辞 SiliVaccineの接頭辞
‘0’ – ‘9’ ‘A’ – ‘J’
‘O’ ‘Org’
その他 16進数に変換
  • 4. 検出名が4つ以上の要素で構成されている場合、接尾辞の直前の要素は16進数に変換した文字列に置換されます。
  • 5. 各要素の先頭文字は大文字に変換され、それ以外の文字は小文字に変換されます。
  • 6. 変換後の名前は、すべての要素がドット(.)で連結されます。

図15:変換後の検出名を作成するコード

トレンドマイクロにおける検出名とSiliVaccineにおける検出名の変換例を以下の表に示します。

トレンドマイクロにおける検出名 SiliVaccineにおける検出名
PRIMUS.512-O Primus.512.Org
TROJ_STEAL1 Trj.Steal1
MAL_NUCRP-5 Mal.Nucrp.F

 

マルウェアのホワイトリスト登録

SiliVaccineでは、ある1つのマルウェア・シグネチャをホワイトリストに登録し、このシグネチャに合致するファイルを一切検出しないようにしています。ホワイトリストに登録されているのは、トレンドマイクロの「MAL_NUCRP-5」というシグネチャです。このシグネチャは、同社Webサイトでは以下のように説明されています。

「…既知のマルウェアであるNUWAR、TIBS、ZHELATの亜種と同様の振る舞いや特性を示した不審なファイルを指す検出名です」

このシグネチャは、特定のマルウェアを検出するためのシグネチャではなく、一部マルウェアに見られるパッキング関連の特徴の検出を目的としていると考えられます。接頭辞「MAL」は、このシグネチャが汎用であることを示しています(トレンドマイクロの説明によると「第2レベルの汎用検出名」)。つまり、複数の既存マルウェアに共通のパターンに基づいて作成されたヒューリスティック・シグネチャであるということです。MAL_NUCRP-5として検出される20種類ほどのファイルを見てみると、偽のアンチウイルス・インストーラから、中国のAPT攻撃グループに関係していると思われるドロッパー・コンポーネントに至るまで、互いに関わりのない多様なマルウェアが対象になっていることが分かります。

ホワイトリスト機能は、プログラム自体のバイナリ・コンポーネントにハードコードされており、この目的のために追加された専用のコードによる暗黙的な比較によって処理されます。これは、対象のシグネチャを完全に削除するのと実質的に同じですが、シグネチャ自体はSiliVaccineに同梱のパターン・ファイルに依然として残されています。この事実からは、SiliVaccineの開発元が「トレンドマイクロのパターン・ファイルに直接手を加える手段を持っていない」、または「パターン・ファイルが更新されるたびにシグネチャを削除する手間を避けた」という可能性が考えられます。

さらに詳しく分析すると、このホワイトリスト機能は、SiliVaccineの主要コンポーネントであるSVMainとSVDealer、つまりSVKernelによるファイル・スキャンを開始する2つのコンポーネントによって実装されていることが分かりました。コード中の複数の場所で、エクスポート関数SVFunc018(VSVirusScanFileW)を呼び出した直後に、直前のスキャンでの検出名を格納するグローバル文字列と「Mal.Nucrp.F」という文字列との比較が行われています。「Mal.Nucrp.F」は、トレンドマイクロにおける検出名「MAL_NUCRP-5」に対応するSiliVaccineの検出名です。検出名が「Mal.Nucrp.F」と一致した場合は、それを完全に無視して、スキャンでは何も見つからなかったかのように処理を続行します。


図16および17:ファイル・スキャン後に行われる検出名「Mal.Nucrp.F」との比較

図18:ホワイトリスト処理で検出名「Mal.Nucrp.F」と比較する処理に見つかった入力ミス

ただし、このミスはホワイトリスト機能の効果には影響しません。スキャン処理が行われるたびに暗黙的な比較が追加で実施されるからです。

興味深いのは、同じような名前のシグネチャ(「MAL_NUCRP-*」)がホワイトリストに一切含まれていない点です。トレンドマイクロ製品で、「MAL_NUCRP-2」(一意のファイル1個)、「MAL_NUCRP-5」(一意のファイル8個)、「MAL_NUCRP-6」(一意のファイル3個)として検出されるファイル群をSiliVaccineでスキャンすると、以下のような結果になります。

図19:MAL_NUCRP-2とMAL_NUCRP-6は検出されるがMAL_NUCRP-5は検出されない

「Mal.Nucrp.F」として検出されるはずのファイルは一切検出されず、Mal.Nucrp.CおよびMal.Nucrp.Gとして検出されるはずのファイルはすべて正しく検出されています。

 

カーネル・ドライバ

SiliVaccineでは、以下の3つのドライバ・コンポーネントが使用されています。

  • SVHook.sys – カーネル・モード・プロセスの情報を収集するモジュール
  • SVFilter.sys – リアルタイム保護とSiliVaccineの関連ファイルの保護で使用されるファイルシステム・フィルタ・ドライバ
  • ststdi2.sys – ネットワーク・トランスポート・ドライバ・インタフェース(TDI)ドライバ

 

保護メカニズム

SVHookドライバとSVFilterドライバはどちらも、Detect It Easyで「BobCrypt2 protector」と検出される奇妙なパッカーでパックされています。ほとんど名前の知られていないパッカーであり、実際には「プロテクター」などと呼べる代物ではないことから、Detect It Easyの判定は誤検出であるように思えます。このパッカーが行っているのは、バイト0x42をキーにして.textセクションのXORを取る単純な処理であり、次の図に示すように簡単に特定することができます。

図20:t0x42をキーにした単純なXORによる.textセクションの暗号化

バイナリのエントリポイントは、パッカーのコードを格納した「.reloc」セクションにあります。

 

SVFilter

SVFilter.sysコンポーネントは、主に以下の2つの目的で使用されるファイルシステム・フィルタ・ドライバです。

  • 1. リアルタイム保護機能 – ユーザ・モード・コンポーネントのSVDealerと連携してこの機能を提供します。
  • 2. SiliVaccineのバイナリ・コンポーネントを削除や改変から保護します。

 

リアルタイム保護

リアルタイム保護機能は、SVDealerによって実装されています。SVDealerはSVFilterドライバを使用してファイルシステム・アクティビティをフックし、アクセスが発生しているファイルをリアルタイムでスキャンします。SVFilterはSVDealerによってロードされ、SVDealerはIOCTL経由でSVFilterに対する通信と制御を実施します。SVDealerはSVFilterに対し、自身を既存のすべてのファイルシステム・ドライバ・スタックにアタッチするよう指示した後、SVFilterからのスキャン信号を待機します。スキャン信号を受け取ったSVDealerは、別のIOCTLを通じてスキャンする必要のあるファイル・パスを読み取り、スキャンを実施して、そのファイルが不正であったか(ホワイトリストに登録されていなかったか)をSVFilterに報告します。SVDealer側から見たこの機能のコードを以下に示します。

図21:SVFilterからの信号を受けたSVDealerによるスキャン(SVDealer側から見たリアルタイム保護機能)

SVFilter側の照合機能は、長大で複雑な関数の奥深くに記述されています。この関数を分析したところ、長大さや複雑さに必然性はなく、その裏側では前述した各種機能が雑然と実行されているだけという事実が判明しました。重複する不可解なチェック処理の後でようやく、リアルタイム・スキャンが実施されます。このリアルタイム・スキャンは、ファイルの実行時にのみ実施されます。このコードは、ファイルが実行のために開かれているのかどうかをチェックし、そうである場合はファイル・パスを格納して、ファイルのスキャンが必要であることをSVDealerに通知します。その後、SVDealerから報告された結果をチェックします。ファイルが不正であった場合は、ファイル名をリストに格納し、そのファイルへのアクセスをブロックします(意味のある用途では使用されていないため、リストの目的は不明です)。この機能のコードを以下に示します。

図22:ファイルの実行をSVDealerに通知し、スキャン結果を受け取って処理
(SVFilter側から見たリアルタイム保護機能)

 

内部コンポーネントの保護

SVFilterのフィルタ機能は、ディスクに保存されたSiliVaccineのバイナリ・ファイルを書き込みアクセスから保護するという役割も担っています。このチェックを実行するコード・セグメントを以下に示します。

図23:ディスク上のSiliVaccine関連ファイルを書き込みアクセスから保護するSVFilterの機能

 

SVHook

SVHookドライバは、風変わりで少し分かりにくいコンポーネントです。名前からは、カーネル・モードのフックに使用されるような印象を受けますが、そのような機能は一切備えていません。実際には、SiliVaccineがシステムのメモリ・スキャンを実行する際、カーネルに対しWindowsのオブジェクト・メタデータを照会する目的でSVMainによってロード、利用されます。実質的には、カーネルからしかアクセスできない情報を照会するカーネル・モードのエージェントとして機能します。

このコンポーネントに関して特に興味深いのは、コードに残されたデバッグ文字列です。SVHookのある関数には、DbgPrintの呼び出しが複数記述されています。この呼び出しは、関数の状態を記述しつつ、関数自体を「sub_800754」と参照しています。

図24:SVHookのバイナリに含まれる奇妙なデバッグ文字列

これはおそらく、リバース・エンジニアリング・ツールのIDAによって自動生成された名称です。つまり、この関数は、リバース・エンジニアリング元となった別のドライバからコピーされた可能性があります。この関数自体は、ユーザ・モード・プロセスからハンドルを受け取り、一致するオブジェクト名を返すのが役割と考えられます。

もう1つ目を引くのは、ドライバが13種類のIOCTLコマンドをサポートしているにもかかわらず、ユーザ・モード・コンポーネント(SVMain)によって呼び出されるのは3種類に過ぎない点です。また、このドライバには複数のバグやミスが含まれているようですが、これは、ドライバの開発がその目的を深く理解しないまま急ごしらえで行われた可能性を示唆しています。例えば、実際に使用されているあるIOCTLは、条件文に次のようなミスがあるため、常に失敗します。以下の図に示すように、SVMainによってIOCTLで送られる入力バッファ・サイズは12バイトに設定されています(これが正しいサイズです)。

しかし、SiliVaccineの開発者は、SVHookの入力サイズを検証する際の条件と混同しているのか、サイズが正しい場合にステータス・コードSTATUS_INVALID_PARAMETERを返しています。

図25および26:SVHookで0x83350004 IOCTLを処理する際のバッファ長チェックに見られるプログラミング・ミス

 

STSTDI

SiliVaccineの各コンポーネントの中で、最後に確認できたドライバがststdi2.sysです。このドライバはTDI(トランスポート・ドライバ・インタフェース)フィルタ・ドライバで、TCP接続をインターセプトし、内部データ構造に記録するために使用されます。この処理は、同ドライバに対応するデバイスをシステムのTCPデバイスにアタッチさせ、上位レベルのカーネルTCPクライアント(TDI APIを使用してTDIトランスポート・ドライバと通信するHTTP.sysなど)からのIRPをインターセプトするという方法で行われます。

DriverEntryには、3つのディスパッチ関数があります。1つ目は、IRPをTCPドライバに渡し、ほとんどの場合にTDIドライバを透過的に使用できるようにするためのデフォルト関数です。2つ目は、接続の作成と終了に関するイベントをインターセプトするIRP_MJ_CREATE、IRP_MJ_CLEANUP、およびIRP_MJ_CLOSEを処理するディスパッチ関数です。3つ目は、IRP_MJ_DEVICE_CONTROLまたはIRP_MJ_INTERNAL_DEVICE_CONTROLのために、渡された特定のIOCTLを処理するドライバです。

図27:STSTDIのDriverEntry関数(メインのディスパッチ・ルーチンとTCPデバイスへのアタッチ部分)

接続を処理するディスパッチ関数は、接続をハッシュ・テーブルに記録しようと試みます。このハッシュ・テーブルには、ある時点でアクティブなすべての接続が記録されます。以下の図では、接続を作成するIRP_MJ_CREATEで、このIRPに関連付けられたシステム・バッファの検査が行われています。また、接続アドレスまたはコンテキストがハッシュ・テーブルに追記されたかどうかを確認しています。同様に、接続を終了するIRP_MJ_CLOSEのインターセプト時には、ハッシュ・テーブル上の対応する接続データが特定され、削除されます。

図28:STSTDIによる、インターセプトしたパケットの処理

ハッシュ・テーブルに記録されたデータを使用するため、ststdi2.sysは、一連のIOCTLを処理するハンドラを備えています。これにより、外部のエンティティ(別のドライバやユーザ空間コンポーネントなど)がハッシュ・テーブルに対し照会や変更操作を行うことが可能となっています。しかし奇妙なことに、SiliVaccineには、これらのIOCTLを発行するコンポーネントは他に存在していません。そのためこのドライバは、無意味な存在であるように見えます。このような現象が起きている理由としては、これがレガシー・コンポーネント、つまり使用されなくなってからもソフトウェアに残されたままになっているコンポーネントである可能性が考えられます。

 

開発元の素性

ここまで、SiliVaccineを構成する各種コンポーネントの技術的な側面を見てきました。このほか、ファイルのメタデータから、いくつかの興味深い事実も判明しています。例えば、PEコンポーネントのリソース・セクションに記載されたバージョン情報(ファイルを解凍した状態でなければ確認できない情報)に目を向けると、PGI(Pyonyang Gwangmyong Information Technology)とSTS Tech-Serviceという2つの会社名を確認できます。

図29:SiliVaccineのバイナリのバージョン情報に記載された会社名

「Gwangmyong」(おそらくは北朝鮮の国内イントラネットを指す「Kwangmyong」のスペルミス)という名称から、PGIは北朝鮮の企業であると推測されますが、STS Tech-Serviceの方はそうした手がかりがなく、いまだ謎に包まれています。この組織のWebサイトは存在せず、その活動状況を示す明確な情報もインターネット上には見当たりません。素性や事業内容ははっきりしないままです。

若干の手がかりはWebで見つけることができたものの、前述の疑問に対する明確な答えを得るには至らず、さらなる調査が求められます。見つかった数少ない情報の1つとしては、Silver Star JapanMagnoliaという2社と共に、複数の日本製アプリケーションの共同開発元として名前が記載されているという事実が挙げられます。同社の名前があった麻雀ゲームやファイル暗号化ユーティリティの「アイアンセキュリティ」は、これらの企業が日本市場向けに開発した正規のアプリケーションであるようです。この事実は、STS Tech-Serviceが日本の企業であることを意味しているのでしょうか?


図30:STS Tech-Serviceが日本の企業と共同開発したとされるアプリケーションの例

さらに詳しい調査を進めたところ、同社が日本企業ではないことを示す証拠が見つかりました。2006年に北朝鮮で開催された「Pyongyang International Technology and Infrastructure Exhibition(平壌国際テクノロジー・インフラストラクチャ展覧会)」というイベントの招待案内に、STS Tech-Serviceが参加企業の1社として名を連ねていたのです。このイベントの元々の目的は、北朝鮮企業と世界各国の企業との提携を促進することです。案内には、世界各地の企業が多数掲載されていますが、イベント主催者の情報によると、STS Tech-Serviceは、北朝鮮国内に拠点を置いているようです。

図31:2006年に北朝鮮で開催された展覧会への招待状。STS Tech-Serviceが参加企業の一覧に名を連ねている。

 

謎のパッチ・ファイル

すでに述べたように、チェック・ポイントが入手したSiliVaccineのインストール・ファイルは、フリー・ジャーナリストのMartyn Williams氏から送られてきたものです。Williams氏自身は、日本人の名前を名乗る謎の人物のメール・アカウントからそのファイルを受け取りました。

インストーラのファイル名は「SiliVaccine4.0_2014_07_08.exe」であり、2014年7月8日にビルドされたバージョン4.0のファイルであることを示唆しています。しかし、インストーラ・ファイルを分析したところ、その実体はWinRAR SFXアーカイブであり、中にはこの日付よりも古いインストーラとパッチとされるファイルが含まれていることが分かりました。

図32:チェック・ポイントが受け取ったインストーラ・ファイルの中身

図33:JAKUの署名に使用されていた証明書

SFXアーカイブを実行すると、その中の2つのファイルが自動的に実行されます。アーカイブ内の古いインストーラ・ファイルは、SiliVaccineの正規のインストーラです。しかし、パッチとされるファイルを詳しく分析すると、パッチではなく、巧妙に偽装されたJAKUマルウェア(攻撃の第1段階で使用されるドロッパー)であることが判明しました。

興味深いのは、このファイルの署名に使用されていた証明書が、ある証明書と非常によく似ている点です。ある証明書とは、APT攻撃グループDarkHotelの攻撃キャンペーンで使用されていたとされる証明書です。この結びつきには合点がいきます。なぜなら、JAKUの攻撃レポートによると、JAKUとDarkHotelの間には「明確な関連性」があり、2つの攻撃の実行者は同じである可能性が示唆されているからです。また、Kasperskyが公開したDarkHotelのレポートでは、この攻撃の実行者は証明書の窃取に関与しているとされています。さらに興味深いことに、2つの攻撃キャンペーンは、どちらも北朝鮮の攻撃グループによるものであると考えられています。

図34:DarkHotelの攻撃キャンペーンで使用されていた、窃取された証明書(KasperskyのDarkHotelレポートより)

関連記事:北朝鮮製アンチウイルス・ソフトウェア「SiliVaccine」に関する特別レポート