2019年9月15日

プロセスインジェクションとマニピュレーション マルウェアの回避テクニック 第 1 回 :

Malware developers are perpetually on the look-out for new techniques that will enable their malicious files of "destruction and chaos" to stay undete

マルウェアの開発者 は、「破壊と混乱」をもたらす悪意のあるファイルを検知されないようにするために、常に新しい技術を探し求めています。これは、感染したマシン上で検出されないことだけでなく、より重要なことは、検出ツールから悪意のある指標や動作を隠すことを意味します。このため、マルウェアの開発者は、最新の回避技術を駆使して、自動脅威分析システムや検知・応答ツールから悪意のあるファイルを隠せるような技術を発見するために、多くの時間とリソースを費やしています。

ソリューションプロバイダが最新の回避技術に気づくと、マルウェア開発者は調整を余儀なくされ、さらに巧妙な技術を駆使して、永遠のいたちごっこを続けることになります。Deep Instinctのブログシリーズ「マルウェアの回避テクニック」では、このような一連の動きを振り返り、このテーマについてもっと知りたいという方のために、基本的な概要をご紹介します。

はじめに

多くの場合、マルウェアは検知を回避するために、悪意のあるコードを実行するためのプロセス操作、特にプロセスインジェクションを含む様々な回避技術を利用します。マルウェアが感染したマシン上で実行されている場合、そのプロセスは アナリストやセキュリティプログラムによって容易に検出することができます。実行中のプロセスのリストを確認し、オペレーティングシステムの一部であったり、インストールされたアプリケーションに属していたりする期待されるプロセスを除外するだけです。感染したシステム上に隠れるために、マルウェアは疑われることなく正規のプロセス内に悪意のあるペイロードをロードすることができます。

プロセスインジェクションと操作は、ステルス性が高く、サイバーセキュリティのアナリストとソリューションの両方を回避することができるため、攻撃者が使用する顕著な手法です。攻撃者は、単に被害者のデバイスにマルウェアをインストールするだけではなく、既存のプロセスにマルウェアを組み込む方法を革新し、検知されずに攻撃を成功させられるようにしています。また、実行可能な技術やバリエーションが非常に多いため、アナリストやソフトウェアが、システム上で実行されている一見正常に見えるプロセスの中にマルウェアが存在することを特定するのは、ますます困難になっています。サイバーセキュリティ企業は、猫とネズミのどちらが最新の動きをしたかに関わらず、効果的な高度なマルウェア検出技術と機能を提供することが、これまで以上に必要とされています。

このブログでは、マルウェアの回避技術に関するシリーズの第1回として、最も広く使用されているプロセスインジェクションや操作技術を紹介し、これらの技術を使用するマルウェアファミリーの例を示し、その検出方法を説明します。

DLL インジェクション

DLL インジェクションは、最もシンプルで最も一般的なプロセスインジェクション技術の 1 つです。別のプロセスの下で悪意のあるダイナミック リンクライブラリ(DLL)を実行するために、マルウェアは悪意のある DLL のパスをリモートプロセスのアドレス空間に書き込みます。そして、DLL の実行を呼び出すために、マルウェアは標的となるプロセスからリモートスレッドを作成します。この手法は、悪意のある DLL がリモートでプロセスにインジェクトする前にディスクに保存されていることを意味します。

DLL インジェクションの手順 :

  1. 実行中のプロセスをたどってターゲットプロセスを見つけ、OpenProcess を呼び出してそのプロセスのハンドルを取得します
  2. 悪意のある DLL ファイルのパスをターゲットプロセスにインジェクトするための領域を、ターゲットプロセスのハンドルを使って VirtualAllocEx を呼び出して割り当てます
  3. WriteProcessMemory で割り当てられた領域に DLL のパスを書き込みます
  4. kernel32.dll から LoadLibrary のアドレスを取得し、DLLへのパスが与えられると、それをメモリにロードします(ただし、実行はしません)
  5. CreateRemoteThread を呼び出し、LoadLibrary のアドレスを渡すと、インジェクトされた DLL ファイルのパスがメモリに読み込まれ、実行されます

この手法の欠点は、悪意のある DLL ファイルをディスク上に保存する必要があるため、通常のセキュリティソリューションでは検出されてしまうことです。とはいえ、この手法はマルウェア開発者が採用しており、一般に広く普及しています。例えば、古くから人気のある RAT である Poison Ivy は、DLL インジェクションを使用しています。Poison Ivy は、いくつかの APT キャンペーンに関与しており、APT グループがスパイ活動のために選択するツールとして推奨されています。

