不正コードの攻撃者の攻撃方法は日々進化している。より安定的で正確な目標を攻撃するために多様な流布方法を利用し、セキュリティ機器、ソフトウェアの検知を避けるために様々な方法を利用して不正コードを隠している。その中でもファイルレス(Fileless)を利用した不正コードの隠し方は進化している。
今年、発見されたマグニバー(Megniber)ランサムウェアはインターネットエクスプローラーのプロセスにInjectionし(Fileless)、ユーザーのPCに不正コードを残さずにファイルを暗号化する行為をしていたと把握されている。
また、5月の全米北朝鮮委員会(NCNK)の「北朝鮮コロナ19状況インタービュー文書」をなりすましたDOC型の不正コードが発見されたが、これはWindows作業スケジューラを利用したファイルレス型であった。
このようにFileless方法を利用している不正コードが続々登場し、今後使用頻度が上がると想定される。攻撃には主にパワーシェル(Power Shell)スクリプトを難読化して利用したり、Process Hollowing, Reflective DLL Injection 等の方法を利用する。
今年6月22日、韓国の有名コミュニティから視力保護プログラムをなりすました不正コードが流布された。当該の不正コードは実行時、バックグラウンドにペイント(正常ファイル)プログラムを実行してる以外、異常行為は見えないファイルだった。しかし、詳細分析結果、ペイント(正常ファイル)に任意のDLLをReflective DLL Inejctionさせて不正行為の動きが確認できた。バックグラウンドから任意のC2にアクセスするログは残し続けるが、不正行為をするファイルは存在しないFileless不正コードだった。今回は実際に不正コードがどうやってReflective DLL Injection方法を使用しているか確認してみよう。
DLL Injectionは実行中の他のプロセスをのスペースに強制にDLLをInjectionする方法を意味する
「▲ DLL Injectionの過程 (参照:malwareforensics1.blogspot.com)」
1.OpenProcessを利用して当該のプロセスのハンドルを求める 2.VirtualAllocで当該のプロセスのメモリスペースを確保する 3.WriteProcessMemoryで当該のプロセスのメモリにInejctionするDLLのパスを入力 4.LoadLibary APIアドレスを求める(GetModuleHandle, GetProcAddress) 5.CreateRemoteThreadで当該のプロセスのInjectionされたデータを実行 |
---|
比較的に簡単な方法でDLLをInjectionすることができるため、不正コードによく使用されていたが、CreateRemoteThreadで当該のプロセスにInjectionされたDLLを実行する際に入るIpStarAddress引数のせいで簡単に検知できるデメリットがある。IpStarAddress引数にはGetProcAddressを通じて取れたLoadLibary(もしくはGetProceAddress)APIのアドレスが入るが、これを検知するとDLL Injectionを防ぐことができる。
Reflective DLL Injectionは既存のDLL Injection方法とは違って現在実行中のプロセスのメモリに任意のDLL対したデータを挿入後、直接マッピング(Mapping)して実行させる方法で動作する。このような動作方法は実際不正行為をしているDLLはバックグラウンドに存在せず、検知も難しい。このような特徴でファイルレス(Fileless)不正コードでよく使用されていて2017年話題になったSMB脆弱性エターナルブルー(Eternal Blue)とダブルパルサー(Double Pulsar)にも使用された。
1.OpenProcessを利用して当該のプロセスのハンドルを求める 2.VirtualAllocで当該のプロセスのメモリスペースを確保する 3.WriteProcessMemoryで当該のプロセスのメモリにInejctionするDLLのパスを入力 「Reflective Loader」 → メモリ実行権限付与(RWX) 4.メモリにDLLマッピング(Mapping) 5.Import Table新規作成 6.再配置及びマッピングされたDLL動作準備完了 7.CreateRemoteThreadで当該のプロセスのInjectionされたデータを実行 |
---|
「▲ Reflective DLL Injectionの過程 (参照:giac.org)」
2つのInjection方法はDLLをどのような形でプロセスにInjectionするかによって違う。DLL Injectionは実行できるファイル(PE)をそのままプロセスにInjectionし、Reflective DLL Injectionの場合、Injection際、実行できるファイルを現在使用中のメモリに直接Injectionし、メモリからすぐ使用できるようにする作業まで行うことが違う。
区分 | DLL Injection | Reflective DLL Injection |
---|---|---|
Injection‐方法 | InjectionしようとするDLLのパスを直接挿入 | InjectionしようとするDLLのパスを直接挿入後、メモリにマッピング(MAPPING) |
Injection-実行 | スレッド(Thread) | スレッド(Thread) |
検知方法 | ・レジストリ(Appinlt_DLLs)値チェック ・スレッド件数内部の引数値チェック | ・正常動作範囲以外のメモリスペースの権限をチェック (メモリにロードするために任意のメモリスペースにRWX権限を付与) |
分析に使用された不正コードの6月韓国のコミュニティの掲示板に視力保護プログラムのなりすまして流布された不正コードである。インストーラ(Installer)の形で流布されて実行時、正常に視力保護プログラムをダウンロードするが、バックグラウンドからはペイント(mspaint.exe)プロセスが実行されてC2アドレスにPCの情報を送信する動作をする。ペイントの場合System32内部にある正常プロセスを利用し、攻撃者は当該の攻撃のためにReflective DLL Injection方法を利用した。
不正コードの全体概要図は下記になる。実行とともに不正DLL(wctE64E.tmp)がドロップされてすぐ削除されるように見える。しかし、バックグラウンドではペイント(mspaint.exe)が動作されてC&Cサーバと通信する。不正行為をしていると想定されるDLLファイルが消えたのが不正行為がプロセスに介して続いてる不思議な現象が確認できる。
区分 | 内容 |
---|---|
ファイル名 | wctE64E.tmp |
MD5 | 19493F139D74950681354BB881113683 |
ファイルサイズ | 286.50KB (293,376 byte) |
「▲ 不正コードの概要図」
Reflective DLL Injectionは既存のDLL Injection方法とは違って現在実行中のプロセスのメモリに任意のDLL対したデータを挿入後、直接マッピング(Mapping)して実行させる方法で動作する。このような動作方法は実際不正行為をしているDLLはバックグラウンドに存在せず、検知も難しい。このような特徴でファイルレス(Fileless)不正コードでよく使用されていて2017年話題になったSMB脆弱性エターナルブルー(Eternal Blue)とダブルパルサー(Double Pulsar)にも使用された。
当該のプロセスには不正DLLをInjectionする対象としてmspaint.exe(ペイント)を利用した。
「▲ mspaint.exeプロセスオープン」
現在実行中の不正DLLファイル(wctE64E.tmp)と同じパスで実行中の不正DLLと同じファイル作成を試すが、CreateFileWのdwShareMode引数が0x0に設定されていてデバッグの状態では正常にファイルが作成できないように設定されている(アンチでバック効果)。それを迂回すると正常にファイルが作成されるところが確認できる。
「▲ 現在実行中の不正DLLファイルのハンドル収集」
dwShareModeの値が0の場合、他のプロセスが削除、読み取り、書き込みアクセスを要請する場合、ファイルまたはデバイスを開けないようにする。従って、不正DLLファイルを分析するために任意のLoaderにInjectionさせる場合、引数によって作成されるファイルのハンドルを正常に持ってくることができないため、それ以降の行為ができない。
正常に作成されたファイル(現在実行中の不正DLL)のサイズを確認後、ヒップ(Heap)を割り当する。正常にヒップを割り当した後、作成されたファイル(現在実行中の不正DLL)のデータを割り当てられたヒップにコピーする。
「▲ 不正DLLのデータを使用するための過程①」
「▲ メモリロード前(上)とロード後(下)」
mspaint.exeプロセスの内部に本格的に不正DLLをInjectionするために、作成(CreateProcess)していたプロセスをオープンする。
「▲ mspaint.exeプロセスオープン」
本格的にReflective DLL Injectionするためにローダー関数であるiAppleCloud関数を呼び出す。当該の関数はImport Tableに宣言されている。関数の内部コードを調べてみよう。
「Reflective DLL Injectionローダー関数(iAppleCloud)を呼び出す」
| STEP1 ローダーに使用するデータ加工 |
|——————————————————————————————————————————————————————————————————————————————————————————————————————————–|
| Injectionのためにローダー(Loader)の機能が大事である。当該ローダーでは現在実行中の不正DLLが呼び出しているシステムDLL(ntdll.dll, kernel32.dll)の情報が必要とする。ローダーの機能のためにAPいが必要のためである。当該ローダーの関数ではWindows API Hashを利用して必要なシステムDLLとAPIを探してローダーに使用できる形に加工する。 |
| STEP2 イメージロード |
|—————————————————————————————————————————————————————————————————-|
| ロードするPEのヘッダーを持ってきた後、不正DLLをメモリにロードするためにメモリを割り当てする。仮想メモリにロードされる際、実行できるImagebaseにローディングできるように再配置(Relocation)作業を行。 |
| STEP3 イメージをロードするセクション確認 |
|————————————————————————|
| 任意のセクションにデータをロードするためにセクションエリアを探索する。 |
| STEP4 Import Table再作成 |
|—————————————————————|
| ロードされた新しいイメージファイルを参照してIATを再作成する。 |
| STEP5 プロセスイメージの再配置 |
|——————————————————————————————–|
| 全ての過程が終わったイメージが競合なく、メモリにロードできるように再配置(Relocation)する。 |
OpenProcessでオープンしたmspaint.exeの内部に0x47AAA(実行中の不正DLLのファイルサイズほど)ほど任意のスペースを割り当てする(割り当てされるスペースのアドレスは実行時異なる)
【▲ mspaint.exeの内部に不正DLLをロードするための任意スペースの割り当て】
【▲ mspaint.exe – 任意のスペースが割り当てられた】
WriteProcessMemoryを利用して総3回mspaint.exeの内部にデータを挿入する。
NO | コピーされるデータ |
---|---|
1 | Heapスペースにロードされている現在実行中の不正DLL |
2 | 現在実行中の不正DLLの絶対パス |
3 | スレッド実行時、初めてスタートする部分 |
【▲ WriteProcessMemoryを利用してデータ挿入】
【▲ 最初のWriteProcessMemoryを通じて挿入される内容】
【▲ 2回目のWriteProcessMemoryを通じて挿入される内容】
【▲ 3回目のWriteProcessMemoryを通じて挿入される内容】
mspaint.exeにReflective DLL Injectionされた不正DLLをCreateRemoteThreadで実行する。
【▲ CreateRemoteThreadを利用してInjectionされたDLLのデータが実行される】
Reflective DLL Injection
Filelessの事例
Written by CYBERFORTRESS, INC.
Tweet