Zw函數與Nt函數的分別與聯繫

Ring3中的NATIVE API,和Ring0的系統調用,都有同名的ZwNt系列函數,一度讓初學者感到迷糊。N久前的我,也是相當的迷糊。現在就以ZwOpenProcessNtOpenProcess函數爲例,詳細闡述下他們的分別和聯繫。
ntdll.dll導出了NtOpenProcessZwOpenProcess兩個函數,我們記爲ntdll!NtOpenProcessntdll!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!KiSystemServicent!KiSystemService會在參數檢查、棧拷貝等操作之後,根據Ring3代碼傳遞過來的調用號0x7A,在SSDT中查找相應的函數地址,然後調用找到的函數。對於我們的例子來說,這個函數就是內核模塊的導出函數nt!NtOpenProcessnt!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!ZwOpenProcessntdll!NtOpenProcess的入口都是0x7C92D5FEntdll!ZwOpenFilentdll!NtOpenFile的入口都是0f7C92D59E。內核空間中的Zw函數,是Nt函數的一個Stup,只是mov系統調用號到eax中,轉而直接調用(注意,沒有像ntdll!ZwOpenProcessnt!KiSystemService去從SSDT中找到相應號碼的函數再調用之,真正的實現都在Nt***函數中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章