Dexterがクレジットカード情報を盗み出す仕組み

Hong Kei Chan, ジュニア アンチウイルスアナリスト
特別技術サポート: Liang Huang, シニア アンチウイルスアナリスト

Dexterはポイントオブセール(POS)システムを標的とするカスタムマルウェアです。このマルウェアはPOSシステムのメモリ内にあるクレジットカード、デビットカードの情報をサーチする能力を備えています。POSマルウェアに関しては今年、大々的に報道されてきました。Targetのデータ侵害では約4000万のクレジットカード、デビットカード口座が侵害を受けたと報告されています(元記事)。また最近では、新たな型のPOSマルウェアにより、アメリカとカナダで4,500以上のクレジットカード情報が漏えいしました(元記事)。

これらのPOSマルウェアはいったい、どのようにしてクレジットカード情報を盗み出すのでしょうか?

今回のブログ記事ではまずDexterの主な特徴を概観し、その後に情報を盗み出すテクニックであるキーロギング、メモリパーシングについて解説しましょう。

概要

Dexterは自身のコピーのドロップ、autorunレジストリエントリの作成、コマンドアンドコントロール(C&C)サーバーとの通信など、多くの不正な機能を実行します。特筆すべき機能を以下にいくつか挙げてみました。

1) 自身のインスタンスの1つのみ実行されるようにミューテックスを作成。

  1. マルウェアプロセスが「"UpdateMutex:」というパラメータで実行されている場合、以下の形式の名前を持つミューテックスが2つ作成されます。
    • [MalwareFileName] UpdateMutex:[4-ByteKey]
    • [MalwareFileName] UpdateMutex:[4-ByteKey][RunningProcessPID]

ミューテックスの名前の最後にある4バイトのキーはC&CサーバーからのHTTPレスポンスを復号するために使用される鍵です。この復号アルゴリズムについては「フック」のセクションで話をします。

  1. 「UpdateMutex:」パラメータがコマンドラインにない場合、マルウェアはミューテックスの名前としてWindowsServiceStabilityMutexという文字列を使用します。

2) 自身のコピーをドロップし、以下のautorunレジストリエントリを作成。

  1. HKCU\Software\Microsoft\Windows\CurrentVersion\Run
     SunのJavaセキュリティプラグイン = 「%AppData%\Java Security\javaplugin.exe」

3) セキュリティレベルを低下

  1. 以下のレジストリエントリを追加し、発行元のわからない特定のファイルタイプが実行される際にWindowsのセキュリティ警報を無効化します。
    • HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Associations
       LowRiskType = 「.exe;.bat;.reg;.vbs;」
  2. アプリケーションや安全でないファイルの起動を許可する以下のInternet Explorerセキュリティゾーン レジストリエントリを追加します。
    • HKLM\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\0
       1806=0x00

Dexterは合計で5つのスレッドを作成します。これはマルウェアがクレジットカード、デビットカード情報のメモリをパースしていく間、システム内の変更を監視するためです。これらのスレッドの機能を以下にまとめてみました。

1) Autorunレジストリ モニター

  • RegNotifyChangeKeyValue APIを使用してautorunレジストリへの変更を監視します。
  • レジストリへの変更を元に戻します。

2) Internet Explorerインジェクター

  • OpenProcess、WriteProcessMemory、 CreateRemoteThreadという3つのAPIを使用し、iexplore.exeにコードを注入します。
  • マルウェアプロセスが終了させられた場合には、不正なコードがiexplore.exeに注入されるようにします。

3) アンチターミネーション モニター

  • DetectShutdownClassクラスでウィンドウを登録、作成します。
  • メッセージ識別子WM_QUERYENDSESSIONあるいはENDSESSION_LOGOFFというパラメータのどちらかを含むメッセージをウィンドウプロシージャによりフィルターにかけ、これを無視します。

4) イベントモニター

  • Dexterが作成した以下の2つのイベントオブジェクトを監視します。
     - ホストがC&Cサーバーからコマンドを受け取る。
     - アンチターミネーションモニターが終了を行うメッセージをインターセプト。

5) メモリパーサー

  • クレジットカード、デビットカード情報を探して実行中のプロセスのメモリページをサーチします。

以下のセクションでは最後のスレッドであるメモリパーサーについて解説します。

フック