反映された DLL ロード (インジェクション)

反射型 DLL インジェクションは、前述の通常の DLL インジェクションとは異なり、Steven Fewer 氏によって導入された、他のプロセス内に DLL をインジェクトして実行するためのステルス性の高い技術です。この技術は、プロセスインジェクションではなく、「セルフローディング」と考える人もいるかもしれません。DLL をディスクに保存しないために、マルウェアは、Windows ローダーが行うように、DLL の生のバイナリを手動で仮想メモリにマッピングする必要があります。ただし、Windows API の LoadLibrary を呼び出さないようにする必要があり、LoadLibrary の呼び出しを監視するツールによって検出される可能性があります。ただし、Windows API の LoadLibrary を呼び出さないようにすると、LoadLibrary の呼び出しを監視するツールに検出される可能性があります。この場合、例えば ReflectiveLoader()  などのターゲットプロセス内で DLL の残りのコンポーネントを完全にロードしてマッピングし、インジェクトされたエクスポート関数の正しいアドレスを取得するだけで十分です。

反映された DLL インジェクションは、以下のステップにまとめることができます :

  1. OpenProcess を使って、Read-Write-eXecute のパーミッションを持つターゲットプロセスを探して開きます
  2. メモリに確保する必要のある DLL データのサイズを計算します
  3. VirtualAllocEx で DLL 用の十分なスペースをメモリ上に確保します
  4. 割り当てられた空間に DLL の生データを書き込む
  5. ReflectiveLoader() など、DLL 内で反射型ロードを行うために使用されるエクスポートされた関数へのオフセットを計算します
  6. CreateRemoteThread を用いて、ReflectiveLoader() のオフセットを渡して、対象プロセスで reflective loader 関数を実行します
  7. ReflectiveLoader() は、適切な CPU レジスタを使用してターゲットプロセスの PEB (Process Environment Block) を検索します。見つかった PEB は、メモリ上の kernel32.dll やその他の必要なライブラリのアドレスを見つけるために使用されます
  8. kernel32 のエクスポートされた関数を走査して、LoadLibraryAGetProcAddressVirtualAlloc などの他の DLL のインポートされた関数のアドレスを修正するために使用される Windows API 関数の正しいアドレスを見つけます
  9. 手順 8 の関数を使って、DLL をメモリにロードし、そのエントリーポイントを呼び出します

最近の Ramnit の亜種は、正規のプロセスの下でモジュールを実行するために、反射的な DLL の読み込みを採用していることが確認されています。Ramnit は、2010年から活動している広範なバンキングトロイの木馬です。2015 年に欧州刑事警察機構は Ramnit の C&C サーバーを停止させましたが、活動は停止せず、今でも人気のあるバンキングマルウェアの 1 つです。

ポータブル・エグゼクティブ・ロード (インジェクション)

反射型 DLL の読み込みと同様に、Portable Executable のインジェクトとロードは、DLL(または実行ファイル)をディスク上に保存する必要がありません。また同様に、PE インジェクションでは、インジェクトされた PE を正しくロードして実行するための作業が必要になります。インジェクトされた  PE をロードして実行するために、マルウェアはインジェクトされた PE の固定アドレスを適切に変更するために、新しいベースアドレスを計算する必要があります。これを実現するために、マルウェアはターゲットプロセス内の再配置テーブルを走査して、正しいアドレスを計算します。

PE のロードを簡単に説明すると:

PE Loading in a nutshell:

  1. 現在のイメージの PE ヘッダを使用して、そのベースアドレスとサイズを取得します
  2. PE をインジェクトするプロセスでは、VirtualAlloc を使用してイメージ用のメモリを割り当てます
  3. memcpy を使用して、イメージをローカルに割り当てられたメモリにコピーします
  4. ターゲットプロセスでは、VirtualAllocEx を用いてインジェクトされたイメージ用のメモリを割り当てます
  5. PE をインジェクトする過程で、ローカルメモリにロードされたから再配置テーブルのオフセットを見つける
  6. VirtualAllocEx から返されたアドレスで動作するように、手順 5 で作成した再配置テーブルを参照して、イメージのすべての絶対アドレスを修正します
  7. WriteProcessMemory を使用して、ローカルプロセスからターゲットプロセスの割り当てメモリにイメージをインジェクト(コピー)します
  8. ターゲットプロセス内で実行されるべきエクスポートされた関数の正しいアドレスを見つける

a)ベースアドレスからインジェクトプロセスにおける関数のアドレスを差し引く

