掲載日:2020/11/17

Bromium Blog記事

Agent Tesla:APIフックを削除してEDRを回避

※ 本ブログは、2019年8月23日にBromium BlogポストされたAgent Tesla: Evading EDR by Removing API Hooksの日本語訳です。

 

Toby GrayとRatnesh Pandeyが執筆しました。

エンドポイント検知および応答(EDR)ツールは、マルウェアが実行されたときに生成される悪意のある活動を検知するのに、オペレーティングシステムのイベントに依存しています。これらのイベントは、後に関連付けされて分析され、異常な挙動や不審な挙動を検知します。このようなイベントのソースの1つは、EDRソリューションが興味深いAPIコールを追跡するのに役立つアプリケーション・プログラム・インターフェース(API)フックです。最近、パスワードを盗むトロイの木馬、Agent Teslaを配信するフィッシングキャンペーンに遭遇しました。Bromium Secure Platformでキャプチャしたフォレンジックデータを分析していたところ、Windows Native APIをエクスポートするダイナミックリンクライブラリ(DLL)であるntdll.dllのアドレス空間でメモリ改ざんイベントが発生していることに気付きました。ペイロードはBromium Secure Platformによって隔離され、マルウェアを捕捉しました。

Agent Teslaのダウンローダーは、プライマリペイロードをドロップして実行する.xlsファイルとしてやって来ます。このブログ記事では、EDRのようなフッキングに依存するツールによる検出を回避するために、ドロッパーによるAPIのアンフックについて説明します。その後のブログ記事では、キャンペーンの詳細な分析を提供します。

 

システムコール

システムコールはオペレーティングシステムのカーネル内の関数で、ユーザーからの要求にサービスを提供し、基礎となる特権リソースにユーザーが直接アクセスできないようにバリアを提供します。Windows システムでは、ntdll.dll ライブラリにユーザーモードのシステムコールが含まれています。これらのシステムコールに関する情報は、関数ポインタの配列とシステムサービス記述子テーブル (SSDT) に格納されます。

 

 SERVICE_TABLE_DESCRIPTORデータ構造はシステムコールの 配列へのポインタを含む 図1 - SERVICE_TABLE_DESCRIPTORデータ構造はシステムコールの 配列へのポインタを含む

 

“Base”は関数ポインタの配列を指し、システムコール番号はこの配列へのインデックスです。これらの関数は、NtAllocateVirtualMemoryの場合の仮想メモリの割り当てのように、何らかのアクションを実行するようカーネルに要求するために使用されます。この議論の残りの部分では、メモリのパーミッションを変更するために使用される、文書化されていないシステムコールである NtProtectVirtualMemory に焦点を当てます。

 

32-BIT CODE ON 64-BIT WINDOWS

32 ビットプログラムが 64 ビット Windows マシン上で実行されると、Windows on Windows 64 (略して WoW64) として知られているシステムの下で実行されます。カーネルは 64 ビットモードで実行されているため、32 ビットプログラムからのシステムコールはすべて、メモリ内の既知の場所にあるラッパー関数 Wow64SystemServiceCall を経由して行われます。これは、多くのシステムコール関数を含む ntdll.dll が非常に反復的な構造を持っていることを意味します。

 

NtProtectVirtualMemoryの逆アセンブル 図2 -NtProtectVirtualMemoryの逆アセンブル

 

  • NtProtectVirtualMemoryの4行の逆アセンブルコードは以下となります。
  • システムコール番号 0x50 を eax レジスタにロード
  •  Wow64Transitionの位置(上のスクリーンショットでは0x77BC2430)をedxレジスタに入る
  • edxで関数を呼び出す
  • この関数から戻る

 

次のシステムコール関数 ZwQuerySection は、この関数の直後にあり、同じ構造に従っていますが、唯一の違いは、0x50 ではなく 0x51 をシステムコール番号として読み込むことです。

 

フックAPI

セキュリティ製品は、ソフトウェアからのシステムAPIコールを傍受して記録するためにAPIフックを使用しています。これを実現する1つの方法は、フッキングするAPIのインメモリコードを変更することです。

フッキングされると、最初の命令は、フッキングソフトウェアによって生成されたトランポリンコードにジャンプする命令に置き換えられます。

 

NtProtectVirtualMemoryの元の関数を5バイトのjmp命令で上書き 図3 - NtProtectVirtualMemoryの元の関数を5バイトのjmp命令で上書き

 

図3では、NtProtectVirtualMemoryの最初の命令はもはや0x50をeaxにロードしません。その代わりに、コードの実行をアドレス 0x004F0012 にリダイレクト(またはジャンプ)します。フッキングコードはそのアドレスに生成されたコードを持ちます。

 

  • フッキングが追加されたアクションを実行、おそらく次のような組み合わせ:
    • アクティビティを監視するためのAPIコールを記録する
    • 特定のアクションを防ぐためにAPIコールを変更する
    • APIをブロックして悪意のある活動を停止させる
  • 置換された命令を実行する(この場合は mov eax, 50 なので、eax レジスタを 0x50 に設定)
  • 元の関数の次の命令(この場合は 0x77BAE215)に戻るために実行をジャンプ

 

