Windows 的 native API 都有兩種 prefix 的開頭,Zw 和 Nt,例如 ZwCreateFile 和 NtCreateFile
user mode 的 native API 在 ntdll.dll 裡面,在 ntdll.dll 裡面實際上 Zw 開頭的 API 跟 Nt 開頭的 API 指向完全一樣的位置,user code 的 code 呼叫 Zw 或 Nt API 事實上是沒有分別的
kernel mode 的 native API 在 ntoskrnl.exe 裡面,在 kernel mode 中 Zw 跟 Nt API 就有分別了
先說 kernel mode 的 Zw API,例如 ZwCreateFile,它會先做一些事前準備,然後才呼叫到真正的 system service routine
它會把參數在 kernel stack 中的位置放到 EDX 暫存器,把 NtCreateFile system service 的 index value 放到 EAX 暫存器,然後透過 KiSystemService 來呼叫位於 KiServiceTable[EAX] 的 function,這個動作跟 user code 呼叫 system service 有點像
在這之中 previous mode 會被設定為 kernel mode
而 kernel mode 的 Nt API,則會直接呼叫該 system service routine,不會透過 KiSystemService 來呼叫,也不會設定 previous mode
看起來在 kernel mode 中 Zw 跟 Nt API 最大的差別就是有沒有去設定 previous mode,假設 previous mode 設定為 user mode 的話,system service routine 會對參數做嚴格的檢查,但是 kernel 基本上相信任何其他的 kernel component,所以 previous mode 為 kernel mode 的話,system service routine 就不會對參數做任何檢查
所以在 kernel 中建議是呼叫 Zw API,因為它會將 previous mode 設定為 kernel mode,若是呼叫 Nt API 的話,因為 kernel code 可能會執行在任意的 user mode stack 中,導致 previous mode 為 user mode,這可能會導致一些非預期的錯誤
沒有留言:
張貼留言