John Uhlmann

コールスタック:マルウェアの無料パスはもうありません

コールスタックがマルウェア検知にもたらす計り知れない価値と、アーキテクチャ上の制限にもかかわらず、Elasticがコールスタックを重要なWindowsエンドポイントテレメトリーと見なしている理由を探ります。

19分で読めますセキュリティ調査
コールスタック:マルウェアの無料パスはもうありません

呼び出し履歴は、

ElasticのWindowsエンドポイントテレメトリの主な差別化要因の1つは 、コールスタックです

ほとんどの検出は何が起こっている に依存していますが、ほとんどの動作は二重の目的であるため、これはしばしば不十分です。呼び出し履歴を使用すると、アクティビティを実行している ユーザー を特定するためのきめ細かな機能も追加されます。この組み合わせにより、悪意のあるアクティビティを発見する比類のない能力が得られます。この詳細なテレメトリーを Elastic Defendのオンホストルールエンジンにフィードすることで、新たな脅威に迅速に対応できます。

コールスタックは美しい嘘です

コンピュータサイエンスでは、 スタック は後入れ先出しのデータ構造です。物理的なアイテムのスタックと同様に、一番上の要素のみを追加または削除できます。呼び出しスタックは、現在アクティブなサブルーチン呼び出しに関する情報を含むスタックです。

x64 ホストでは、この呼び出し履歴は、 Intel LBR、Intel BTS、Intel AET、 Intel IPTx64 Architectural LBR などの CPU の実行トレース機能を使用してのみ正確に生成できます。これらのトレース機能は、パフォーマンス プロファイリングとデバッグの目的で設計されていますが、一部のセキュリティ シナリオでも使用できます。ただし、より一般的に利用できるのは、 スタック ウォーク と呼ばれるメカニズムによってスレッドのデータ スタックから回復される おおよその 呼び出し履歴です。

x64 アーキテクチャでは、当然のことながら "スタック ポインター レジスタ" (rsp) はスタック データ構造を指しており、このスタック上のデータを読み書きするための効率的な命令があります。さらに、 call 命令は新しいサブルーチンに制御を移しますが、スタックポインタが参照するメモリアドレスにリターンアドレスも保存します。ret命令は、後でこの保存されたアドレスを取得して、実行を中断したところから戻すことができます。ほとんどのプログラミング言語の関数は、通常、これら 2 つの命令を使用して実装され、パフォーマンスのために関数パラメーターとローカル関数変数の両方が通常、このスタックに割り当てられます。スタックの 1 つの関数に関連する部分は、スタック フレームと呼ばれます。

スタック ウォーキングは、スレッド スタックに格納されている異種データからリターン アドレスのみを回復することです。リターンアドレスは制御フローのためにどこかに保存する必要があるため、Stack Walkingはこの既存のデータを取り込み、コールスタックを 近似 します。これは、ほとんどのデバッグとパフォーマンス プロファイルのシナリオに完全に適していますが、セキュリティ監査には少し役に立ちません。主な問題は、逆方向に分解できないことです。特定の通話サイトの返信先住所はいつでも特定できますが、その逆はできません。最善の方法は、先行する命令の長さ 15 それぞれを確認し、どれが正確に 1 つの呼び出し命令に分解されるかを確認することです。それでも、復元したのは 以前の 通話サイトだけであり、必ずしも 正確な直前の 通話サイトである必要はありません。これは、ほとんどのコンパイラが テールコール の最適化を使用して不要なスタックフレームを省略するためです。これにより、Win32StartAddress 関数が呼び出されてもスタック上に存在する保証がないなど、 セキュリティにとって厄介なシナリオ が作成されます。

したがって、通常コールスタックと呼ばれるものは、実際にはリターンアドレススタックです。

