18

ネイティブ API では、Microsoft は各 API 呼び出しの 2 つのバージョンをエクスポートします。1 つは Zw で始まり、もう 1 つは Nt で始まります。ZwCreateThread と NtCreateThread。

私の質問は、呼び出しのこれら 2 つのバージョンの違いは何ですか?また、いつ、なぜ Zw または Nt を排他的に使用する必要があるのでしょうか? 私の理解では、Zw バージョンでは呼び出し元がカーネル モードに存在することが保証されますが、Nt ではそうではありません。

Zw および Nt 接頭辞/略語の特定の意味についても疑問に思っていますか? Nt はおそらく NT(New Technology) Windows ファミリまたは Native (おそらくそうではない) を指していると推測できますか? Zwは何かの略ですか?

4

2 に答える 2

16

アップデート:

Larry Osterman の回答 (必ず読む必要があります) とは別に、言及すべきことがもう 1 つあります。

NtXxx バリアントは、呼び出しがユーザー モードからのものであるかのようにチェックを実行するため、これは、NtXxs 関数に渡されるすべてのバッファーが kernel-mode ではなく、ユーザー モードのアドレス空間に存在する必要があることを意味します。したがってNtCreateFile、ドライバーのような関数を呼び出して、カーネル モード バッファーへのポインターを渡すと、STATUS_ACCESS_VIOLATIONこれにより a が返されます。


ネイティブ システム サービス ルーチンの Nt および Zw バージョンの使用を参照してください。

カーネル モード ドライバーは、ネイティブ システム サービス ルーチンの Zw バージョンを呼び出して、パラメーターが信頼できるカーネル モード ソースからのものであることをルーチンに通知します。この場合、ルーチンは、最初にパラメーターを検証しなくてもパラメーターを安全に使用できると想定します。ただし、パラメーターがユーザー モード ソースまたはカーネル モード ソースのいずれかからのものである可能性がある場合、ドライバーは代わりにルーチンの Nt バージョンを呼び出します。モードまたはカーネル モード。

ネイティブ システム サービス ルーチンは、受け取るパラメータについて追加の仮定を行います。カーネル モード ドライバーによって割り当てられたバッファーへのポインターをルーチンが受け取った場合、ルーチンは、バッファーがユーザー モード メモリではなく、システム メモリに割り当てられたと見なします。ルーチンがユーザー モード アプリケーションによって開かれたハンドルを受け取る場合、ルーチンは、カーネル モード ハンドル テーブルではなく、ユーザー モード ハンドル テーブルでハンドルを検索します。

また、Zw何の略でもありません。Zw プレフィックスの意味を参照してください。:

Windows ネイティブ システム サービス ルーチンの名前は、接頭辞 Nt および Zw で始まります。Nt プレフィックスは Windows NT の略語ですが、Zw プレフィックスには意味がありません。Zw が選択された理由の 1 つは、他の API との潜在的な名前の競合を回避するため、および将来必要になる可能性がある潜在的に有用な 2 文字のプレフィックスの使用を回避するためです。

于 2011-01-22T21:06:48.820 に答える
13

Merhdadの回答に対するコメントとしてこれを残すつもりでしたが、長すぎました...

Mehrdad の答えは 100% 正確です。また、少し誤解を招きます。「Using Nt and Zw...」の記事にリンクされている「PreviousMode」の記事では、Mehrdad がより詳細に説明しています言い換え: Nt API 呼び出しと Zw API 呼び出しの主な違いは、Zw 呼び出しがシステム コール ディスパッチャーを経由することですが、ドライバーの場合、Nt 呼び出しは API への直接呼び出しです。

ドライバーが Zw API を呼び出すとき、システム コール ディスパッチャーを実行することの唯一の実際の効果は、KeGetPreviousMode() を UserMode ではなく KernelMode に設定することです (明らかに、ユーザー モード コードでは、Zw と Nt の形式は同じです)。さまざまなシステム コールが ExGetPreviousMode が KernelMode であることを確認すると、アクセス チェックをバイパスします (ドライバーは何でもできるため)。

ドライバーが API の NT 形式を呼び出す場合、アクセス チェックが原因で失敗する可能性があります。

具体的な例: ドライバーが NtCreateFile を呼び出す場合、NtCreateFile は SeAccessCheck() を呼び出して、ドライバーを呼び出したアプリケーションがファイルを作成する権限を持っているかどうかを確認します。同じドライバーが ZwCreateFile を呼び出した場合、NtCreateFile API 呼び出しは SeAccessCheck を呼び出しません。これは、ExGetPreviousMode が KernelMode を返したため、ドライバーがファイルにアクセスできると見なされるためです。

ドライバーの作成者は、セキュリティに大きな影響を与える可能性があるため、2 つの違いを理解することが重要です...

于 2011-01-23T16:55:12.237 に答える