<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[Asuka Nakajima - Elastic Security Labs]]></title>
    <description><![CDATA[Trusted security news & research from the team at Elastic.]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[Asuka Nakajima - Elastic Security Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte2c6b841aff36df4/6a88d9784acc96e3f324863d/security-labs-thumbnail.png</url>
      <link>https://www.elastic.co/jp/security-labs/author/asuka-nakajima</link>
    </image>
    <link>https://www.elastic.co/jp/security-labs/author/asuka-nakajima</link>
    <atom:link href="https://www.elastic.co/jp/security-labs/rss/author/asuka-nakajima.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[jp]]></language>
    <lastBuildDate>Wed, 16 Sep 2026 12:43:14 GMT</lastBuildDate>
  <item>
    <title><![CDATA[未公開のカーネルデータ構造を使ったホットキー型キーロガーの検知]]></title>
    <description><![CDATA[本記事では、ホットキー型キーロガーとは何かについてと、その検知方法について紹介します。具体的には、ホットキー型キーロガーがどのようにしてキー入力を盗み取るのかを解説した後、カーネルレベルに存在する未公開(Undocumented)のホットキーテーブルを活用した検知手法について説明します。]]></description>
    <content:encoded><![CDATA[<h2>未公開のカーネルデータ構造を使った</h2>
<h2 id="-1">ホットキー型キーロガーの検知</h2>
<p>本記事では、ホットキー型キーロガーとは何かについてと、その検知方法について紹介します。具体的には、ホットキー型キーロガーがどのようにしてキー入力を盗み取るのかを解説した後、カーネルレベルに存在する未公開(Undocumented)のホットキーテーブルを活用した検知手法について説明します。</p>
<h2 id="-2">はじめに</h2>
<p>　Elastic Security Labsでは2024年5月、<a href="https://www.elastic.co/guide/en/integrations/current/endpoint.html">Elastic Defend</a>のバージョン 8.12 より追加された、Windows上で動作するキーロガーの検知を強化する新機能を紹介する<a href="https://www.elastic.co/security-labs/protecting-your-devices-from-information-theft-keylogger-protection-jp">記事</a>を公開しました 。具体的には、サイバー攻撃で一般的に使われる4種類のキーロガー(ポーリング型キーロガー、フッキング型キーロガー、Raw Input Modelを用いたキーロガー、DirectInputを用いたキーロガー)を挙げ、それらに対する私たちが提供した検知手法についてを解説しました。具体的には<a href="https://learn.microsoft.com/ja-jp/windows-hardware/drivers/devtest/event-tracing-for-windows--etw-">Event Tracing for Windows</a> (ETW)における、Microsoft-Windows-Win32kプロバイダを用いた振る舞い検知の方法についてを紹介しました。<br />
　記事公開後、大変光栄なことに記事がMicrosoft社のPrincipal Security Researcherである<a href="https://jonathanbaror.com/">Jonathan Bar Or</a>氏の目に留まり、「ホットキー型キーロガーもある」といった貴重なご意見とともに、そのPoCコードも公開してくださりました。そこで本記事では、氏が公開したホットキー型キーロガーのPoCコードである「<a href="https://github.com/yo-yo-yo-jbo/hotkeyz">Hotkeyz</a>」 をもとに、本キーロガーの検知手法の一案についてを述べたいと思います。</p>
<h2 id="-3">ホットキー型キーロガーの概要</h2>
<h3 id="-4">そもそもホットキーとは何か？</h3>
<p>　ホットキー型キーロガーについて説明する前に、まずホットキーとは何かを解説します。ホットキーとは、キーボードショートカットの一種であり、コンピュータにおいて、特定の機能を直接呼び出して実行させるキーまたはキーの組み合わせのことを指します。例えばWindowsにおいてタスク(ウィンドウ)を切り替える際に「<strong>Alt + Tab</strong>」を押している人も多いかと思います。この時使っているこの「<strong>Alt + Tab</strong>」が、タスク切り替え機能を直接呼び出す「ホットキー」にあたります。</p>
<p><em>(注: ホットキー以外にも、キーボードショートカットは存在しますが、本記事ではそれらは対象外です。また本記事に記載の事項はすべて、筆者が検証に利用した環境である、仮想化ベースのセキュリティが動作していないWindows 10 version 22H2 OS Build 19045.5371が前提になります。他のWindowsのバージョンではまた内部の構造や挙動が違う場合があること、ご注意ください。)</em></p>
<h3 id="-5">任意のホットキーが登録できることを悪用する</h3>
<p>　先ほどの例のようにWindowsで予め設定されたホットキーを使う以外にも、実は自分で任意のホットキーを登録することも可能です。登録方法は様々ありますが、<a href="https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-registerhotkey">RegisterHotKey</a>というWindows APIを使えば、指定のキーをホットキーとして登録することができます。例えば、以下が<code>RegisterHotKey</code> APIを使って「A」(<a href="https://learn.microsoft.com/ja-jp/windows/win32/inputdev/virtual-key-codes">virtual-key code</a>で0x41)キーを、グローバルなホットキーとして登録するためのコードの例です。</p>
<pre><code>/*
BOOL RegisterHotKey(
  [in, optional] HWND hWnd, 
  [in]           int  id,
  [in]           UINT fsModifiers,
  [in]           UINT vk
);
*/
RegisterHotKey(NULL, 1, 0, 0x41);
</code></pre>
<p>　ホットキーとして登録後、登録されたキーが押下された場合、<code>RegisterHotKey</code> APIの第一引数で指定したウィンドウ(NULLの場合はホットキー登録時のスレッド)の<a href="https://learn.microsoft.com/ja-jp/windows/win32/winmsg/about-messages-and-message-queues">メッセージキュー</a>に、<a href="https://learn.microsoft.com/ja-jp/windows/win32/inputdev/wm-hotkey">WM_HOTKEYメッセージ</a>が届くようになります。以下は実際に、メッセージキューにWM_HOTKEY メッセージが来ていないかを<a href="https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-getmessage">GetMessage</a> APIを使って確認し、届いていた場合、WM_HOTKEYメッセージに内包されていた virtual-key code(今回の場合「0x41」)を取り出しているコード(メッセージループ)になります。</p>
<pre><code>MSG msg = { 0 };
while (GetMessage(&amp;msg, NULL, 0, 0)) {
    if (msg.message == WM_HOTKEY) {
        int vkCode = HIWORD(msg.lParam);
        std::cout &lt;&lt; "WM_HOTKEY received! Virtual-Key Code: 0x"
            &lt;&lt; std::hex &lt;&lt; vkCode &lt;&lt; std::dec &lt;&lt; std::endl;
    }
}
</code></pre>
<p>　これは言い換えると、例えばメモ帳アプリに文章を書く際、Aキーから入力された文字は、文字としての入力ではなく、グローバルなホットキーとして認識されることになります。</p>
<p>　今回は「A」のみをホットキーとして登録しましたが、複数のキー(BやCやD)を同時に個々のホットキーとして登録することも可能です。これはつまり、<code>RegisterHotKey</code> APIでホットキーとして登録可能な範囲の任意のキー(virtual-key code)の入力は、すべてグローバルなホットキーとして横取りすることも可能であるということです。そしてホットキー型キーロガーはこの性質を悪用して、ユーザから入力されたキーを盗み取ります。<br />
　筆者が手元の環境で試した限りは、英数字と基本的な記号キーだけでなく、それらにSHIFT修飾子をつけたすべてキーが<code>RegisterHotKey</code> APIでホットキーとして登録可能でした。そのため、キーロガーとして問題なく、情報の窃取に必要なキーの監視ができると言えるでしょう。</p>
<h3 id="-6">密かにキーを盗み取る</h3>
<p>　ホットキー型キーロガーがキーを盗み取る実際の流れについてを、Hotkeyzを例に紹介します。<br />
Hotkeyzでは最初に、各英数字キーに加えて、一部のキー(VK_SPACEやVK_RETURNなど)のvirtual-key codeを、<code>RegisterHotKey</code> APIを使い個々のホットキーとして登録します。その後キーロガー内のメッセージループにて、登録されたホットキーのWM_HOTKEYメッセージが、メッセージキューに到着していないかを<a href="https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-peekmessagew">PeekMessageW</a> APIを使って確認します。そしてWM_HOTKEYメッセージが来ていた場合、メッセージに内包されているvirtual-key codeを取り出して、最終的にはそれをテキストファイルに保存します。以下がメッセージループ内のコードのコードです。特に重要な部分を抜粋して掲載しています。</p>
<pre><code>while (...)
{
    // Get the message in a non-blocking manner and poll if necessary
    if (!PeekMessageW(&amp;tMsg, NULL, WM_HOTKEY, WM_HOTKEY, PM_REMOVE))
    {
        Sleep(POLL_TIME_MILLIS);
        continue;
    }
....
   // Get the key from the message
   cCurrVk = (BYTE)((((DWORD)tMsg.lParam) &amp; 0xFFFF0000) &gt;&gt; 16);

   // Send the key to the OS and re-register
   (VOID)UnregisterHotKey(NULL, adwVkToIdMapping[cCurrVk]);
   keybd_event(cCurrVk, 0, 0, (ULONG_PTR)NULL);
   if (!RegisterHotKey(NULL, adwVkToIdMapping[cCurrVk], 0, cCurrVk))
   {
       adwVkToIdMapping[cCurrVk] = 0;
       DEBUG_MSG(L"RegisterHotKey() failed for re-registration (cCurrVk=%lu,    LastError=%lu).", cCurrVk, GetLastError());
       goto lblCleanup;
   }
   // Write to the file
  if (!WriteFile(hFile, &amp;cCurrVk, sizeof(cCurrVk), &amp;cbBytesWritten, NULL))
  {
....
</code></pre>
<p>　ここで特筆するべき点としては、ユーザにキーロガーの存在を気取られないため、メッセージからvirtual-key codeを取り出した時点で、いったんそのキーのホットキー登録を<a href="https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-unregisterhotkey">UnregisterHotKey</a> APIを使って解除し、その上で<a href="https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-keybd_event">keybd_event</a>を使ってキーを送信することです。これにより、ユーザからは問題無くキーが入力出来ているように見え、キーが裏で窃取されていることに気が付かれにくくなります。そしてキーを送信した後は再びそのキーを<code>RegisterHotKey</code> APIを使ってホットキーとして登録し、再びユーザからの入力を待ちます。以上が、ホットキー型キーロガーの仕組みです。</p>
<h2 id="-7"><strong>ホットキー型キーロガーの検知手法</strong></h2>
<p>　ホットキー型キーロガーとは何かやその仕組みについて理解したところで、次にこれをどのように検知するかについてを説明します。</p>
<h3 id="etwregisterhotkeyapi">ETWではRegisterHotKey APIは監視していない</h3>
<p>　以前の記事で書いた方法と同様に、まずはホットキー型キーロガーも<a href="https://learn.microsoft.com/ja-jp/windows/win32/etw/about-event-tracing">Event Tracing for Windows</a> (ETW) を利用して検知が出来ないかを検討・調査しました。その結果、ETWでは<code>RegisterHotKey</code> APIや<code>UnRegisterHotKey</code> APIを監視していないことがすぐに判明しました。Microsoft-Windows-Win32k プロダイバーのマニフェストファイルの調査に加えて、<code>RegisterHotKey</code>のAPIの内部(具体的にはwin32kfull.sysにある<code>NtUserRegisterHotKey</code>)をリバースエンジニアリングをしたものの、これらのAPIが実行される際、ETWのイベントを送信しているような形跡は残念ながら見つかりませんでした。<br />
　以下の図は、ETWで監視対象となっている<code>GetAsyncKeyState</code>(<code>NtUserGetAsyncKeyState</code>)と、<code>NtUserRegisterHotKey</code>の逆コンパイル結果を比較したものを示しています。<code>NtUserGetAsyncKeyState</code>の方には関数の冒頭に、<code>EtwTraceGetAsyncKeyState</code>というETWのイベント書き出しに紐づく関数が存在しますが、<code>NtUserRegisterHotKey</code>には存在しないのが見て取れます。</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcc28afaca9cca911/6a856c14342d69d2a4219cee/image3.png" alt="図1: NtUserGetAsyncKeyStateとNtUserRegisterHotKeyの逆コンパイル結果の比較" title="図1: NtUserGetAsyncKeyStateとNtUserRegisterHotKeyの逆コンパイル結果の比較" />
　<br />
　Microsoft-Windows-Win32k 以外のETWプロバイダーを使って、間接的に<code>RegisterHotKey</code> APIを呼び出しを監視する案もでたものの、次に紹介する、ETWを使わず「ホットキーテーブル」を利用した検知手法が、<code>RegisterHotKey</code> APIを監視するのと同様かそれ以上の効果が得られることが分かり、最終的にはこの案を採用することにしました。</p>
<h3 id="gphkhashtable">ホットキーテーブル(gphkHashTable)を利用した検知</h3>
<p>　ETWでは<code>RegisterHotKey</code> APIの呼び出しを直接監視出来ないことが判明した時点で、ETWを利用せずに検知する方法を検討することにしました。検討の最中、「そもそも登録されたホットキーの情報がどこかに保存されているのではないか？」「もし保存されているとしたら、その情報が検知に使えるのではないか？」という考えに至りました。その仮説をもとに調査した結果、すぐに<code>NtUserRegisterHotkey</code>内にて<code>gphkHashTable</code>というラベルがつけられたハッシュテーブルを発見することが出来ました。Microsoft社が公開しているオンラインのドキュメント類を調査しても<code>gphkHashTable</code>についての情報はなかったため、これは未公開(undocumented)のカーネルデータ構造のようです。</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt98d8ed6f918d0bbb/6a856c18bc5bb3074df807ec/image1.png" alt="図2: ホットキーテーブルgphkHashTable。NtUserRegisterHotKey内で呼ばれたRegisterHotKey関数内にて発見" title="図2: ホットキーテーブルgphkHashTable。NtUserRegisterHotKey内で呼ばれたRegisterHotKey関数内にて発見" /></p>
<p>　リバースエンジニアリングをした結果、このハッシュテーブルは、登録されたホットキーの情報を持つオブジェクトを保存しており、各オブジェクトは<code>RegisterHotKey</code> APIの引数にて指定されたvirtual-key codeや修飾子の情報を保持していることが分かりました。以下の図(右)がホットキーのオブジェクト(<strong>HOT_KEY</strong>と命名)の構造体の定義の一部と、図(左)が実際にwindbg上で<code>gphkHashTable</code>にアクセスした上で、登録されたホットキーのオブジェクトを見た時の様子です。</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt40e0226a73d7e9d3/6a856c1b80984c0a1d6671be/image4.png" alt="図3: ホットキーオブジェクトの詳細。Windbg画面(図左)とHOT_KEY構造体の詳細" title="図3: ホットキーオブジェクトの詳細。Windbg画面(図左)とHOT_KEY構造体の詳細" /></p>
<p>　リバースエンジニアリングをした結果をまとめると、ghpkHashTableは図4のような構造になっていることがわかりました。具体的には、<code>RegisterHotKey</code> APIで指定されたvirtual-key codeに対して0x80の余剰演算をした結果をハッシュテーブルのインデックスにしていました。そして同じインデックスを持つホットキーオブジェクトを連結リストで結ぶことで、virtual-key codeが同じでも、修飾子が違うホットキーの情報も保持・管理出来るようになっています。  </p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5a26e28d70f3f4ed/6a856c1ed7b2e732fbfe729e/image6.png" alt="図4: gphkHashTableの構造" title="図4: gphkHashTableの構造" /></p>
<p>　つまり<code>gphkHashTable</code>で保持している全てのHOT_KEYオブジェクトを走査すれば、登録されている全ホットキーの情報が取得できるということになります。取得した結果、主要なキー(例えば単体の英数字キー）全てが個々のホットキーとして登録されていれば、ホットキー型キーロガーが動作していることを示す強い根拠となります。</p>
<h2 id="-8">検知ツールを作成する</h2>
<p>　では次に、実際に検知ツールの方を実装していきます。<code>gphkHashTable</code>自体はカーネル空間に存在するため、ユーザモードのアプリケーションからはアクセス出来ません。そのため検知のために、デバイスドライバを書くことにしました。具体的には<code>gphkHashTable</code>のアドレスを取得した後、ハッシュテーブルに保存されている全オブジェクトを走査した上で、ホットキーとして登録されている英数字キーの数が一定数以上ならば、ホットキー型キーロガーが存在する可能性がある事を知らせてくるデバイスドライバを作成することにしました。</p>
<h3 id="gphkhashtable-1">gphkHashTableのアドレスを取得する方法</h3>
<p>　検知ツールを作成するにあたり、最初に直面した課題としては「gphkHashTableのアドレスをどのようにして取得すればよいのか？」ということです。悩んだ結果、<strong>win32kfull.sys</strong>のメモリ空間内でgphkHashTableにアクセスしている命令から直接gphkHashTableのアドレスを取得することにしました。<br />
　リバースエンジニアリングした結果、<code>IsHotKey</code>という関数内では、関数の冒頭部分にあるlea命令(lea rbx, gphkHashTable)にて、gphkHashTableのアクセスしていることがわかりました。この命令のオプコードバイト(0x48, 0x8d, 0x1d)部分をシグネチャに該当行を探索して、得られた32bit(4バイト)のオフセットからgphkHashTableのアドレスを算出することにしました。  </p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb3c3a91d3e8cc2f4/6a856c219d2b71cdfef9258c/image5.png" alt="図5: IsHotKey関数内 " title="図5: IsHotKey関数内" /></p>
<p>　加えて、IsHotKey関数自体もエクスポート関数でないため、そのアドレスも何らかの方法で取得しなければいけません。そこでさらなるリバースエンジニアリングの結果、<code>EditionIsHotKey</code>というエクスポートされた関数内で、<code>IsHotKey</code>関数が呼ばれていることがわかりました。そこでEditionIsHotKey関数から前述と同様の方法で、IsHotKey関数のアドレスを算出することにしました。(補足ですが、<strong>win32kfull.sys</strong>のベースアドレスに関しては<code>PsLoadedModuleList</code>というAPIで探せます。)</p>
<p>　## <strong>win32kfull.sys</strong>のメモリ空間にアクセスするには </p>
<p>　<strong>gphkHashTable</strong>のアドレスを取得する方法について検討が終わったところで、実際に<strong>win32kfull.sys</strong>のメモリ空間にアクセスして、<strong>gphkHashTable</strong>のアドレスを取得するためのコードを書き始めました。この時直面した課題としては、<strong>win32kfull.sys</strong>は「セッションドライバ」であるという点ですが、ここではまず「セッション」とは何かについて、簡単に説明します。<br />
　Windowsでは一般的にユーザがログインした際、ユーザ毎に個別に「セッション」(1番以降のセッション番号)が割り当てられます。かなり大雑把に説明すると、最初にログインしたユーザには「セッション１」が割り当てられ、その状態で別のユーザがログインした場合今度は「セッション２」が割り当てられます。そして各ユーザは個々のセッション内で、それぞれのデスクトップ環境を持ちます。<br />
　この時、セッション別(ログインユーザ別)に管理するべきカーネルのデータは、カーネルメモリ内の「セッション空間」というセッション別の分離したメモリ空間で管理され、win32k ドライバが管理しているようなGUIオブジェクト(ウィンドウ、マウス・キーボード入力の情報等)もこれに該当します。これにより、ユーザ間で画面や入力情報が混ざることがないのです。(かなり大まかな説明のため、より詳しくセッションについて知りたい方はJames Forshaw氏の<a href="https://googleprojectzero.blogspot.com/2016/01/raising-dead.html">こちらのブログ記事</a>を読むことをおすすめします。)  </p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc733f19744428aad/6a856c23f61d6e77be9c1879/image2.png" alt="図6: セッションの概要。 セッション0はサービスプロセス専用のセッション" title="図6: セッションの概要。 セッション0はサービスプロセス専用のセッション" />
　　<br />
以上の背景から、<strong>win32kfull.sys</strong>は「セッションドライバ」と呼ばれています。つまり、例えば最初のログインユーザのセッション(セッション1)内で登録されたホットキーの情報は、同じセッション内からしかアクセスできないということです。ではどうすれば良いのかというと、このような場合、<a href="https://learn.microsoft.com/ja-jp/windows-hardware/drivers/ddi/ntifs/nf-ntifs-kestackattachprocess">KeStackAttachProcess</a>が利用できることが<a href="https://eversinc33.com/posts/kernel-mode-keylogging.html">知られています</a>。<br />
　KeStackAttachProcessは、現在のスレッドを指定のプロセスのアドレス空間に一時的にアタッチすることが出来ます。この時、対象のセッションにいるGUIプロセス、より正確には<strong>win32kfull.sys</strong>をロードしているプロセスにアタッチすることが出来れば、対象セッションの<strong>win32kfull.sys</strong>やそのデータにアクセスすることが出来ます。今回は、ログインユーザが１ユーザであることを仮定して、各ユーザのログオン操作を担うプロセスである<strong>winlogon.exe</strong>を探してアタッチすることにしました。</p>
<h3 id="-9">登録されているホットキーを確認する</h3>
<p>　<strong>winlogon.exe</strong>のプロセスにアタッチし、<strong>gphkHashTable</strong>のアドレスを特定出来た後は、後は<strong>gphkHashTable</strong>をスキャンして登録されたホットキーを確認するだけです。以下がその抜粋版のコードです。</p>
<pre><code>BOOL CheckRegisteredHotKeys(_In_ const PVOID&amp; gphkHashTableAddr)
{
-[skip]-
    // Cast the gphkHashTable address to an array of pointers.
    PVOID* tableArray = static_cast&lt;PVOID*&gt;(gphkHashTableAddr);
    // Iterate through the hash table entries.
    for (USHORT j = 0; j &lt; 0x80; j++)
    {
        PVOID item = tableArray[j];
        PHOT_KEY hk = reinterpret_cast&lt;PHOT_KEY&gt;(item);
        if (hk)
        {
            CheckHotkeyNode(hk);
        }
    }
-[skip]-
}

VOID CheckHotkeyNode(_In_ const PHOT_KEY&amp; hk)
{
    if (MmIsAddressValid(hk-&gt;pNext)) {
        CheckHotkeyNode(hk-&gt;pNext);
    }

    // Check whether this is a single numeric hotkey.
    if ((hk-&gt;vk &gt;= 0x30) &amp;&amp; (hk-&gt;vk &lt;= 0x39) &amp;&amp; (hk-&gt;modifiers1 == 0))
    {
        KdPrint(("[+] hk-&gt;id: %u hk-&gt;vk: %x\n", hk-&gt;id, hk-&gt;vk));
        hotkeyCounter++;
    }
    // Check whether this is a single alphabet hotkey.
    else if ((hk-&gt;vk &gt;= 0x41) &amp;&amp; (hk-&gt;vk &lt;= 0x5A) &amp;&amp; (hk-&gt;modifiers1 == 0))
    {
        KdPrint(("[+] hk-&gt;id: %u hk-&gt;vk: %x\n", hk-&gt;id, hk-&gt;vk));
        hotkeyCounter++;
    }
-[skip]-
}
....
if (CheckRegisteredHotKeys(gphkHashTableAddr) &amp;&amp; hotkeyCounter &gt;= 36)
{
   detected = TRUE;
   goto Cleanup;
}
</code></pre>
<p>　コード自体は難しくなく、ハッシュテーブルの各インデックスの先頭から順に、連結リストをたどりながらすべての<strong>HOT_KEY</strong>オブジェクトにアクセスして、登録されているホットキーが単体の英数字キーか否かを確認しています。作成した検知ツールでは、すべての単体英数字キーがホットキーとして登録<br />
されていた場合、ホットキー型キーロガーが存在するとしてアラートを挙げます。また、今回実装の簡略化のため、英数字単体キーのホットキーのみを対象としていますが、SHIFTなどの修飾子付きのホットキーも容易に調べることが可能です。</p>
<h3 id="hotkeyz">Hotkeyzを検知する</h3>
<p>　検知ツール(Hotkey-based Keylogger Detector)は以下にて公開しました。使い方も以下に記載していますので、興味ある方はぜひご覧ください。加えて本研究は<a href="https://nullcon.net/goa-2025/speaker-windows-keylogger-detection">NULLCON Goa 2025</a>でも発表しましたので、その<a href="https://docs.google.com/presentation/d/1B0Gdfpo-ER2hPjDbP_NNoGZ8vXP6X1_BN7VZCqUgH8c/edit?usp=sharing">発表スライド</a>も併せてご覧いただけます。</p>
<p>*<a href="https://github.com/AsuNa-jp/HotkeybasedKeyloggerDetector">https://github.com/AsuNa-jp/HotkeybasedKeyloggerDetector</a></p>
<p>　最後に、本ツールを用いて実際にHotkeyzを検知する様子を収録したデモ動画が以下になります。</p>
<p><a href="https://drive.google.com/file/d/1koGLqA5cPlhL8C07MLg9VDD9-SW2FM9e/view?usp=drive_link">DEMO_VIDEO.mp4</a></p>
<h2 id="-10">謝辞</h2>
<p>　<a href="https://www.elastic.co/security-labs/protecting-your-devices-from-information-theft-keylogger-protection-jp">前回の記事</a>を読んで下さり、その上でホットキー型キーロガーの手法について教えてくださり、その上そのPoCとなるHotkeyzを公開してくださった、Jonathan Bar Or氏に心より感謝致します。</p>]]></content:encoded>
    <link>https://www.elastic.co/security-labs/threat-command/detecting-hotkey-based-keyloggers</link>
    <guid isPermaLink="false">detecting-hotkey-based-keyloggers</guid>
    <category><![CDATA[Platform Internals]]></category>
    <dc:creator><![CDATA[Asuka Nakajima]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfc22a2b9b9707cc9/6a7c7ce896b5a6527e8754dc/Security_Labs_Images_12.jpg" length="0" type="image/jpeg"/>
    <pubDate>Tue, 04 Mar 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[情報窃取から端末を守る]]></title>
    <description><![CDATA[本記事ではElastic Securityにおいて、エンドポイント保護を担っているElastic Defendに今年(バージョン8.12より)新たに追加された、キーロガーおよびキーロギング検出機能について紹介します。]]></description>
    <content:encoded><![CDATA[<p>本記事ではElastic Securityにおいて、エンドポイント保護を担っているElastic Defendに今年(バージョン<a href="https://www.elastic.co/guide/en/security/8.12/release-notes-header-8.12.0.html#enhancements-8.12.0">8.12</a>より)新たに追加された、キーロガーおよびキーロギング検出機能について紹介します。</p>
<h2>はじめに</h2>
<p>Elastic Defend 8.12より、Windows上で動作するキーロガーおよび、キーロギング機能を備えたマルウェア(情報窃取型マルウェアや、リモートアクセス型トロイの木馬、通称RAT)の検知の強化を目的に、キーロガーが使用する代表的なWindows API群の呼び出しを監視・記録する機能が追加されました。本記事ではこの新機能に焦点を当て、その技術的な詳細を解説します。加えて、本機能に付随して新たに作成された振る舞い検知ルール(Prebuilt rule)についても紹介します。</p>
<h3 id="-1">キーロガーとはなにか？どのような危険性があるのか？</h3>
<p>キーロガーとは、コンピュータ上で入力されたキーの内容を監視および記録(キーロギング)するソフトウェアの一種です(※1)。キーロガーは、ユーザのモニタリングなどの正当な理由で利用されることもありますが、攻撃者によって頻繁に悪用されるソフトウェアです。具体的には、ユーザがキーボード経由で入力した認証情報やクレジットカード情報、各種機密情報などのセンシティブな情報の窃取などに際に使われます。(※1: パソコンにUSB等で直接取り付けるようなハードウェア型のキーロガーもありますが、本記事ではソフトウェア型のキーロガーに焦点を当てます。)</p>
<p>キーロガーを通じて入手したセンシティブな情報は、金銭の窃取やさらなるサイバー攻撃の足がかりに悪用されます。それゆえに、キーロギング行為自体は直接的にコンピュータに被害をおよばさないものの、続くサイバー攻撃の被害を食い止めるためにも、早期の検知が非常に重要だと言えます。</p>
<p>キーロギング機能を持つマルウェアは多々あり、特にRAT、情報窃取型マルウェア、バンキングマルウェアといった種類のマルウェアにキーロギング機能が搭載されている場合があることが確認されています。有名なマルウェアでキーロギング機能を有するものとしては<a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.agent_tesla">Agent Tesla</a>や<a href="https://malpedia.caad.fkie.fraunhofer.de/details/apk.lokibot">Lokibit</a>、そして<a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.404keylogger">SnakeKeylogger</a>などが挙げられます。</p>
<h3 id="-2">いかにして入力した文字を盗み取っているのか？</h3>
<p>では次に、キーロガーはいかにしてユーザがキーボードから入力した文字を、ユーザに気づかれること無く盗み取っているのかを、技術的な観点から説明していきます。キーロガー自体は、あらゆるOS環境(Windows/Linux/macOSやモバイルデバイス)で存在しうるものではありますが、本記事ではWindowsのキーロガーに焦点を絞って解説します。特にWindows APIや機能を使用してキー入力を取得する4つの異なるタイプのキーロガーについて解説します。</p>
<p>一点補足としては、ここでキーロギングの手法について説明しているのは、あくまで本記事後半で紹介している、新しい検知機能についての理解を深めていただくためです。そのため、例として掲載しているコードはあくまで単なる例であり、実際にそのまま動くコードが掲載されている訳ではありません(※3)。</p>
<p>(※2:  Windows上で動作するキーロガーは、カーネル空間(OS)側に設置されるものと、通常のアプリケーションと同じ領域(ユーザ空間)に設置されるものに大別されます。本記事では、後者のタイプを取り上げます。 )
(※3: 以下に掲載されている例のコードを元にキーロガーを作成し悪用した場合、弊社では対応、および、責任について負いかねます 。)</p>
<ol>
<li>ポーリング型キーロガー</li>
</ol>
<p>このタイプのキーロガーは、キーボードの各キーの状態(キーが押された否か)を短い間隔(1秒よりはるかに短い間隔)で定期的に確認します。そして前回の確認以降に、新たに押されたキーがあることが判明した場合、その押されたキーの文字の情報を記録・保存します。この一連の流れを繰り返すことで、キーロガーは、ユーザが入力した文字列の情報を取得しているのです。</p>
<p>ポーリング型のキーロガーは、キーの入力状態をチェックするWindowsのAPIを利用して実装されており、代表的には <a href="https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-getasynckeystate"><code>GetAsyncKeyState</code></a> APIが利用されます。このAPIは、特定のキーが現在押されているか否かに加えて、その特定のキーが前回のAPI呼び出し以降押されたか否かの情報を取得することが出来ます。以下が<code>GetAsyncKeyState</code> APIを使ったポーリング型キーロガーの簡単な例です。</p>
<pre><code>while(true)
{
    for (int key = 1; key &lt;= 255; key++)
    {
        if (GetAsyncKeyState(key) &amp; 0x01)
        {
            SaveTheKey(key, "log.txt");
        }
    }
    Sleep(50);
}
</code></pre>
<p>ポーリング(<code>GetAsyncKeyState</code>)を用いてキー押下状態を取得する手法は、古くから存在する典型的なキーロギングの手法として知られているだけでなく、今でもマルウェアによって使われていることが確認されています。</p>
<ol>
<li>フッキング型キーロガー</li>
</ol>
<p>フッキング型キーロガーは、ポーリング型キーロガーと同じく、古くから存在する典型的な種類のキーロガーです。ここではまず「そもそもフックとは何か？」について説明します。</p>
<p>フックとは大雑把に言うと「アプリケーションの特定の処理に、独自の処理を割り込ませる仕組み」のことを指す言葉です。そして、フックを使って独自の処理を割り込ませることを「フックする」とも言います。Windowsでは、アプリケーションに対するキー入力などのメッセージ(イベント)をフックすることが出来る仕組みが用意されており、この仕組みは<a href="https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-setwindowshookexa">SetWindowsHookEx</a> APIを通じて利用することが出来ます。以下が<code>SetWindowsHookEx</code> APIを使ったポーリング型キーロガーの簡単な例です。</p>
<pre><code>HMODULE hHookLibrary = LoadLibraryW(L"hook.dll");
FARPROC hookFunc = GetProcAddress(hHookLibrary, "SaveTheKey");

HHOOK keyboardHook = NULL;

keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL,
                (HOOKPROC)hookFunc,
                hHookLibrary,
                0);
</code></pre>
<ol>
<li>Raw Input Modelを用いたキーロガー</li>
</ol>
<p>このタイプのキーロガーは、キーボードなどの入力デバイスから得られた、生の入力データ(Raw Input)を取得し、それを保存・記録します。このキーロガーの詳細について説明する前に、まずWindowsにおける入力方式である「Original Input Model」と「Raw Input Model」について理解する必要があります。以下がそれぞれの入力方式についての説明です。</p>
<ul>
<li><strong>Original Input Model</strong>:  キーボードなどの入力デバイスから入力されたデータを、一度OSを介して必要な処理をした後、アプリケーション側に届ける方式</li>
<li><strong>Raw Input Model</strong>:  キーボードなどの入力デバイスから入力されたデータを、そのままアプリケーション側が直接受け取る方式</li>
</ul>
<p>Windowsでは当初、Original Input Modelのみが使われていました。しかしWindows XP以降に、おそらくは入力デバイスの多様化などの要因から、Raw Input Modelが導入されました。Raw Input Modelでは、<a href="https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-registerrawinputdevices"><code>RegisterRawInputDevices</code></a> APIを使い、入力データを直接受け取りたい入力デバイスを登録します。そしてその後、<a href="https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-getrawinputdata"><code>GetRawInputData</code></a>) APIを用いて生データを取得します。
以下がこれらのAPIを使った、Raw Input Modelを用いたキーロガーの簡単な例です。</p>
<pre><code>LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{

    UINT dwSize = 0;
    RAWINPUT* buffer = NULL;

    switch (uMessage)
    {
    case WM_CREATE:
        RAWINPUTDEVICE rid;
        rid.usUsagePage = 0x01;  // HID_USAGE_PAGE_GENERIC
        rid.usUsage = 0x06;      // HID_USAGE_GENERIC_KEYBOARD
        rid.dwFlags = RIDEV_NOLEGACY | RIDEV_INPUTSINK;
        rid.hwndTarget = hWnd;
        RegisterRawInputDevices(&amp;rid, 1, sizeof(rid));
        break;
    case WM_INPUT:
        GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL,
&amp;dwSize, sizeof(RAWINPUTHEADER));

        buffer = (RAWINPUT*)HeapAlloc(GetProcessHeap(), 0, dwSize);

        if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, buffer, 
&amp;dwSize, sizeof(RAWINPUTHEADER)))
        {
            if (buffer-&gt;header.dwType == RIM_TYPEKEYBOARD)
            {
                SaveTheKey(buffer, "log.txt");
            }
        }
        HeapFree(GetProcessHeap(), 0, buffer);
        break;
    default:
        return DefWindowProc(hWnd, uMessage, wParam, lParam);
    }
    return 0;
}
</code></pre>
<p>この例では、最初に生入力を受け取りたい入力デバイスを<code>RegisterRawInputDevices</code>を用いて、登録します。ここでは、キーボードの生入力データを受け取るように設定・登録しています。</p>
<ol>
<li><code>DirectInput</code>を用いたキーロガー</li>
</ol>
<p>最後に、<code>DirectInput</code>を用いたキーロガーについて説明します。このキーロガーは簡単に言えばMicrosoft DirectXの機能を悪用したキーロガーです。DirectXとは、ゲームや動画などのマルチメディア関連の処理を扱うためのAPI群の総称(ライブラリ)です。</p>
<p>ゲームにおいて、ユーザから各種入力が取得できることは必須機能と言って良いことから、DirectXにおいてもユーザの入力を処理するAPI群が提供されています。そして、DirectXのバージョン8以前に提供されていたそれらAPI群のことを「DirectInput」と呼びます。以下が<code>DirectInput</code>に関連するAPIを使ったキーロガーの簡単な例です。補足ですが、<code>DirectInput</code>を用いてキーを取得する際、裏では<code>RegisterRawInputDevices</code> APIが呼ばれています。</p>
<pre><code>LPDIRECTINPUT8        lpDI = NULL;
LPDIRECTINPUTDEVICE8    lpKeyboard = NULL;

BYTE key[256];
ZeroMemory(key, sizeof(key));

DirectInput8Create(hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&amp;lpDI, NULL);
lpDI-&gt;CreateDevice(GUID_SysKeyboard, &amp;lpKeyboard, NULL);
lpKeyboard-&gt;SetDataFormat(&amp;c_dfDIKeyboard);
lpKeyboard-&gt;SetCooperativeLevel(hwndMain, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE | DISCL_NOWINKEY);

while(true)
{
    HRESULT ret = lpKeyboard-&gt;GetDeviceState(sizeof(key), key);
    if (FAILED(ret)) {
        lpKeyboard-&gt;Acquire();
        lpKeyboard-&gt;GetDeviceState(sizeof(key), key);
    }
  SaveTheKey(key, "log.txt");    
    Sleep(50);
}
</code></pre>
<h2 id="windowsapi">Windows API呼び出しを監視してキーロガーを検出する</h2>
<p>Elastic Defendでは、Event Tracing for Windows (ETW ※4)を用いて、前述の種類のキーロガーを検知しています。具体的には、関連するWindows API群の呼び出しを監視し、その挙動のログを取得することで実現しています。監視するWindows API群と、付随して新規に作成したキーロガーの検知ルールは以下です。(※4 一言でいうとWindowsが提供する、アプリケーションやデバイスドライバなどのシステム側のコンポーネントを、トレースおよびロギングする仕組み。)</p>
<h3 id="windowsapi-1">監視するWindows API群:</h3>
<ul>
<li><a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getasynckeystate">GetAsyncKeyState</a></li>
<li><a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexw">SetWindowsHookEx</a></li>
<li><a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerrawinputdevices">RegisterRawInputDevice</a></li>
</ul>
<h3 id="-3">追加したキーロガー検知ルール一覧:</h3>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_getasynckeystate_api_call_from_suspicious_process.toml">GetAsyncKeyState API Call from Suspicious Process</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_getasynckeystate_api_call_from_unusual_process.toml">GetAsyncKeyState API Call from Unusual Process</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_keystroke_input_capture_via_directinput.toml">Keystroke Input Capture via DirectInput</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_keystroke_input_capture_via_registerrawinputdevices.toml">Keystroke Input Capture via RegisterRawInputDevices</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_keystroke_messages_hooking_via_setwindowshookex.toml">Keystroke Messages Hooking via SetWindowsHookEx</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_keystrokes_input_capture_from_a_managed_application.toml">Keystrokes Input Capture from a Managed Application</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_keystrokes_input_capture_from_a_suspicious_module.toml">Keystrokes Input Capture from a Suspicious Module</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_keystrokes_input_capture_from_suspicious_callstack.toml">Keystrokes Input Capture from Suspicious CallStack</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_keystrokes_input_capture_from_unsigned_dll.toml">Keystrokes Input Capture from Unsigned DLL</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_keystrokes_input_capture_via_setwindowshookex.toml">Keystrokes Input Capture via SetWindowsHookEx</a></li>
</ul>
<p>新規に追加した機能および検知ルールにより、Elastic Defendにてキーロガー・キーロギングの包括的な監視と検出が可能となり、これらの脅威に対するWindowsエンドポイントのセキュリティと保護の強化を実現しました。</p>
<h3 id="windows">Windowsのキーロガーを検知する</h3>
<p>次に実際の検知の様子をお見せします。例として、Raw Input Modelを用いたキーロガーをElastic Defendで検出してみます。ここでは<code>RegisterRawInputDevices</code> APIを用いた簡易的なキーロガー「Keylogger.exe」を用意し、テスト環境で実行してみました※5。(※5 実行環境はWindows 10の執筆時点の最新版であるWindows 10 Version 22H2 19045.4412です。)</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9ab2a05716d2ed5d/6a856cafba7acc17fb990e28/image1.png" alt="Elastic Securityのアラート" title="Elastic Securityのアラート" /></p>
<p>キーロガーを実行した直後に、検知ルール(<a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_keystroke_input_capture_via_registerrawinputdevices.toml">Keystroke Input Capture via <code>RegisterRawInputDevices</code></a>)が発動し、エンドポイント側でアラートが上がりました。このアラートのさらなる詳細はKibana上から見ることが出来ます。</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte5588266862e2369/6a856cb29a32f154a3a7ccec/image3.png" alt="Elastic Securityのアラートダッシュボード" title="Elastic Securityのアラートダッシュボード" /></p>
<p>以下が検知ルールの詳細です。検知に使われているAPIの部分を中心に説明します。</p>
<pre><code>query = '''
api where
 process.Ext.api.name == "RegisterRawInputDevices" and not process.code_signature.status : "trusted" and
 process.Ext.api.parameters.usage : ("HID_USAGE_GENERIC_KEYBOARD", "KEYBOARD") and
 process.Ext.api.parameters.flags : "*INPUTSINK*" and process.thread.Ext.call_stack_summary : "?*" and
 process.thread.Ext.call_stack_final_user_module.hash.sha256 != null and process.executable != null and
 not process.thread.Ext.call_stack_final_user_module.path :
                         ("*\\program files*", "*\\windows\\system32\\*", "*\\windows\\syswow64\\*",
                          "*\\windows\\systemapps\\*",
                          "*\\users\\*\\appdata\\local\\*\\kumospace.exe",
                          "*\\users\\*\\appdata\\local\\microsoft\\teams\\current\\teams.exe") and 
 not process.executable : ("?:\\Program Files\\*.exe", "?:\\Program Files (x86)\\*.exe")
'''
</code></pre>
<p>このアラートは簡単に言うと「署名されていないプロセス」または「署名されているが、その署名者が信頼できないプロセス」が、キー入力を取得する目的で<code>RegisterRawInputDevices</code>  APIを呼び出した時に発せられるアラートです。<code>RegisterRawInputDevices</code> APIが呼び出された際の引数の情報に着目しており、より具体的にはAPIの第一引数である、<a href="https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/ns-winuser-rawinputdevice">RAWINPUTDEVICE</a>構造体のメンバの情報を検知に用いています。</p>
<p>この引数の値が、キーボード入力の取得を試みていることを示している場合、キーロガーが実行されたと見なして、アラートを上げるようになっています。 <code>RegisterRawInputDevices</code> APIのログはKibana上でも確認できます。</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt32b1877484597e62/6a856cb60782900263320408/image2.png" alt="Kibana上で確認できるRegisterRawInputDevices APIログ" title="Kibana上で確認できるRegisterRawInputDevices APIログ" /></p>
<h3 id="windowsapi-2">各Windows APIの呼び出しの際に取得しているデータ</h3>
<p>分量の都合で、追加したすべての検知ルールとAPIの詳細については本記事では説明しません。ですが最後に、対象のWindows APIの呼び出しの際にElastic Defend側で取得しているデータについて、簡単にご紹介します。各項目についてさらに知りたい方は、<a href="https://github.com/elastic/endpoint-package/blob/main/custom_schemas/custom_api.yml">custom_api.yml</a>に記載されているElastic Common Schema（ECS）とのマッピングをご参照ください。</p>
<p>| API名 | フィールド | 説明(原文を日本語訳したもの) | 例 |
| --- | --- | --- | --- |
| GetAsyncKeyState | process.Ext.api.metadata.ms_since_last_keyevent | このパラメーターは、最後の GetAsyncKeyState イベントからの経過時間をミリ秒で示します。 | 94 |
| GetAsyncKeyState | process.Ext.api.metadata.background_callcount | このパラメーターは、最後に成功した GetAsyncKeyState 呼び出しからの間に行われた、失敗した呼び出しも含めたすべての GetAsyncKeyState API 呼び出しの回数を示します。 | 6021 |
| SetWindowsHookEx | process.Ext.api.parameters.hook_type | Tインストールするフックの種類 | "WH_KEYBOARD_LL"
| SetWindowsHookEx | process.Ext.api.parameters.hook_module | フック先の処理を保有するDLL | "c:\windows\system32\taskbar.dll"
| SetWindowsHookEx | process.Ext.api.parameters.procedure | フック先となる処理や関数のメモリアドレス | 2431737462784 |
| SetWindowsHookEx | process.Ext.api.metadata.procedure_symbol | フック先の処理の要約 | "taskbar.dll" |
| RegisterRawInputDevices | process.Ext.api.metadata.return_value | RegisterRawInputDevices API 呼び出しの戻り値 | 1 |
| RegisterRawInputDevices | process.Ext.api.parameters.usage_page | このパラメーターはデバイスのトップレベルコレクション（Usage Page）を示す。RAWINPUTDEVICE 構造体の最初のメンバ | "GENERIC" |
| RegisterRawInputDevices | process.Ext.api.parameters.usage | このパラメーターは、Usage Page 内の特定のデバイス（Usage）を示します。RAWINPUTDEVICE 構造体の２番目のメンバ | "KEYBOARD" |
| RegisterRawInputDevices | process.Ext.api.parameters.flags | UsagePageとUsageによって提供される情報をどのように解釈するかを指定するモードフラグ。RAWINPUTDEVICE 構造体の３番目のメンバ | "INPUTSINK" |
| RegisterRawInputDevices | process.Ext.api.metadata.windows_count | 呼び出し元スレッドが所有するウィンドウの数 | 2 |
| RegisterRawInputDevices | process.Ext.api.metadata.visible_windows_count | 呼び出し元スレッドが所有する表示されているウィンドウの数 | 0 |
| RegisterRawInputDevices | process.Ext.api.metadata.thread_info_flags | スレッドの情報を表すフラグ | 16 |
| RegisterRawInputDevices | process.Ext.api.metadata.start_address_module | スレッドの開始アドレスに紐づくモジュールの名前 | "C:\Windows\System32\DellTPad\ApMsgFwd.exe" |
| RegisterRawInputDevices | process.Ext.api.metadata.start_address_allocation_protection | スレッドの開始アドレスに紐づくメモリ保護属性 | "RCX" |</p>
<h2 id="-4">まとめ</h2>
<p>本記事では、Elastic Defend 8.12にて導入された、Windows環境におけるキーロガーおよびキーロギング検知機能についてご紹介しました。具体的には、キーロギングに関連する代表的なWindows API群の呼び出しを監視することで、シグネチャに依存しない、振る舞い検知によるキーロガー検出を実現しました。精度を高め、誤検知率を減らすために、数ヶ月にわたる研究・調査をもとにこの機能と新しいルールを開発しました。</p>
<p>Elastic Defendではキーロガー関連のAPI以外にも、攻撃者に一般的に利用されるメモリ操作等の<a href="https://www.elastic.co/security-labs/doubling-down-etw-callstacks">API群なども監視すること</a>で、多層的な防御を実現しております。Elastic Security および Elastic Defendについて気になった方はぜひ<a href="https://www.elastic.co/jp/security">製品ページ</a>や<a href="https://www.elastic.co/jp/videos/intro-elastic-security">ドキュメント</a>を御覧頂ければ幸いです。</p>]]></content:encoded>
    <link>https://www.elastic.co/security-labs/blog/protecting-your-devices-from-information-theft-keylogger-protection</link>
    <guid isPermaLink="false">protecting-your-devices-from-information-theft-keylogger-protection</guid>
    <category><![CDATA[Endpoint Protection & Security]]></category>
    <dc:creator><![CDATA[Asuka Nakajima]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt32edc7c676cd809b/6a856cb9f61d6e36ae9c1888/Security_Labs_Images_10.jpg" length="0" type="image/jpeg"/>
    <pubDate>Thu, 30 May 2024 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[情報窃取から端末を守る]]></title>
    <description><![CDATA[本記事ではElastic Securityにおいて、エンドポイント保護を担っているElastic Defendに今年(バージョン8.12より)新たに追加された、キーロガーおよびキーロギング検出機能について紹介します。]]></description>
    <content:encoded><![CDATA[<p>本記事ではElastic Securityにおいて、エンドポイント保護を担っているElastic Defendに今年(バージョン<a href="https://www.elastic.co/guide/en/security/8.12/release-notes-header-8.12.0.html#enhancements-8.12.0">8.12</a>より)新たに追加された、キーロガーおよびキーロギング検出機能について紹介します。</p>
<h2>はじめに</h2>
<p>Elastic Defend 8.12より、Windows上で動作するキーロガーおよび、キーロギング機能を備えたマルウェア(情報窃取型マルウェアや、リモートアクセス型トロイの木馬、通称RAT)の検知の強化を目的に、キーロガーが使用する代表的なWindows API群の呼び出しを監視・記録する機能が追加されました。本記事ではこの新機能に焦点を当て、その技術的な詳細を解説します。加えて、本機能に付随して新たに作成された振る舞い検知ルール(Prebuilt rule)についても紹介します。</p>
<h3 id="-1">キーロガーとはなにか？どのような危険性があるのか？</h3>
<p>キーロガーとは、コンピュータ上で入力されたキーの内容を監視および記録(キーロギング)するソフトウェアの一種です(※1)。キーロガーは、ユーザのモニタリングなどの正当な理由で利用されることもありますが、攻撃者によって頻繁に悪用されるソフトウェアです。具体的には、ユーザがキーボード経由で入力した認証情報やクレジットカード情報、各種機密情報などのセンシティブな情報の窃取などに際に使われます。(※1: パソコンにUSB等で直接取り付けるようなハードウェア型のキーロガーもありますが、本記事ではソフトウェア型のキーロガーに焦点を当てます。)</p>
<p>キーロガーを通じて入手したセンシティブな情報は、金銭の窃取やさらなるサイバー攻撃の足がかりに悪用されます。それゆえに、キーロギング行為自体は直接的にコンピュータに被害をおよばさないものの、続くサイバー攻撃の被害を食い止めるためにも、早期の検知が非常に重要だと言えます。</p>
<p>キーロギング機能を持つマルウェアは多々あり、特にRAT、情報窃取型マルウェア、バンキングマルウェアといった種類のマルウェアにキーロギング機能が搭載されている場合があることが確認されています。有名なマルウェアでキーロギング機能を有するものとしては<a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.agent_tesla">Agent Tesla</a>や<a href="https://malpedia.caad.fkie.fraunhofer.de/details/apk.lokibot">Lokibit</a>、そして<a href="https://malpedia.caad.fkie.fraunhofer.de/details/win.404keylogger">SnakeKeylogger</a>などが挙げられます。</p>
<h3 id="-2">いかにして入力した文字を盗み取っているのか？</h3>
<p>では次に、キーロガーはいかにしてユーザがキーボードから入力した文字を、ユーザに気づかれること無く盗み取っているのかを、技術的な観点から説明していきます。キーロガー自体は、あらゆるOS環境(Windows/Linux/macOSやモバイルデバイス)で存在しうるものではありますが、本記事ではWindowsのキーロガーに焦点を絞って解説します。特にWindows APIや機能を使用してキー入力を取得する4つの異なるタイプのキーロガーについて解説します。</p>
<p>一点補足としては、ここでキーロギングの手法について説明しているのは、あくまで本記事後半で紹介している、新しい検知機能についての理解を深めていただくためです。そのため、例として掲載しているコードはあくまで単なる例であり、実際にそのまま動くコードが掲載されている訳ではありません(※3)。</p>
<p>(※2:  Windows上で動作するキーロガーは、カーネル空間(OS)側に設置されるものと、通常のアプリケーションと同じ領域(ユーザ空間)に設置されるものに大別されます。本記事では、後者のタイプを取り上げます。 )
(※3: 以下に掲載されている例のコードを元にキーロガーを作成し悪用した場合、弊社では対応、および、責任について負いかねます 。)</p>
<ol>
<li>ポーリング型キーロガー</li>
</ol>
<p>このタイプのキーロガーは、キーボードの各キーの状態(キーが押された否か)を短い間隔(1秒よりはるかに短い間隔)で定期的に確認します。そして前回の確認以降に、新たに押されたキーがあることが判明した場合、その押されたキーの文字の情報を記録・保存します。この一連の流れを繰り返すことで、キーロガーは、ユーザが入力した文字列の情報を取得しているのです。</p>
<p>ポーリング型のキーロガーは、キーの入力状態をチェックするWindowsのAPIを利用して実装されており、代表的には <a href="https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-getasynckeystate"><code>GetAsyncKeyState</code></a> APIが利用されます。このAPIは、特定のキーが現在押されているか否かに加えて、その特定のキーが前回のAPI呼び出し以降押されたか否かの情報を取得することが出来ます。以下が<code>GetAsyncKeyState</code> APIを使ったポーリング型キーロガーの簡単な例です。</p>
<pre><code>while(true)
{
    for (int key = 1; key &lt;= 255; key++)
    {
        if (GetAsyncKeyState(key) &amp; 0x01)
        {
            SaveTheKey(key, "log.txt");
        }
    }
    Sleep(50);
}
</code></pre>
<p>ポーリング(<code>GetAsyncKeyState</code>)を用いてキー押下状態を取得する手法は、古くから存在する典型的なキーロギングの手法として知られているだけでなく、今でもマルウェアによって使われていることが確認されています。</p>
<ol>
<li>フッキング型キーロガー</li>
</ol>
<p>フッキング型キーロガーは、ポーリング型キーロガーと同じく、古くから存在する典型的な種類のキーロガーです。ここではまず「そもそもフックとは何か？」について説明します。</p>
<p>フックとは大雑把に言うと「アプリケーションの特定の処理に、独自の処理を割り込ませる仕組み」のことを指す言葉です。そして、フックを使って独自の処理を割り込ませることを「フックする」とも言います。Windowsでは、アプリケーションに対するキー入力などのメッセージ(イベント)をフックすることが出来る仕組みが用意されており、この仕組みは<a href="https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-setwindowshookexa">SetWindowsHookEx</a> APIを通じて利用することが出来ます。以下が<code>SetWindowsHookEx</code> APIを使ったポーリング型キーロガーの簡単な例です。</p>
<pre><code>HMODULE hHookLibrary = LoadLibraryW(L"hook.dll");
FARPROC hookFunc = GetProcAddress(hHookLibrary, "SaveTheKey");

HHOOK keyboardHook = NULL;

keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL,
                (HOOKPROC)hookFunc,
                hHookLibrary,
                0);
</code></pre>
<ol>
<li>Raw Input Modelを用いたキーロガー</li>
</ol>
<p>このタイプのキーロガーは、キーボードなどの入力デバイスから得られた、生の入力データ(Raw Input)を取得し、それを保存・記録します。このキーロガーの詳細について説明する前に、まずWindowsにおける入力方式である「Original Input Model」と「Raw Input Model」について理解する必要があります。以下がそれぞれの入力方式についての説明です。</p>
<ul>
<li><strong>Original Input Model</strong>:  キーボードなどの入力デバイスから入力されたデータを、一度OSを介して必要な処理をした後、アプリケーション側に届ける方式</li>
<li><strong>Raw Input Model</strong>:  キーボードなどの入力デバイスから入力されたデータを、そのままアプリケーション側が直接受け取る方式</li>
</ul>
<p>Windowsでは当初、Original Input Modelのみが使われていました。しかしWindows XP以降に、おそらくは入力デバイスの多様化などの要因から、Raw Input Modelが導入されました。Raw Input Modelでは、<a href="https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-registerrawinputdevices"><code>RegisterRawInputDevices</code></a> APIを使い、入力データを直接受け取りたい入力デバイスを登録します。そしてその後、<a href="https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-getrawinputdata"><code>GetRawInputData</code></a>) APIを用いて生データを取得します。
以下がこれらのAPIを使った、Raw Input Modelを用いたキーロガーの簡単な例です。</p>
<pre><code>LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{

    UINT dwSize = 0;
    RAWINPUT* buffer = NULL;

    switch (uMessage)
    {
    case WM_CREATE:
        RAWINPUTDEVICE rid;
        rid.usUsagePage = 0x01;  // HID_USAGE_PAGE_GENERIC
        rid.usUsage = 0x06;      // HID_USAGE_GENERIC_KEYBOARD
        rid.dwFlags = RIDEV_NOLEGACY | RIDEV_INPUTSINK;
        rid.hwndTarget = hWnd;
        RegisterRawInputDevices(&amp;rid, 1, sizeof(rid));
        break;
    case WM_INPUT:
        GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL,
&amp;dwSize, sizeof(RAWINPUTHEADER));

        buffer = (RAWINPUT*)HeapAlloc(GetProcessHeap(), 0, dwSize);

        if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, buffer, 
&amp;dwSize, sizeof(RAWINPUTHEADER)))
        {
            if (buffer-&gt;header.dwType == RIM_TYPEKEYBOARD)
            {
                SaveTheKey(buffer, "log.txt");
            }
        }
        HeapFree(GetProcessHeap(), 0, buffer);
        break;
    default:
        return DefWindowProc(hWnd, uMessage, wParam, lParam);
    }
    return 0;
}
</code></pre>
<p>この例では、最初に生入力を受け取りたい入力デバイスを<code>RegisterRawInputDevices</code>を用いて、登録します。ここでは、キーボードの生入力データを受け取るように設定・登録しています。</p>
<ol>
<li><code>DirectInput</code>を用いたキーロガー</li>
</ol>
<p>最後に、<code>DirectInput</code>を用いたキーロガーについて説明します。このキーロガーは簡単に言えばMicrosoft DirectXの機能を悪用したキーロガーです。DirectXとは、ゲームや動画などのマルチメディア関連の処理を扱うためのAPI群の総称(ライブラリ)です。</p>
<p>ゲームにおいて、ユーザから各種入力が取得できることは必須機能と言って良いことから、DirectXにおいてもユーザの入力を処理するAPI群が提供されています。そして、DirectXのバージョン8以前に提供されていたそれらAPI群のことを「DirectInput」と呼びます。以下が<code>DirectInput</code>に関連するAPIを使ったキーロガーの簡単な例です。補足ですが、<code>DirectInput</code>を用いてキーを取得する際、裏では<code>RegisterRawInputDevices</code> APIが呼ばれています。</p>
<pre><code>LPDIRECTINPUT8        lpDI = NULL;
LPDIRECTINPUTDEVICE8    lpKeyboard = NULL;