マルウェアの作成者は、このあいまいさを利用して嘘をつきます。彼らは、正当なモジュールを介してトランポリンスタックフレームを作成し、悪意のあるコードから発信された呼び出しを隠すか、CPUが実行するものとは異なるリターンアドレスを予測するようにスタックウォークを強制します。もちろん、マルウェアは常に嘘をつく試みであり、マルウェア対策はその嘘を暴くプロセスにすぎません。

“...しかし、やがて真実が明らかになるだろう。

  • ウィリアム・シェイクスピア、ヴェネツィアの商人、第2幕、シーン2

コールスタックを美しくする

これまで、スタックウォークは数値メモリアドレスのリストにすぎませんでした。それらを分析に役立てるには、コンテキストでそれらを充実させる必要があります。(注: 現在、カーネルスタックフレームは含まれていません。

最小限の有用なエンリッチメントは、これらのアドレスをモジュール内のオフセットに変換することです(例:ntdll.dll+0x15c9c4)。しかし、これでは最も悪質なマルウェアしか捕捉できませんが、さらに深く掘り下げることができます。Windows で最も重要なモジュールは、ネイティブ API と Win32 API を実装するモジュールです。これらの API のアプリケーションバイナリインタフェースでは、各関数の名前を、含まれているモジュールの エクスポートディレクトリ に含める必要があります。これは、Elastic がエンドポイントのコールスタックを充実させるために現在使用している情報です。

ベンダーのインフラストラクチャ (特に Microsoft) でホストされている パブリック シンボル (利用可能な場合) を使用することで、より正確なエンリッチメントを実現できます。この方法では、より深い忠実度が提供されますが、運用コストが高くなり、エアギャップのお客様には実現できません。

Microsoft カーネル シンボルとネイティブ シンボルの経験則では、各コンポーネントのエクスポートされたインターフェイスには、Ldr、Tp、Rtl などの大文字のプレフィックスが付けられます。プライベート関数は、このプレフィックスを p で拡張します。デフォルトでは、外部リンケージを持つプライベート関数は 、パブリックシンボルテーブルに含まれます。オフセットが非常に大きい場合は、関数が非常に大きいことを示している可能性がありますが、シンボルがない名前のない関数を示しているだけである可能性もあります。一般的なガイドラインは、エクスポートされた関数の 3 桁以上のオフセットは、別の関数に属している可能性が高いと見なすことです。

呼び出し履歴スタックウォークスタックウォークモジュールStack Walk Exports(エラスティックアプローチ)スタックウォークパブリックシンボル
0x7ffb8eb9c9c2 0x12d383f0046 0x7ffb8eb1a9d8 0x7ffb8eb1aaf4 0x7ffb8ea535ff 0x7ffb8da5e8cf 0x7ffb8eaf14eb0x7ffb8eb9c9c4 0x7ffb8c3c71d6 0x7ffb8eb1a9ed 0x7ffb8eb1aaf9 0x7ffb8ea53604 0x7ffb8da5e8d4 0x7ffb8eaf14f1ntdll.dll+0x15c9c4 kernelbase.dll+0xc71d6ntdll.dll+0xda9edntdll.dll+0xdaaf9ntdll.dll+0x13604kernel32.dll+0x2e8d4ntdll.dll+0xb14f1ntdll.dll!NtProtectVirtualMemory+0x14 kernelbase.dll!VirtualProtect+0x36 ntdll.dll!RtlAddRefActivationContext+0x40d ntdll.dll!RtlAddRefActivationContext+0x519 ntdll.dll!RtlAcquireSRWLockExclusive+0x974 kernel32.dll!BaseThreadInitThunk+0x14 ntdll.dll!RtlUserThreadStart+0x21ntdll.dll!NtProtectVirtualMemory+0x14 kernelbase.dll!VirtualProtect+0x36 ntdll.dll!RtlTpTimerコールバック+0x7d ntdll.dll!TppTimerpExecuteCallback+0xa9 ntdll.dll!TppWorkerThread+0x644 kernel32.dll!BaseThreadInitThunk+0x14 ntdll.dll!RtlUserThreadStart+0x21

呼び出しスタックのエンリッチメント レベルの比較

上記の例では、0x12d383f0000のシェルコードは、そのアドレスがスタックウォークに表示されないように、意図的にテールコールを使用しています。この嘘の省略は、茎の散歩だけでも明らかです。Elasticは、マルウェアが別のスレッドからのVirtualProtectへの呼び出しをプロキシするタイマーコールバック関数を登録したため、これをproxy_callヒューリスティックで報告します。

コールスタックを強力にする

Event Tracing for Windows (ETW) で監視するシステム呼び出しの呼び出し履歴には、想定される構造があります。スタックの一番下には、スレッドの StartAddress (通常は ntdll.dll) があります。RtlUserThreadStart です。これに続いて、Win32 API スレッド エントリ - kernel32.dll!BaseThreadInitThunk を呼び出し、次に最初のユーザー モジュール。ユーザーモジュールは、Win32 (またはネイティブ) API の一部ではないアプリケーションコードです。この最初のユーザー モジュールは、スレッドの Win32StartAddress と一致する必要があります (その関数が末尾呼び出しを使用した場合を除く)。最終的なユーザーモジュールがネイティブAPI呼び出しを行うWin32 APIを呼び出すまで、さらに多くのユーザーモジュールが続き、最終的にカーネルへのシステムコールが発生します。

検出の観点からは、この呼び出し履歴で最も重要なモジュールは 最終的なユーザー モジュールです。Elasticは、このモジュールをハッシュとコード署名とともに表示します。これらの詳細は、アラートのトリアージに役立ちますが、さらに重要なことは、マルウェアのように動作する正当なソフトウェアの動作をベースライン化できる粒度を大幅に改善することです。ベースラインの正常値が正確であればあるほど、マルウェアが混ざりにくくなります。

{
  "process.thread.Ext": {
    "call_stack_summary": "ntdll.dll|kernelbase.dll|file.dll|rundll32.exe|kernel32.dll|ntdll.dll",
    "call_stack": [
      { "symbol_info": "c:\\windows\\system32\\ntdll.dll!NtAllocateVirtualMemory+0x14" }, /* Native API */
      { "symbol_info": "c:\\windows\\system32\\kernelbase.dll!VirtualAllocExNuma+0x62" }, /* Win32 API */
      { "symbol_info": "c:\\windows\\system32\\kernelbase.dll!VirtualAllocEx+0x16" }, /* Win32 API */
      {
        "symbol_info": "c:\\users\\user\\desktop\\file.dll+0x160d8b", /* final user module */
        "callsite_trailing_bytes": "488bf0488d4d88e8197ee2ff488bc64883c4685b5e5f415c415d415e415f5dc390909090905541574156415541545756534883ec58488dac2490000000488b71",
        "callsite_leading_bytes": "088b4d38894c2420488bca48894db8498bd0488955b0458bc1448945c4448b4d3044894dc0488d4d88e8e77de2ff488b4db8488b55b0448b45c4448b4dc0ffd6"
      },
      { "symbol_info": "c:\\users\\user\\desktop\\file.dll+0x7b429" },
      { "symbol_info": "c:\\users\\user\\desktop\\file.dll+0x44a9" },
      { "symbol_info": "c:\\users\\user\\desktop\\file.dll+0x5f58" },
      { "symbol_info": "c:\\windows\\system32\\rundll32.exe+0x3bcf" },
      { "symbol_info": "c:\\windows\\system32\\rundll32.exe+0x6309" }, /* first user module - typically the ETHREAD.Win32StartAddress module */
      { "symbol_info": "c:\\windows\\system32\\kernel32.dll!BaseThreadInitThunk+0x14" }, /* Win32 API */
      { "symbol_info": "c:\\windows\\system32\\ntdll.dll!RtlUserThreadStart+0x21" /* Native API - the ETHREAD.StartAddress module */
      }
    ],
    "call_stack_final_user_module": {
      "path": "c:\\users\\user\\desktop\\file.dll",
      "code_signature": [ { "exists": false } ],
      "name": "file.dll",
      "hash": { "sha256": "0240cc89d4a76bafa9dcdccd831a263bf715af53e46cac0b0abca8116122d242" }
    }
  }
}

エンリッチされた呼び出し履歴のサンプル

コールスタックの最終ユーザーモジュールのエンリッチメント:

namecall_stack_final_user_moduleのファイル名。また、プライベート実行可能メモリを示す "Unbacked" や、疑わしい呼び出し履歴を示す "Undetermined" にすることもできます。
パスcall_stack_final_user_moduleのファイルパス。
hash.sha256 です。call_stack_final_user_module の sha256、またはprotection_provenance モジュール (存在する場合)。
code_signaturecall_stack_final_user_moduleのコード署名、またはprotection_provenanceモジュールがある場合はその署名。
allocation_private_bytesこのメモリ領域内のバイト数で、+X と共有不可能の両方であるもの。0 以外の値は、コードのフック、パッチ適用、または空洞化を示している可能性があります。
protectionページの動作領域のメモリー保護は、RX でない場合に含まれます。MEMORY_BASIC_INFORMATIONに対応します。守る。
protection_provenanceこのページの保護が最後に変更されたメモリ領域の名前。「Unbacked」はシェルコードを示している可能性があります。
protection_provenance_pathこのページの保護が最後に変更されたモジュールのパス。
理由「未確定」のprotection_provenanceにつながった異常なcall_stack_summary。

クイック コール スタックの用語集

コールスタックを調べるときには、理解しておくと便利なネイティブ API 関数がいくつかあります。現在MicrosoftのKen Johnsonは、 NTDLLカーネルモードからユーザーモードへのコールバックのカタログ を提供してくれました。真面目な話、ここで立ち止まって、最初にそれを読んでみてください。

先ほど RtlUserThreadStart に会いました。この RtlUserFiberStart とその兄弟 RtlUserFiberStart は、どちらも呼び出し履歴の一番下にのみ表示する必要があります。これらは、それぞれユーザースレッドと ファイバーのエントリポイントです。ただし、すべてのスレッドの最初の命令は、実際には LdrInitializeThunk です。スレッド初期化 (および必要に応じて処理) のユーザー モード コンポーネントを実行した後、この関数は NtContinue を介してエントリポイントに制御を移し、命令ポインターを直接更新します。これは、今後のスタック ウォークに表示されないことを意味します。

したがって、LdrInitializeThunk を含む呼び出し履歴が表示されている場合は、スレッドの実行が開始されていることを意味します。これは、アプリケーション互換性 Shim Engine が動作する場所であり、フックベースのセキュリティ製品がそれ自体をインストールすることを好む場所であり、マルウェアが他のセキュリティ製品 よりも先 に実行を試みる場所です。Marcus HutchinsGuido Miggelenbrink は、このトピックについて優れたブログを書いています。このスタートアップ競争は、テレメトリに カーネル ETW を使用するセキュリティ製品には存在しません。

{
  "process.thread.Ext": {
    "call_stack_summary": "ntdll.dll|file.exe|ntdll.dll",
    "call_stack": [
      { "symbol_info": "c:\\windows\\system32\\ntdll.dll!ZwProtectVirtualMemory+0x14" },
      { "symbol_info": "c:\\users\\user\\desktop\\file.exe+0x1bac8" },
      { "symbol_info": "c:\\windows\\system32\\ntdll.dll!RtlAnsiStringToUnicodeString+0x3cb" },
      { "symbol_info": "c:\\windows\\system32\\ntdll.dll!LdrInitShimEngineDynamic+0x394d" },
      { "symbol_info": "c:\\windows\\system32\\ntdll.dll!LdrInitializeThunk+0x1db" },
      { "symbol_info": "c:\\windows\\system32\\ntdll.dll!LdrInitializeThunk+0x63" },
      { "symbol_info": "c:\\windows\\system32\\ntdll.dll!LdrInitializeThunk+0xe" }
    ],
    "call_stack_final_user_module": {
      "path": "c:\\users\\user\\desktop\\file.exe",
      "code_signature": [ { "exists": false } ],
      "name": "file.exe",
      "hash": { "sha256": "a59a7b56f695845ce185ddc5210bcabce1fff909bac3842c2fb325c60db15df7" }
    }
  }
}

エントリポイント前の実行例

次のペアは KiUserExceptionDispatcher と KiRaiseUserExceptionDispatcher です。カーネルは前者を使用して、ユーザー・モードの例外条件が発生した後、登録されたユーザー・モード構造化例外ハンドラーに実行を渡します。後者も例外を発生させますが、代わりにカーネルに代わって発生します。この 2 番目のバリアントは、通常、 アプリケーション検証ツールを含むデバッガーによってのみキャッチされ、ユーザー モード コードがシステム呼び出しからのリターン コードを十分にチェックしていないタイミングを特定するのに役立ちます。これらの関数は、通常、アプリケーション固有のクラッシュ処理または Windows エラー報告に関連する呼び出し履歴に表示されます。しかし、マルウェアはこれを疑似ブレークポイントとして使用することがあります(例えば、システムコールを行った直後にシェルコードを再隠すために メモリ保護を変動 させたい場合など)。

{
  "process.thread.Ext": {
    "call_stack_summary": "ntdll.dll|file.exe|ntdll.dll|file.exe|kernel32.dll|ntdll.dll",
    "call_stack": [
      {
        "symbol_info": "c:\\windows\\system32\\ntdll.dll!ZwProtectVirtualMemory+0x14",
        "protection_provenance": "file.exe", /* another vendor's hooks were unhooked */
        "allocation_private_bytes": 8192
      },
      { "symbol_info": "c:\\users\\user\\desktop\\file.exe+0xd99c" },
      { "symbol_info": "c:\\windows\\system32\\ntdll.dll!RtlInitializeCriticalSectionAndSpinCount+0x1c6" },
      { "symbol_info": "c:\\windows\\system32\\ntdll.dll!RtlWalkFrameChain+0x1119" },
      { "symbol_info": "c:\\windows\\system32\\ntdll.dll!KiUserExceptionDispatcher+0x2e" },
      { "symbol_info": "c:\\users\\user\\desktop\\file.exe+0x12612" },
      { "symbol_info": "c:\\windows\\system32\\kernel32.dll!BaseThreadInitThunk+0x14" },
      { "symbol_info": "c:\\windows\\system32\\ntdll.dll!RtlUserThreadStart+0x21" }
    ],
    "call_stack_final_user_module": {
      "name": "file.exe",
      "path": "c:\\users\\user\\desktop\\file.exe",
      "code_signature": [ { "exists": false }],
      "hash":   { "sha256": "0e5a62c0bd9f4596501032700bb528646d6810b16d785498f23ef81c18683c74" }
    }
  }
}

例外ハンドラによる保護変動の例

次は KiUserApcDispatcher で、 これはユーザー APC の配信に使用されます。これらはマルウェア作成者のお気に入りのツールの1つであり、Microsoftはその使用について限られた可視性しか提供していません。

{
  "process.thread.Ext": {
    "call_stack_summary": "ntdll.dll|kernelbase.dll|ntdll.dll|kernelbase.dll|cronos.exe",
    "call_stack": [
      { "symbol_info": "c:\\windows\\system32\\ntdll.dll!NtProtectVirtualMemory+0x14" },
      { "symbol_info": "c:\\windows\\system32\\kernelbase.dll!VirtualProtect+0x36" }, /* tail call */
      { "symbol_info": "c:\\windows\\system32\\ntdll.dll!KiUserApcDispatcher+0x2e" },
      { "symbol_info": "c:\\windows\\system32\\ntdll.dll!ZwDelayExecution+0x14" },
      { "symbol_info": "c:\\windows\\system32\\kernelbase.dll!SleepEx+0x9e" },
      {
        "symbol_info": "c:\\users\\user\\desktop\\file.exe+0x107d",
        "allocation_private_bytes": 147456, /* stomped */
        "protection": "RW-", /* fluctuation */
        "protection_provenance": "Undetermined", /* proxied call */
        "callsite_leading_bytes": "010000004152524c8d520141524883ec284150415141baffffffff41525141ba010000004152524c8d520141524883ec284150b9ffffffffba0100000041ffe1",
        "callsite_trailing_bytes": "4883c428c3cccccccccccccccccccccccccccc894c240857b820190000e8a10c0000482be0488b052fd101004833c44889842410190000488d84243014000048"
      }
    ],
    "call_stack_final_user_module": {
      "name": "Undetermined",
      "reason": "ntdll.dll|kernelbase.dll|ntdll.dll|kernelbase.dll|file.exe"
    }
  }
}

APCによる保護変動の例

Windows ウィンドウ マネージャーは、カーネル モード デバイス ドライバー (win32k.sys) に実装されます。大概。ウィンドウマネージャがユーザーモードから何かをする必要があるときがあり、KiUserCallbackDispatcher はそれを実現するためのメカニズムです。これは基本的に、user32.dll関数を対象とするリバースシステムコールです。プロセスの KernelCallbackTable のエントリを上書きすることは、GUI スレッドを乗っ取る簡単な方法であるため、この呼び出しに続く他のモジュールは疑わしいです。

これらのカーネル モードからユーザー モードへの各エントリ ポイントの目的に関する知識は、特定の呼び出し履歴が自然であるか、または別の目標を達成するために悪用されたかどうかを判断するのに大いに役立ちます。

コールスタックを理解できるようにする

わかりやすくするために、イベントにさまざまなプロセスでタグを付けます。Ext.api.behaviorsを特定します。これらの動作は必ずしも悪意のあるものではありませんが、アラートのトリアージや脅威ハンティングに関連する側面を浮き彫りにしています。呼び出し履歴の場合、これには次のものが含まれます。

native_apiWin32 API ではなく、ネイティブ API に対して直接呼び出しが行われました。
direct_syscallA syscall instruction originated outside of the Native API layer.
proxy_call呼び出し履歴は、真のソースをマスクするためのプロキシされた API 呼び出しを示している場合があります。
シェルコードセンシティブAPIと呼ばれる第2世代の実行可能な非画像メモリ。
image_indirect_callAn entry in the call stack was preceded by a call to a dynamically resolved function.
image_rop呼び出しスタックのエントリの前に呼び出し命令がありませんでした。
image_rwx呼び出しスタックのエントリは書き込み可能です。コードは読み取り専用にする必要があります。
unbacked_rwx呼び出し履歴のエントリは、非イメージで書き込み可能です。JITコードも読み取り専用にする必要があります。
truncated_stackThe call stack seems to be unexpectedly truncated. This may be due to malicious tampering.

状況によっては、これらの動作だけでマルウェアを検出するのに十分な場合があります。

スプーフィング - バイパスか責任か?

返信先アドレスのなりすましは、長年にわたって ゲームのハッキングマルウェア の定番の手法でした。この単純なトリックにより、挿入されたコードは、正当なモジュールの評判をほとんど影響なく借りることができます。ディープ コール スタックの検査と動作のベースラインの目標は、マルウェアにこのフリー パスを与えないようにすることです。

攻撃的な研究者は、完全なコールスタックのなりすましのアプローチを調査することで、この取り組みを支援しています。特に:

SilentMoonwalkは、優れた攻撃研究であることに加えて、嘘をつくと2倍のトラブルに巻き込まれるという優れた例です。多くの防衛回避技術は、隠すことによるセキュリティに依存しており、研究者によって暴露されると、それらは責任になる可能性があります。このケースでは、調査には、回避の試みによって もたらされる 検出機会に関するアドバイスが含まれていました。

{
  "process.thread.Ext": {
    "call_stack_summary": "ntdll.dll|kernelbase.dll|kernel32.dll|ntdll.dll",
    "call_stack": [
      { "symbol_info": "c:\\windows\\system32\\ntdll.dll!NtAllocateVirtualMemory+0x14" },
      { "symbol_info": "c:\\windows\\system32\\kernelbase.dll!VirtualAlloc+0x48" },
      {
        "symbol_info": "c:\\windows\\system32\\kernelbase.dll!CreatePrivateObjectSecurity+0x31",
        /* 4883c438 stack desync gadget - add rsp 0x38 */
        "callsite_trailing_bytes": "4883c438c3cccccccccccccccccccc48895c241057498bd8448bd2488bf94885c90f84660609004885db0f845d060900418bd14585c97411418bc14803c383ea",
        "callsite_leading_bytes": "cccccccccccccccccccccccccccccc4883ec38488b4424684889442428488b442460488944242048ff15d9b21b000f1f44000085c00f8830300900b801000000"
      },
      { "symbol_info": "c:\\windows\\system32\\kernelbase.dll!Internal_EnumSystemLocales+0x406" },
      { "symbol_info": "c:\\windows\\system32\\kernelbase.dll!SystemTimeToTzSpecificLocalTimeEx+0x2d1" },
      { "symbol_info": "c:\\windows\\system32\\kernelbase.dll!WaitForMultipleObjectsEx+0x982" },
      { "symbol_info": "c:\\windows\\system32\\kernel32.dll!BaseThreadInitThunk+0x14" },
      { "symbol_info": "c:\\windows\\system32\\ntdll.dll!RtlUserThreadStart+0x21" }
    ],
    "call_stack_final_user_module": {
      "name": "Undetermined", /* gadget module resulted in suspicious call stack */
      "reason": "ntdll.dll|kernelbase.dll|kernel32.dll|ntdll.dll"
    }
  }
}

SilentMoonwalk コールスタックの例

隠れたアーティファクトを発掘するための標準的な手法は、複数の手法を使用してそれらを列挙し、結果に不一致がないか比較することです。これが RootkitRevealer のしくみです。このアプローチは、 スレッドスタックを登 るだけでなく、下りる Get-InjectedThreadEx.exe でも使用されました。

特定の状況では、2 つの方法で呼び出し履歴を回復できる場合があります。不一致がある場合は、信頼性の低い呼び出し履歴が call_stack_summary_original として出力されます。

{
  "process.thread.Ext": {
    "call_stack_summary": "ntdll.dll",
    "call_stack_summary_original": "ntdll.dll|kernelbase.dll|version.dll|kernel32.dll|ntdll.dll",
    "call_stack": [
      { "symbol_info": "c:\\windows\\system32\\ntdll.dll!NtContinue+0x12" },
      { "symbol_info": "c:\\windows\\system32\\ntdll.dll!LdrInitializeThunk+0x13" }
    ],
    "call_stack_final_user_module": {
      "name": "Undetermined",
      "reason": "ntdll.dll"
    }
  }
}

呼び出し履歴の概要の元の例

コールスタックはすべての人のためのものです

デフォルトでは、アラートにはコールスタックのみが表示されますが、これは高度なポリシーを使用して構成できます。

events.callstacks.emit_in_events設定されている場合、呼び出し履歴は収集される通常のイベントに含まれます。それ以外の場合は、動作保護ルールをトリガーするイベントにのみ含まれます。これを設定すると、データ量が大幅に増加する可能性があることに注意してください。デフォルト: false

Windowsコールスタックの詳細については、以下のElasticセキュリティラボの記事をご覧ください。

この記事を共有する