Dexterはクレジットカード、デビットカード情報を求めてメモリページのパースを行う機能を持ち合わせているだけでなく、手入力されたクレジットカード、デビットカード情報をキャプチャすることもできます。これを行うためには、Dexterはユーザーのキーストロークをインターセプトし、データをファイルへ書き込むためのフックをインストールしなければなりません。

まず、リソースセクションに埋め込まれているSecureDll.dllというファイルをドロップします。このDLLにはDexterが後にセットするフックプロシージャが含まれています。

このDLLをロードすると、Dexterは以下のレジストリエントリを作成します。これらはキーストローク情報のインターセプトが行われるすべてのインスタンスの共有データとして使用されます。

  • HKCU\Software\Helper Solution Software
     val1 = C:\[CurrentFolder]\strokes.log
  • HKCU\Software\Helper Solution Software
     val2 = C:\[CurrentFolder]\tmp.log

SetWindowsHookEx APIを使用し、Dexterは2種類のフックプロシージャ、WH_KEYBOARDとWH_GETMESSAGEインストールします。最初のプロシージャはキーボード入力を監視するためのもので、2つ目のプロシージャはstrokes.logとtmp.logへデータを書き込むためのものです。

これらのフックプロシージャはどちらもGetKeyboardState APIとToAscii APIを使用してプリンタブルなキーストローク文字をログに記入するという点で非常に似ています。違いとして、WH_KEYBOARDのフックはGetKeyboardLayout、MapVirtualKeyExA、GetKeyNameTextAというAPIを使ってフォアグラウンドウィンドウのタイトルバーに表示されるテキストなどの追加的情報を、以下に挙げるノンプリンタブルの特殊文字に相当する文字列とともに、strokes.logファイルに記入することが可能となっています。

DLLの注入により、キーボード入力を監視するプロセスはSecureDll.dllをロードせざるを得なくなります。ロードされると、そのDLLMain関数が上の2つのレジストリエントリにクエリーを行い、 strokes.logとtmp.logというファイルへのパスを取得します。そのファイルパスがキーロギングされたデータが書き込まれた場所としてフックプロシージャで使用されます。

簡単に検出されることを回避するため、このデータはファイルへ書き込まれる前に暗号化されます。暗号化アルゴリズムはシンプルなルーピングXOR演算です。

鍵はGetTickCountへの呼び出しから取得し、2つのログファイルの最初の4バイトとして格納されます。

メモリパーサー

Dexterは CreateToolhelp32Snapshot、Process32First、Process32NextというAPIを使用し、実行されているプロセスのリスト内をサーチします。 Dexterは以下のリストにある16のプロセスを排除し、OpenProcess APIへの呼び出しを介してターゲットプロセスのハンドルを取得します。

Dexterは VirtualQueryEx APIを使用し、ターゲットプロセスの仮想アドレス空間のページ上にある情報を回収します。クエリーの行われた領域上にPAGE_GUARDやPAGE_NOACCESS保護がない場合、仮想メモリにそのページをダンプするためReadProcessMemory APIが呼び出されます。そして、取得したデータの処理へと移ります。

Dexterがメモリをどのようにパースするのかを解説する前に、クレジットカード、デビットカードの磁気ストライプの基本的な仕組みを理解しておくことが重要です。

磁気ストライプにはトラック1、トラック2、トラック3という3つのトラックが含まれています。トラック1とトラック2は口座番号、有効期限、CVV番号などの機密情報を格納するために金融機関が使用しています。トラック3は読み込みと書き込みに使用されます。レジ係やカード所有者がクレジットカード、デビットカードをリーダーに通すと、Electronic Data Capture(EDC)ソフトウェアがアクワイアラーへ認証リクエストを送信します。磁気ストライプのデータはISO/IEC標準に応じてフォーマットされ、認証のためにアクワイアラーへ送信されます。下の図はサンプル クレジットカードのフォーマットされたトラック1、トラック2のデータの例です。

DexterのサーチアルゴリズムはISO/IEC標準に基づいて構築されており、以下のセパレータを使用します。

  • トラック1には「^」
  • トラック2には「=」あるいは 「D」
  • トラック1、トラック2の両方に終了標識「?」

これらの文字は有効データと長さをチェックする際にパーフェクトマーカーとしての役割を果たします。以下の図に示すように、プリンタブルなASCII文字であることを確認するために各バイトがまずチェックされ、その後にフィールドセパレータであるかどうかがチェックされます。