BYTE key[256];
ZeroMemory(key, sizeof(key));

DirectInput8Create(hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&amp;lpDI, NULL);
lpDI-&gt;CreateDevice(GUID_SysKeyboard, &amp;lpKeyboard, NULL);
lpKeyboard-&gt;SetDataFormat(&amp;c_dfDIKeyboard);
lpKeyboard-&gt;SetCooperativeLevel(hwndMain, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE | DISCL_NOWINKEY);

while(true)
{
    HRESULT ret = lpKeyboard-&gt;GetDeviceState(sizeof(key), key);
    if (FAILED(ret)) {
        lpKeyboard-&gt;Acquire();
        lpKeyboard-&gt;GetDeviceState(sizeof(key), key);
    }
  SaveTheKey(key, "log.txt");    
    Sleep(50);
}
</code></pre>
<h2 id="windowsapi">Windows API呼び出しを監視してキーロガーを検出する</h2>
<p>Elastic Defendでは、Event Tracing for Windows (ETW ※4)を用いて、前述の種類のキーロガーを検知しています。具体的には、関連するWindows API群の呼び出しを監視し、その挙動のログを取得することで実現しています。監視するWindows API群と、付随して新規に作成したキーロガーの検知ルールは以下です。(※4 一言でいうとWindowsが提供する、アプリケーションやデバイスドライバなどのシステム側のコンポーネントを、トレースおよびロギングする仕組み。)</p>
<h3 id="windowsapi-1">監視するWindows API群:</h3>
<ul>
<li><a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getasynckeystate">GetAsyncKeyState</a></li>
<li><a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexw">SetWindowsHookEx</a></li>
<li><a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerrawinputdevices">RegisterRawInputDevice</a></li>
</ul>
<h3 id="-3">追加したキーロガー検知ルール一覧:</h3>
<ul>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_getasynckeystate_api_call_from_suspicious_process.toml">GetAsyncKeyState API Call from Suspicious Process</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_getasynckeystate_api_call_from_unusual_process.toml">GetAsyncKeyState API Call from Unusual Process</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_keystroke_input_capture_via_directinput.toml">Keystroke Input Capture via DirectInput</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_keystroke_input_capture_via_registerrawinputdevices.toml">Keystroke Input Capture via RegisterRawInputDevices</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_keystroke_messages_hooking_via_setwindowshookex.toml">Keystroke Messages Hooking via SetWindowsHookEx</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_keystrokes_input_capture_from_a_managed_application.toml">Keystrokes Input Capture from a Managed Application</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_keystrokes_input_capture_from_a_suspicious_module.toml">Keystrokes Input Capture from a Suspicious Module</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_keystrokes_input_capture_from_suspicious_callstack.toml">Keystrokes Input Capture from Suspicious CallStack</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_keystrokes_input_capture_from_unsigned_dll.toml">Keystrokes Input Capture from Unsigned DLL</a></li>
<li><a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_keystrokes_input_capture_via_setwindowshookex.toml">Keystrokes Input Capture via SetWindowsHookEx</a></li>
</ul>
<p>新規に追加した機能および検知ルールにより、Elastic Defendにてキーロガー・キーロギングの包括的な監視と検出が可能となり、これらの脅威に対するWindowsエンドポイントのセキュリティと保護の強化を実現しました。</p>
<h3 id="windows">Windowsのキーロガーを検知する</h3>
<p>次に実際の検知の様子をお見せします。例として、Raw Input Modelを用いたキーロガーをElastic Defendで検出してみます。ここでは<code>RegisterRawInputDevices</code> APIを用いた簡易的なキーロガー「Keylogger.exe」を用意し、テスト環境で実行してみました※5。(※5 実行環境はWindows 10の執筆時点の最新版であるWindows 10 Version 22H2 19045.4412です。)</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt45d4ec5f07335e04/6a7d83e2bd219817c775530c/image1.png" alt="Elastic Securityのアラート" /></p>
<p>キーロガーを実行した直後に、検知ルール(<a href="https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/collection_keystroke_input_capture_via_registerrawinputdevices.toml">Keystroke Input Capture via <code>RegisterRawInputDevices</code></a>)が発動し、エンドポイント側でアラートが上がりました。このアラートのさらなる詳細はKibana上から見ることが出来ます。</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9965e04bb9eb282d/6a7d83e55967e542625da580/image3.png" alt="Elastic Securityのアラートダッシュボード" /></p>
<p>以下が検知ルールの詳細です。検知に使われているAPIの部分を中心に説明します。</p>
<pre><code>query = '''
api where
 process.Ext.api.name == "RegisterRawInputDevices" and not process.code_signature.status : "trusted" and
 process.Ext.api.parameters.usage : ("HID_USAGE_GENERIC_KEYBOARD", "KEYBOARD") and
 process.Ext.api.parameters.flags : "*INPUTSINK*" and process.thread.Ext.call_stack_summary : "?*" and
 process.thread.Ext.call_stack_final_user_module.hash.sha256 != null and process.executable != null and
 not process.thread.Ext.call_stack_final_user_module.path :
                         ("*\\program files*", "*\\windows\\system32\\*", "*\\windows\\syswow64\\*",
                          "*\\windows\\systemapps\\*",
                          "*\\users\\*\\appdata\\local\\*\\kumospace.exe",
                          "*\\users\\*\\appdata\\local\\microsoft\\teams\\current\\teams.exe") and 
 not process.executable : ("?:\\Program Files\\*.exe", "?:\\Program Files (x86)\\*.exe")
'''
</code></pre>
<p>このアラートは簡単に言うと「署名されていないプロセス」または「署名されているが、その署名者が信頼できないプロセス」が、キー入力を取得する目的で<code>RegisterRawInputDevices</code>  APIを呼び出した時に発せられるアラートです。<code>RegisterRawInputDevices</code> APIが呼び出された際の引数の情報に着目しており、より具体的にはAPIの第一引数である、<a href="https://learn.microsoft.com/ja-jp/windows/win32/api/winuser/ns-winuser-rawinputdevice">RAWINPUTDEVICE</a>構造体のメンバの情報を検知に用いています。</p>
<p>この引数の値が、キーボード入力の取得を試みていることを示している場合、キーロガーが実行されたと見なして、アラートを上げるようになっています。 <code>RegisterRawInputDevices</code> APIのログはKibana上でも確認できます。</p>
<p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3acfb0688ab15e5d/6a7d83e91967eaf06f32d8e4/image2.png" alt="Kibana上で確認できるRegisterRawInputDevices APIログ" /></p>
<h3 id="windowsapi-2">各Windows APIの呼び出しの際に取得しているデータ</h3>
<p>分量の都合で、追加したすべての検知ルールとAPIの詳細については本記事では説明しません。ですが最後に、対象のWindows APIの呼び出しの際にElastic Defend側で取得しているデータについて、簡単にご紹介します。各項目についてさらに知りたい方は、<a href="https://github.com/elastic/endpoint-package/blob/main/custom_schemas/custom_api.yml">custom_api.yml</a>に記載されているElastic Common Schema（ECS）とのマッピングをご参照ください。</p>
<p>| API名 | フィールド | 説明(原文を日本語訳したもの) | 例 |
| --- | --- | --- | --- |
| GetAsyncKeyState | process.Ext.api.metadata.ms_since_last_keyevent | このパラメーターは、最後の GetAsyncKeyState イベントからの経過時間をミリ秒で示します。 | 94 |
| GetAsyncKeyState | process.Ext.api.metadata.background_callcount | このパラメーターは、最後に成功した GetAsyncKeyState 呼び出しからの間に行われた、失敗した呼び出しも含めたすべての GetAsyncKeyState API 呼び出しの回数を示します。 | 6021 |
| SetWindowsHookEx | process.Ext.api.parameters.hook_type | Tインストールするフックの種類 | "WH_KEYBOARD_LL"
| SetWindowsHookEx | process.Ext.api.parameters.hook_module | フック先の処理を保有するDLL | "c:\windows\system32\taskbar.dll"
| SetWindowsHookEx | process.Ext.api.parameters.procedure | フック先となる処理や関数のメモリアドレス | 2431737462784 |
| SetWindowsHookEx | process.Ext.api.metadata.procedure_symbol | フック先の処理の要約 | "taskbar.dll" |
| RegisterRawInputDevices | process.Ext.api.metadata.return_value | RegisterRawInputDevices API 呼び出しの戻り値 | 1 |
| RegisterRawInputDevices | process.Ext.api.parameters.usage_page | このパラメーターはデバイスのトップレベルコレクション（Usage Page）を示す。RAWINPUTDEVICE 構造体の最初のメンバ | "GENERIC" |
| RegisterRawInputDevices | process.Ext.api.parameters.usage | このパラメーターは、Usage Page 内の特定のデバイス（Usage）を示します。RAWINPUTDEVICE 構造体の２番目のメンバ | "KEYBOARD" |
| RegisterRawInputDevices | process.Ext.api.parameters.flags | UsagePageとUsageによって提供される情報をどのように解釈するかを指定するモードフラグ。RAWINPUTDEVICE 構造体の３番目のメンバ | "INPUTSINK" |
| RegisterRawInputDevices | process.Ext.api.metadata.windows_count | 呼び出し元スレッドが所有するウィンドウの数 | 2 |
| RegisterRawInputDevices | process.Ext.api.metadata.visible_windows_count | 呼び出し元スレッドが所有する表示されているウィンドウの数 | 0 |
| RegisterRawInputDevices | process.Ext.api.metadata.thread_info_flags | スレッドの情報を表すフラグ | 16 |
| RegisterRawInputDevices | process.Ext.api.metadata.start_address_module | スレッドの開始アドレスに紐づくモジュールの名前 | "C:\Windows\System32\DellTPad\ApMsgFwd.exe" |
| RegisterRawInputDevices | process.Ext.api.metadata.start_address_allocation_protection | スレッドの開始アドレスに紐づくメモリ保護属性 | "RCX" |</p>
<h2 id="-4">まとめ</h2>
<p>本記事では、Elastic Defend 8.12にて導入された、Windows環境におけるキーロガーおよびキーロギング検知機能についてご紹介しました。具体的には、キーロギングに関連する代表的なWindows API群の呼び出しを監視することで、シグネチャに依存しない、振る舞い検知によるキーロガー検出を実現しました。精度を高め、誤検知率を減らすために、数ヶ月にわたる研究・調査をもとにこの機能と新しいルールを開発しました。</p>
<p>Elastic Defendではキーロガー関連のAPI以外にも、攻撃者に一般的に利用されるメモリ操作等の<a href="https://www.elastic.co/security-labs/doubling-down-etw-callstacks">API群なども監視すること</a>で、多層的な防御を実現しております。Elastic Security および Elastic Defendについて気になった方はぜひ<a href="https://www.elastic.co/jp/security">製品ページ</a>や<a href="https://www.elastic.co/jp/videos/intro-elastic-security">ドキュメント</a>を御覧頂ければ幸いです。</p>]]></content:encoded>
    <link>https://www.elastic.co/security-labs/blog/protecting-your-devices-from-information-theft-keylogger-protection</link>
    <guid isPermaLink="false">protecting-your-devices-from-information-theft-keylogger-protection</guid>
    <category><![CDATA[Endpoint Protection & Security]]></category>
    <dc:creator><![CDATA[Asuka Nakajima]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfe1d0bd62f242193/6a7d83f9498cafd42601eec0/Security_Labs_Images_10.jpg" length="0" type="image/jpeg"/>
    <pubDate>Thu, 30 May 2024 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>