我一直在研究 Windows 内部,最近才了解系统调用,我想知道是否可以像函数一样使用这些系统调用?我知道它们并不是真的要从外部访问。
例如:NtUserEmptyClipboard
是Win32k.sys中的一个系统调用,它的地址是0x117f
如果我想像函数一样使用这个调用,我该怎么做?
我一直在研究 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
把 syscall 号放入eax
,然后调用syscall
指令。每个系统调用都有一个由 Windows 任意分配的数字(即,这个数字是 ntdll 和内核之间的秘密握手,微软需要随时更改)
这些指令都不是“魔法”,您也可以直接在您的应用程序中执行它们(但当然没有实际理由这样做 - 只是为了好玩)
EmptyClipboard
是所谓的“Win32 API”之一,NtUserEmptyClipboard
是对应的“本机API”。
与 Linux 不同syscall(2)
,我们很少应该直接调用“原生 API”。我听说他们在ntdll.dll
而不是win32k.sys
。但是我们应该能够像在普通 DLL 中定义的普通函数一样调用它们。
本机 API 的主要部分是通过 ntdll.dll 中的普通函数导出的。您可以将此 dll 加载到您的进程中并像任何其他 API 函数一样调用这些函数。只要你有正确的函数原型和参数,调用就可以正常工作。他们在内部所做的是从用户模式转换到内核模式,然后他们使用系统服务描述符表 (SSDT) 中的偏移量在内核模式内存中查找函数的地址,然后调用该函数。有一个开源项目http://nativetest.codeplex.com/可以调用您可能引用的本机 api。
win32k.sys 中的函数没有暴露在 ntdll.dll 中。据我所知,它们没有暴露在任何地方。您列出的地址 - 我相信 - 实际上是 SSDT 的偏移量。如果你真的需要调用这个函数,你必须自己从用户模式转换到内核模式,把函数的所有参数和 SSDT 偏移量放在正确的位置。
正如其他人所建议的那样,我建议找到用户模式 API 来帮助完成您想做的事情。FWIW,根据链接 /dump 输出,在 user32.dll 中,函数 EmptyClipboard 似乎直接转发到 NtUserEmptyClipboard。
1731 DF 0002018A EmptyClipboard = _NtUserEmptyClipboard@0
我强烈怀疑这0x117f
是您要查找的地址。我怀疑这可能是您需要传递给GetProcAddress
. 但我不确定,因为这些东西因 Windows 版本而异(这就是为什么普通人改用文档化函数的原因)