日本免费全黄少妇一区二区三区-高清无码一区二区三区四区-欧美中文字幕日韩在线观看-国产福利诱惑在线网站-国产中文字幕一区在线-亚洲欧美精品日韩一区-久久国产精品国产精品国产-国产精久久久久久一区二区三区-欧美亚洲国产精品久久久久

1 《Undocumented Windows 2000 Secrets》翻譯 --- 第二章( 二 )


Ntdll.dll 是一個(gè)操作系統(tǒng)組件,它為 Native API 準(zhǔn)確地提供服務(wù),ntdll.dll 是 Native API 在用戶(hù)模式下的前端 。Native API 真正的接口在 ntoskrnl.exe 中實(shí)現(xiàn) 。從其文件名可以猜出它就是 NT 操作系統(tǒng)內(nèi)核 。事實(shí)上,內(nèi)核模式驅(qū)動(dòng)程序?qū)ο到y(tǒng)服務(wù)的請(qǐng)求多數(shù)時(shí)候都會(huì)進(jìn)入該模塊 。Ntdll.dll 的主要任務(wù)就是為運(yùn)行于用戶(hù)模式的程序提供一個(gè)確定的內(nèi)核函數(shù)的子集,這其中就包括 Win32 子系統(tǒng) DLLs。在 圖 2-1 中,從 ntdll.dll 指向 ntoskrnl.exe 的箭頭旁標(biāo)注的 INT 2eh 表示 Windows 2000 使用此中斷將 CPU 特權(quán)級(jí)從用戶(hù)模式切換到內(nèi)核模式 。開(kāi)發(fā)內(nèi)核( kernel-mode )模式程序的人員認(rèn)為用戶(hù)模式的代碼是具有攻擊性的、充滿(mǎn)錯(cuò)誤的和危險(xiǎn)的 。因此,必須讓這些代碼遠(yuǎn)離內(nèi)核函數(shù) 。而通過(guò)在調(diào)用 API 的過(guò)程中將特權(quán)級(jí)別從用戶(hù)模式切換到內(nèi)核模式是一種可控制這些問(wèn)題的方式 。調(diào)用程序從來(lái)不可能觸及內(nèi)核,它只能察看它們 。
例如,由 kernel32.dll 導(dǎo)出的 Win32 API 函數(shù) DeviceIoControl() 最終會(huì)調(diào)用由 ntdll.dll 導(dǎo)出的 NtDeviceIoControlFile()。通過(guò)反編譯該函數(shù)會(huì)發(fā)現(xiàn)此函數(shù)令人驚訝的實(shí)現(xiàn)方式 — 它是如此的簡(jiǎn)單! 示列 2-1 展示了這些 。首先,CPU 寄存器 EAX 被裝入了一個(gè)“魔術(shù)”數(shù)字 0x38,這是一個(gè)分派 ID。接下來(lái),寄存器 EDX 被設(shè)置指向堆棧中的某處,其地址為堆棧指針 ESP 加上 4,因此,EDX 將指向堆棧中返回地址的后面,該返回地址在進(jìn)入 NtDeviceIoControlFile() 時(shí)將被立即保存下來(lái) 。顯而易見(jiàn),EDX 指向的位置是用來(lái)臨時(shí)存放傳遞進(jìn)來(lái)的參數(shù)的 。接下來(lái)的指令是一個(gè)簡(jiǎn)單的 INT 2eh,該指令將跳轉(zhuǎn)到中斷描述符表( Interrupt Descriptor Table,IDT )的 0x2e 位置上存放的中斷處理例程( interrupt handler )中 。這看上去是不是很熟悉?事實(shí)上,這有些像 Dos 下的 INT 21h 調(diào)用 。然而,Windows 2000 的 INT 2eh 接口要遠(yuǎn)比一個(gè)簡(jiǎn)單的 API 調(diào)用有用,分配器( dispatcher )利用它從用戶(hù)模式進(jìn)入內(nèi)核模式 。請(qǐng)注意,這種模式切換方式是 x86 處理器特有的 。在 Alpha 平臺(tái)上,有不同的方式來(lái)實(shí)現(xiàn)此種功能 。
NtDeviceIoControlFile:
mov eax, 38h
lea edx, [esp 4]
int 2Eh
ret 28h
示列 2-1. ntdll.NtDeviceIoControlFile() 的實(shí)現(xiàn)方式
Windows 2000 Native API 由 248 個(gè)函數(shù)組成,這些函數(shù)都采用上述方式進(jìn)入內(nèi)核 。與 Windows NT 4.0 相比多出了 37 個(gè) 。你很容易在 ntdll.dll 的導(dǎo)出列表中通過(guò) Nt 前綴來(lái)認(rèn)出它們 。Ntdll.dll 總共導(dǎo)出了 249 個(gè)這樣的符號(hào) 。多出的那個(gè)函數(shù)是 NtCurrentTeb(),該函數(shù)是一個(gè)純粹的用戶(hù)模式函數(shù),它無(wú)需進(jìn)入內(nèi)核 。附錄 B 中的 表 B-1 列出了所有可用的 Native API。該表同時(shí)還指出那個(gè)函數(shù)是由 ntoskrnl.exe 導(dǎo)出的 。令人奇怪的是,在處于內(nèi)核模式的模塊中,只能調(diào)用 Native API 的一個(gè)子集 。另一方面,ntoskrnl.exe 導(dǎo)出了兩個(gè) ntdll.dll 沒(méi)有提供的 Nt* 符號(hào)(指以 Nt 開(kāi)頭的符號(hào)): NtBuildNumber 和 NtGlobalFlag。這兩個(gè)符號(hào)都沒(méi)有指向函數(shù)的入口地址,而是指向 ntoskrnl.exe 中的變量 。驅(qū)動(dòng)模塊( driver module )可以使用 C 編譯器的 extern 關(guān)鍵字來(lái)導(dǎo)入這些變量 。Window 2000 采用此種方式導(dǎo)出了很多變量,稍后我將給出一個(gè)示例代碼來(lái)使用其中的幾個(gè) 。
你可能會(huì)奇怪為什么 表 B-1 (位于附錄 B 中)分別為 ntdll.dll 和 ntoskrnl.exe 提供了兩列,其名稱(chēng)分別為: ntdll.Nt* 、 ntdll.Zw* 和 ntoskrnl.Nt* 、 ntoskrnl.Zw*。原因是,這兩個(gè)模塊導(dǎo)出了兩組相互關(guān)聯(lián)的 Native API 符號(hào) 。在 表 B-1 (位于附錄 B 中)的最左列給出了所有名字中包含 Nt 前綴的符號(hào) 。另一個(gè)集合包含相似的名字,不過(guò)由 Zw 前綴代替了 Nt。反編譯 ndll.dll 可看出每對(duì)符號(hào)都指向相同的代碼 。這看起來(lái)似乎是浪費(fèi)內(nèi)存 。然而,如果你反編譯 ntoskrnl.exe,你就會(huì)發(fā)現(xiàn) Nt* 符號(hào)指向?qū)嶋H的代碼而 Zw* 指向 INT 2eh stubs (如 示列 2-1 列出的) 。這意味著 Zw* 函數(shù)集合將從用戶(hù)模式轉(zhuǎn)入內(nèi)核模式,而 Nt* 符號(hào)直接指向的代碼會(huì)在模式切換后被執(zhí)行 。

推薦閱讀