カーネルモードでのWindows関数の呼び出し

多くの皆さん、親愛なるKhabrovitesは、Windowsカーネルの機能を使用しています。 ただし、これらの関数がどのように呼び出されるかを誰もが想像できるわけではありません。 また、いくつかのカーネルメカニズムの知識は非常に役立ちます。



このテキストは、(理論的には)これをより深いレベルで知っているドライバー作成者を対象としていません。



そもそも、カーネルモードには、よく知られているすべてのWinAPIよりも多くの機能があります。 これは、文書化されていない多くの関数がカーネルに埋め込まれているためです(Win7およびWin8のリリースにより状況は改善されましたが、これらの関数の多くはMSDNに移行します)。 このような関数のリストは、たとえばここにあります。



これらの機能は、いくつかのグループに分類できます。





これはどのように呼ばれますか?



ユーザーモードから呼び出すことから始めましょう。



-まず、 NtDll.dll-ユーザーモードとカーネルモードの「レイヤー」を使用します。 必要なカーネル関数が含まれています。 この関数は、その番号をEAXレジスターに入れます。 これは、カーネルに既知の2つのテーブル、ServiceTableとArgumentTableのインデックスです。 特徴的に、この番号はOSの各バージョンに固有です。 多くの場合、WinXPからVistaに移行するときだけでなく、VistaからVista SP1に移行するときでも変化します。

-さらに、パラメータスタックの最上部のアドレスはEDXに配置されます。ほとんどの場合、これはESPレジスタの値です。 なぜ既存の値をコピーするのでしょうか? 実際には、割り込みが実行された後、プロセッサの状態全体がスタックにフラッシュされ、ESPは必要なものではなくなります。

-最後に、カーネルモードへの切り替えがあります。 古いプロセッサおよびシステムでは、これは0x2e割り込みを使用して行われます;最新のプロセッサでは、このための特別なプロセッサ命令があります:IntelのSysEnter 、AMDのSysCall

-呼び出しの結果は、アドレスが特定のセルのグローバル割り込みテーブルにあるコードのプロセッサによる実行です。 このコードは、割り込みの場合はKiSystemService()を、プロセッサへの特別な命令の場合はKiFastCallEntry()を呼び出します。 ちなみに、2番目のものは粗いレジスタMSRに登録されており、MSRにすばやくアクセスできます。

-さらに、カーネルで実行されるコードは、関数呼び出しがどこから来たのか、カーネルモードまたはユーザーモードから来たのかに応じて、少し異なる方法で実行されます。 カーネルコードのタスク:内部関数テーブルを使用してEAXから関数呼び出しを実行します。 このテーブルはKiServiceDescriptorTableと呼ばれます 。 これは、3つのフィールドを持つ構造です:







SysEnterおよびSysCall関数が呼び出されると、OS関数にディスパッチする必要があります。 各スレッドには、ユーザーモードとカーネルモードのスタックがあります。 OSはArgumentTableテーブルのセル値を受け取ります。このテーブルは、スタックでパラメーターが占めるバイト数を示します(このため、EDXを記憶しています)。 次に、このバイト数をカーネルスタックにコピーします。 その後、ServiceTableを介して関数呼び出しを行います。 もちろん、ユーザーモードの変更がカーネル内の関数の実行に悪影響を及ぼさないようにするために、2つのスタックでのこのようなトラブルはすべて必要です。



-関数が呼び出されて実行され、その操作が終了すると、カーネルモードからの復帰がiretまたはSysExit / SysRetツールを使用して実行されます。



カーネルモードでのカーネル関数の呼び出し。



原則として、すべて同じですが、...

カーネル関数のリストを注意深く見ると、 nt関数に完全に似ているが、接頭辞zw-の関数があることに気付くでしょう。 それらはすべて、nt関数に一意にマッピングされます。 ただし、カーネルモードでは、動作が異なります。



違いは、zw関数ではパラメーターが検証されないことです。 言い換えれば、ユーザーモードから呼び出す場合、システムは関数に渡されるパラメーターを注意深く監視します。神がプログラマーに何かを見逃すことを禁じ、そしてこんにちは、ブルースクリーン。 カーネルモードでは、主にドライバーで動作します。システムは、追加のチェックが貴重な時間を浪費するため、すべてのパラメーターを自分でチェックし、有効性を保証するとシステムは既に信じています。 これは次のように機能します。zwが呼び出されると、関数番号をEAXにロードし、カーネルスタックへのポインターをEDXに入れてから、検証しないntオプションを呼び出します。



これに関連して疑問が生じます-ユーザーモードからzw関数を終了するとどうなりますか? システムはすべてを許しますか? そうでもない。 zwがユーザーモードで呼び出される場合、ntツインを呼び出すだけです。



ここでは、一般に、カーネル関数の呼び出しに関するすべての基本情報。 あなたが興味を持っていたことを願っています。



All Articles