b) ターゲットプロセスでは、割り当てられたメモリのアドレスに (b) の結果を加える

9. CreateRemoteThread で新しいスレッドを作成し、手順 8 で作成した関数のリモートアドレスを渡して、インジェクトした関数を実行します

注:インジェクトされた PE のベースアドレスの計算と絶対アドレスの固定に加えて、インポートされた関数を呼び出すためにインジェクションされた IAT を固定する必要があるかもしれません。前述の「反映された DLL ロード」のステップ 8 を確認してください。

実際には、ロシアを拠点とする APT グループである Turla をはじめとする複数のアクターが PE のロードを採用しています。Turla のスパイ活動のプラットフォームは、ランダムなプロセスに PE をロードするために PowerSploit の Invoke-ReflectivePEInjection.ps1 を採用しています。

プロセスホローイング

正当なプロセスに悪意のあるペイロードを実行させるための別の手法として、プロセスホローイングがあります。この手法では、正規のプロセスがマルウェアによって一時停止状態で起動されます。そして、サスペンド状態の間に、ターゲットプロセスのメモリをアンマップ(空洞化)して、悪意のあるペイロードを格納します。

プロセスホローイングの手順 :

  1. CreationFlags パラメータを CREATE_SUSPENDED=0x00000004 に設定した CreateProcess を呼び出すことで、サスペンド状態の新しいプロセスを開始します
  2. ZwUnmapViewOfSection または NtUnmapViewOfSection を使用して対象プロセスのメモリをアンマップします
  3. VirtualAllocEx を使用して、悪意のあるペイロードのためにメモリ内のスペースを割り当てます
  4. WriteProcessMemory で、割り当てられたメモリ領域にペイロードをインジェクトします
  5. GetThreadContext を呼び出すことで、インジェクトされたペイロードの正しい位置から開始するよう、対象プロセスの実行ポイントを変更します
  6. ResumeThread を呼び出して、対象となるプロセスの実行を再開します

プロセスの空洞化は、非常に人気のあるバンキングマルウェア TrickBot で見られました。2016 年以降、TrickBot は何千人ものオンラインバンキング(およびその他のサービス)の口座を危険にさらす大きな脅威となっています。プロセスホローイングは、TrickBot が長年にわたって採用してきたいくつかの回避技術の 1 つに過ぎません。

次の段階へ

ここ数年、「AtomBombing」や「Process Doppelgänging」という新しいプロセスインジェクションや操作技術が登場し、マルウェア開発者やセキュリティ研究者の間で急速に広まっています。

AtomBombingは、WindowsのAPC(Asynchronous Procedure Call)を利用した一連のプロセスインジェクション技術に関するものです。AtomBombing は、Windows がデータの共有や保存に使用しているグローバルアトムテーブルを利用して、悪意のあるコードを格納し、正規のプロセスで実行します。この手法は、有名なバンキングトロイの木馬である Dridex で確認されています。

プロセスドッペルゲンガーは、WindowsのTxF(Transactional NTFS)に依存しています。TxF は、トランザクテッド・ハンドルが 1 つのファイルに書き込むことだけを許可し、他のハンドルによる書き込み操作を阻止することでデータの整合性を確保する機能です。他のハンドルは、最初の書き込みハンドルを取得した時点で保存されているデータのバージョンを読み取ることができる。書き込み操作中にアプリケーションが失敗した場合、TxF はデータの初期バージョンへのロールバックを行います。プロセスドッペルゲンガーでは、正規のアプリケーションから作成された TxF トランザクションを使用して、このトランザクションのコンテキスト内でのみ表示されるファイルコンテンツを悪意のあるデータで上書きします。ここからは、他のインジェクションやローディングの手法と同様に、悪意のあるデータがメモリに読み込まれます。次に、上書きされたデータが TxFによってロールバックされ、悪意のあるデータの証拠がディスクから削除されます。最後に、読み込まれた悪意のあるコードは、新たに作成されたプロセスによって実行されます。この手法は一般的になりつつあり、AZORult、LokiBot、Pony Stealer などのマルウェアファミリーが採用しています。

マルウェアは、被害者を感染させる方法を常に模索しています。”善良な “マルウェアは、標的となるシステムへの影響を最小限に抑えながら被害者に感染し、疑われないように可能な限りその存在を偽装します。ここでは、正規のプロセスに紛れ込もうとするマルウェアに見られる回避技術の基本的な概要を紹介します。この概要が、マルウェアの回避技術を理解するための良い出発点となることを願っています。意識して安全を確保してください。

次のブログでは、仮想化対策マルウェアに焦点を当てています。