我可以直接访问Windows内核系统调用吗?

时间:2014-02-06 05:26:59

标签: c++ c windows system-calls windows-kernel

我一直在研究Windows内部,并且刚刚学习了系统调用,我想知道是否可以像函数一样使用这些系统调用?我知道他们并不是真的想从外部访问。

例如:NtUserEmptyClipboard是Win32k.sys中的系统调用,其地址为0x117f

如果我想像函数一样使用此调用,我该怎么办呢?

4 个答案:

答案 0 :(得分:4)

你想要做的事情在很大程度上取决于你感兴趣的架构,但要知道的是,ntdll.dll是每个系统调用的用户模式蹦床 - 也就是唯一一个实际进行系统调用的人当天结束时是ntdll。

所以,让我们在WinDbg中拆解其中一个方法,打开任何旧的exe(我选择了记事本)。首先,使用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看起来是neato。让我们把它拆开:

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和内核之间的秘密握手,并且只要微软需要就会发生变化)

这些说明都不是“神奇的”,您也可以直接在您的应用中执行它们(但是没有实际的理由这样做,当然 - 只是为了测试)

答案 1 :(得分:2)

EmptyClipboard是所谓的“Win32 API”之一,NtUserEmptyClipboard是相应的“原生API”。

与Linux syscall(2)不同,我们很少直接调用“本机API”。我听说他们在ntdll.dll而不是win32k.sys。但我们应该能够像普通DLL中定义的普通函数一样调用它们。

答案 2 :(得分:0)

我强烈怀疑0x117f是您正在寻找的地址。我怀疑它可能是您需要传递给GetProcAddress的值。但我不确定,因为这些内容因Windows版本而异(这就是普通人使用文档化功能的原因)

答案 3 :(得分:0)

本机API的主要部分是通过ntdll.dll的普通函数导出的。您可以将此dll加载到您的进程中,并像调用任何其他API函数一样调用这些函数。只要您拥有正确的函数原型和参数,调用就可以正常工作。他们在内部做的是从usermode转换到kernelmode,然后他们使用偏移到系统服务描述符表(SSDT)中来查找内核模式内存中函数的地址,然后调用该函数。有一个开源项目http://nativetest.codeplex.com/,可以调用您可能引用的本机API。

win32k.sys中的函数未在ntdll.dll中公开。据我所知,他们没有暴露在任何地方。您列出的地址 - 我相信 - 实际上是SSDT的抵消。如果你真的需要调用这个函数,你必须自己从usermode转换到kernelmode,把函数的所有参数和SSDT偏移放到正确的位置。

正如其他人所推荐的那样,我建议找到usermode API来帮助完成你想要做的事情。 FWIW,在user32.dll中,根据链接/转储输出,函数EmptyClipboard似乎直接转发到NtUserEmptyClipboard。

1731   DF 0002018A EmptyClipboard = _NtUserEmptyClipboard@0