フィールドセパレータの位置が特定されると、Dexterは以下の情報を得るために前後のバイトをチェックします。

  • 主口座番号: 15~16桁(カナダの一部銀行のカードは19桁)
  • カード所有者の名前: 2~26文字(トラック1のみ)
  • 機密情報: 最低15桁(Dexterは有効期限/DD/CVVをグループ化)

主口座番号(PAN)に関してはLuhn、つまり「係数10」アルゴリズムを使用して有効かどうか確認が行われます。このアルゴリズムは銀行カードの番号の有効性をすばやくチェックするために広く使用されているものです。有効であることが確認されると、そのデータがメモリへ書き込まれます。下の図はシミュレートされたElectronic Data Capture(EDC)ソフトウェアのメモリページから回収された、サンプルクレジットカードのトラック1、トラック2のデータです。

Dexterは現在のプロセスの次のページ上のデータのパースも引き続き行い、リスト上の次の実行プロセスへと移ります。盗み出された情報はプロセス名とともに割り当てられたメモリブロックへ加えられます。このメモリブロックはC&Cサーバーへ送信されるHTTPリクエストの一部となります。

この後Dexterは、前述の概要セクションで述べた5つ目のスレッド、メモリパーサーを作成します。ここで解説したものと同じ手法を用い、クレジットカード、デビットカード情報を求めて実行中のプロセスのメモリページのサーチを続けるためです。

HTTPリクエストの準備

DexterはInternetOpen、InternetConnect、HttpOpenRequest、HttpSendRequestAというWinINet APIを使用し、TCPポート80でHTTPを介してC&Cサーバーと通信を行います。

下の表はWinINet APIと使用されるパラメータです。

ではDexterがどのようにC&Cサーバーへ送信されるHTTPリクエストを準備するのかを簡単に見ていきましょう。

この時点で、Dexterにはキーストロークデータをログしている2つのフックプロシージャと、クレジットカード、デビットカード情報を探して実行中のプロセスの仮想アドレス空間内のページを継続的にパースするスレッドがあります。これらの盗み出されたデータをすべてC&Cサーバーへ送信する必要があります。

キーストローク ログファイルはランダムに生成されたさまざまな鍵で暗号化されているため、Dexterはまずそのコンテンツをメモリへ読み込み、復号する必要があります。メモリへ読み込まれると、tmp.logとstrokes.log は即座に削除されます。下の図は tmp.logファイルから読み込まれ、「bkut」という4文字の鍵を使って復号されたデータの例です。復号されたバイトから、2つ目のサンプルクレジットカードのトラック1のデータが明らかになりました。

上と同じパーシングアルゴリズムを使用し、クレジットカード、デビットカード番号を探すためにtmp.log から復号されたバイトに対してサーチが行われます。その情報が見つかると、このデータはメモリパーサーが使用しているのと同じ割り当てられたメモリへ加えられますが、下のように「\r\n#AVER_START#」という文字列と「\r\n#AVER_END#」という文字列でデータをカプセル化することで区別されます。

Dexterの最後のプロシージャではHTTPリクエストの本文が作成されます。上の表2のHttpSendRequestAのパラメータでわかるように、このフィールドはサーバーサイドPHPスクリプトに対して可変となっています。このフィールドは図3と同じルーピングXORアルゴリズムで暗号化されていますが、ランダムに生成された最後の4文字鍵とBase64エンコーディングが用いられています。以下の図でPOSTリクエストにより生成されたトラフィックのサンプルを見ることができます。

マルウェアコードによると合計10の変数があるようですが、実際に使用されているのは9のみです。9つのHTTPフィールド/値ペアの内容は以下の通りです。

結論

今回のレポートではDexterがどのようにPOSシステムからクレジットカード、デビットカード情報を盗み出すことができるのかを解説してきました。要するに、Dexterは実行中のプロセスのメモリダンプをパースし、2つのフックプロシージャをインストールし、盗み出した情報をC&Cサーバーへ送信するということです。

POSシステムの所有者をDexterのようなPOSを狙うカスタムマルウェアから保護するためには、2014年1月2日に発行されたUS-CERTのアラート(TA14-002A)に掲載されている成功事例(元文書)を参考にすると良いでしょう。