我一直在研究Windows内部,最近才了解系统调用,我想知道是否可以像函数一样使用这些系统调用?我知道它们并不是真的要从外部访问。
例如:NtUserEmptyClipboard
是 Win32k 中的系统调用.sys,它的地址是0x117f
如果我想像函数一样使用此调用,我该怎么做?
你想做什么在很大程度上取决于你感兴趣的架构,但要知道的是,ntdll.dll
是每个系统调用的用户模式蹦床 - 即唯一在一天结束时实际进行系统调用的是 ntdll。
因此,让我们通过打开任何旧的 exe(我选择了记事本)在 WinDbg 中反汇编这些方法之一。首先,使用x ntdll!*
查找 ntdll 导出的符号:
0:000> x ntdll!*
00007ff9`ed1aec20 ntdll!RtlpMuiRegCreateLanguageList (void)
00007ff9`ed1cf194 ntdll!EtwDeliverDataBlock (void)
00007ff9`ed20fed0 ntdll!shortsort_s (void)
00007ff9`ed22abbf ntdll!RtlUnicodeStringToOemString$fin$0 (void)
00007ff9`ed1e9af0 ntdll!LdrpAllocateDataTableEntry (void)
...
所以,让我们随机选择一个,NtReadFile
看起来很整洁。让我们拆解它:
0:000> uf ntdll!NtReadFile
ntdll!NtReadFile:
00007ff9`ed21abe0 4c8bd1 mov r10,rcx
00007ff9`ed21abe3 b805000000 mov eax,5
00007ff9`ed21abe8 0f05 syscall
00007ff9`ed21abea c3 ret
在这里,我们看到我们把rcx
塞进去,把系统呼叫号码放进eax
,然后调用syscall
指令。每个系统调用都有一个由Windows任意分配的数字(即这个数字是ntdll和内核之间的秘密握手,可以随时更改Microsoft)
这些指令都不是"魔术",您也可以直接在您的应用程序中执行它们(当然,没有实际的理由这样做 - 只是为了好玩)
EmptyClipboard
是所谓的"Win32 API"之一,NtUserEmptyClipboard
是相应的"本机API"。
- http://en.wikipedia.org/wiki/Native_API
与Linuxsyscall(2)
不同,我们很少直接调用"本机API"。 我听说他们在ntdll.dll
而不是win32k.sys
. 但是我们应该能够像在普通 DLL 中定义的普通函数一样调用它们。
- 有没有办法从用户模式调用Windows本机API函数?
我强烈怀疑0x117f
是您要查找的地址。我怀疑这可能是您需要传递给GetProcAddress
的值。但我不确定,因为这些东西因Windows版本而异(这就是为什么普通人使用记录的函数的原因)
本机 API 的主要部分通过 ntdll.dll 的普通函数导出。您可以将此 dll 加载到进程中,并像调用任何其他 API 函数一样调用这些函数。只要您有正确的函数原型和参数,调用就可以正常工作。它们在内部执行的操作是从用户模式转换到内核模式,然后使用系统服务描述符表 (SSDT) 中的偏移量在内核模式内存中查找函数的地址,然后调用该函数。有一个开源项目 http://nativetest.codeplex.com/,它调用您可能引用的本机 API。
win32k.sys 中的函数不会在 ntdll.dll 中公开。据我所知,它们没有暴露在任何地方。您列出的地址 - 我相信 - 实际上是SSDT的偏移量。如果确实需要调用此函数,则必须自己从用户模式过渡到内核模式,将函数的所有参数和 SSDT 偏移量放在正确的位置。
正如其他人所建议的那样,我建议找到用户模式 API 来帮助完成您想要做的事情。 FWIW,在 user32 中.dll根据链接/dump 输出,函数 EmptyClipboard 似乎直接转发到 NtUserEmptyClipboard。
1731 DF 0002018A EmptyClipboard = _NtUserEmptyClipboard@0