元の関数はその後も通常通りに実行を続けるので、API を呼び出しているコードもシステムカーネルも、関数呼び出しが横取りされたことを認識していません。

 

マルウェアによるAPIフッキングのアンフック

メールヘッダ

  • From: Alhaji Nasiru <sales@gossipnewspro.info >
  • To: <–<Redacted>–.com>
  • Subject: New Purchase Order for August
  • Date: Sun, 28 Jul 2019 16:41:52 -0700
  • Attachment: Signeded-revised-PI.xls

 

ダウンローダー

  • Filename: Signeded-revised-PI.xls
  • Size: 82 KB (83968 bytes)
  • MD5: C081E4AA1FBEC4857E88E4FBF91FE90E
  • SHA-1: 1F6527CBD8BC83132A89C4F66A897A576259C4A1
  • SHA-256: 42BD54E60C86AE02BCD9BCD02FA82C9D77D831F3EED77DD924E2E6976B9A5808

 

ドロッパー

  • Filename: v4bc6f.exe [Win32.Trojan.Injector]
  • File size: 936 KB (958464 bytes)
  • MD5: 97BD950CA1FBD49A632A876A05E7ACEF
  • SHA-1: 6FD6E4B676BD363B817F54F067684A14BA31E053
  • SHA-256: 851AC0EF0956156EFCDDDB15288A6DF82009940D58F851D006732675F3B9AD1D

 

最近のマルウェアは通常、アンチウイルスなどのシグネチャベースの検出技術による静的検出を回避するために、ポリモーフィズムや難読化技術に依存しています。EDR ツールは、システムアクティビティを監視し、通常のアプリケーションの動作から逸脱している場合や、既知の悪意のあるパターンと一致する場合に、疑わしいイベントにフラグを立てることで、その機能を実現しています。これらのイベントのほとんどは、APIをフックすることによって生成されます。一部のセキュリティソリューションでは、疑わしいイベントがトリガーされた場合に悪意のあるプロセスをブロックするためにAPIフックを使用するものもあります。

今回この悪意のあるサンプルを分析したところ、ペイロードであるAgent Tesla (bin.exe)を起動する前に、メモリマップされたntdll.dllを変更しているユニークなコードがあることに気付きました。このマルウェアはシェルコードにより、次のアクションを実行します。

 

  • ntdll.dll のアドレス空間の NtProtectVirtualMemory を呼び出して、その領域のメモリ権限を PAGE_EXECUTE_READWRITE に変更
  • 以下のように ntdll.dll から API フックを削除
  • NtProtectVirtualMemory を呼び出して、領域のページ権限を PAGE_EXECUTE_READ に戻す
  • フックを削除した後、ShellExecuteW API を介してメインペイロードを実行

 

APIフックを削除するシェルコード 図4-APIフックを削除するシェルコード

 

悪意のあるコードは、ntdll.dll のメモリを 1 byteずつスキャンする前に、Wow64SystemServiceCall のアドレスを edx レジスタにロードします。上記のコードで0x004A0A50 の命令は、スキャンするntdll.dll の次の部分の位置持つ ebx レジスタをインクリメントしています。

0x004A0A51での最初のチェックは、前述のフックのアンフックとは関係のないチェックを行っているので、その比較はスキップして0x004A0A6Bにジャンプしてください。0x004A0A6BのチェックはWow64Transitionの値を調べており、それが見つかれば0x004A0A6Fから始まる命令が実行されます。手順は以下の通りです。

 

  • eax(システムコール番号のカウンタで、NtProtectVirtualMemoryの場合は0x50)の値をWow64Transitionの値の場所の5byte前に書き込む
  • 0xB8をWow64Transitionの値の位置の6byte前に書き込む
  • eax の値をインクリメントし、システムコール番号を次の値に移動

 

5 byte(eax 4 byte、0xB8 1byte)を書き込んだ結果、フック命令(前の例では jmp 0x004F0012 など)を元の命令(前の例では mov eax, 50)に置き換えました。

最終的には、悪意のあるコードがシステム API を呼び出すことができるようになり、その要求がフックによって監視されたりブロックされたりすることはありません。

悪意のある活動はすべて、保護のためにハードウェアによる隔離が利用されているマイクロ仮想マシン(uVM)内で行われるため、このフック解除はBromium Secure Platformにとっては問題ではありません。

 

Agent Teslaペイロード

  • ファイル名: bin.exe [Byte-code-MSIL.Spyware.Ielib]
  • ファイルサイズ: 331.5 KB (339456 バイト)
  • md5: 640ca1048f2aed048cb209234fa080b9
  • sha-1: 58790a758b31e80648db288ba86f49f7dc05d89b
  • sha-256: 53997af9cf992bf7a97e54f79a1474a1c0023133d7b97b861a278baa238c9421

関連記事