我一直在研究Windows内部,并且刚刚学习了系统调用,我想知道是否可以像函数一样使用这些系统调用?我知道他们并不是真的想从外部访问。
例如:NtUserEmptyClipboard
是Win32k.sys中的系统调用,其地址为0x117f
如果我想像函数一样使用此调用,我该怎么办呢?
答案 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