【问题标题】:Can I access Windows Kernel system calls directly?我可以直接访问 Windows 内核系统调用吗?
【发布时间】:2014-03-02 22:00:02
【问题描述】:

我一直在研究 Windows 内部结构,最近才了解系统调用,我想知道是否可以像函数一样使用这些系统调用?我知道它们并不是真的要被外部访问。

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

如果我想像函数一样使用这个调用,我该怎么做?

【问题讨论】:

  • 最好使用文档化的函数,例如EmptyClipboard
  • Link或许能帮到你
  • 系统功能通常没有文档记录(有少数例外),并且可能会在操作系统版本之间更改(或被删除)。
  • @OMerObaid:该链接适用于 Linux,不适用于 Windows。

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


【解决方案1】:

您想要做什么在很大程度上取决于您感兴趣的架构,但要知道的是,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 和内核之间的秘密握手,并且可以随时更改)

这些指令都不是“魔法”,您也可以直接在您的应用中执行它们(当然,没有实际理由这样做 - 只是为了好玩)

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      我非常怀疑0x117f 是您要查找的地址。我怀疑这可能是您需要传递给GetProcAddress 的值。但我不确定,因为这些东西因 Windows 版本而异(这就是为什么普通人使用文档化的函数)

      【讨论】:

      【解决方案4】:

      原生 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
      

      【讨论】:

        猜你喜欢
        • 2013-03-28
        • 1970-01-01
        • 1970-01-01
        • 2016-07-04
        • 2012-10-24
        • 1970-01-01
        • 2021-07-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多