Ring3中的NATIVE API,和Ring0的系統調用,都有同名的Zw和Nt系列函數,一度讓初學者感到迷糊。N久前的我,也是相當的迷糊。現在就以ZwOpenProcess和NtOpenProcess函數爲例,詳細闡述下他們的分別和聯繫。
ntdll.dll導出了NtOpenProcess和ZwOpenProcess兩個函數,我們記爲ntdll!NtOpenProcess和ntdll!ZwOpenProcess。仔細看一下,會發現他們的入口點實際上都是一樣的,這就是說,ntdll!ZwOpenProcess僅僅是ntdll!NtOpenProcess函數的別名而已,實現如下:
ZwOpenProcess
.text:7C92D5FE mov eax, 7Ah ; NtOpenProcess
.text:7C92D603 mov edx, 7FFE0300h
.text:7C92D608 call dword ptr [edx]
.text:7C92D60A retn 10h
7FFE0300h處是ntdll!KiFastSystemCall的入口,ntdll!KiFastSystemCall會保存起當前的棧指針,然後通過引發0x2e中斷,陷入內核。
當觸發0x2e中斷後,CPU將執行環境切換到Ring0狀態,然後去調用內核模塊的0x2e處理例程nt!KiSystemService。nt!KiSystemService會在參數檢查、棧拷貝等操作之後,根據Ring3代碼傳遞過來的調用號0x7A,在SSDT中查找相應的函數地址,然後調用找到的函數。對於我們的例子來說,這個函數就是內核模塊的導出函數nt!NtOpenProcess。nt!NtOpenProcess纔是真正的打開進程實現函數。但是內核模塊也導出了nt!ZwOpenProcess,這個nt!ZwOpenProcess,有什麼用處呢?會不會像ntdll!ZwOpenProcess一樣,也僅僅是ntdll!NtOpenProcess的一個別名?實際上,nt!ZwOpenProcess並不僅僅是nt!NtOpenProcess一個別名,我們可以看一下nt!ZwOpenProcess的實現:
kd> u nt!ZwOpenProcess
nt!ZwOpenProcess:
804fede8 mov eax,7Ah
804feded lea edx,[esp+4]
804fedf1 pushfd
804fedf2 push 8
804fedf4 call nt!KiSystemService (8053d891)
804fedf9 ret 10h
與ntdll.ZwOpenProcess是不是很接近?nt!ZwOpenProcess也只是讓nt!KiSystemService調用SSDT中的第0x7A號函數,他自己本身沒有進行任何打開進程的實現。
到這兒,就可以總結一下了:用戶空間中的Zw***和Nt***的實現都是一樣的,比如ntdll!ZwOpenProcess和ntdll!NtOpenProcess的入口都是0x7C92D5FE,ntdll!ZwOpenFile和ntdll!NtOpenFile的入口都是0f7C92D59E。內核空間中的Zw函數,是Nt函數的一個Stup,只是mov系統調用號到eax中,轉而直接調用(注意,沒有像ntdll!ZwOpenProcess)nt!KiSystemService去從SSDT中找到相應號碼的函數再調用之,真正的實現都在Nt***函數中。
Zw函數與Nt函數的分別與聯繫
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.