【问题标题】:Different system call ID's responsible for calling different functions on different versions of OS不同的系统调用ID负责在不同版本的操作系统上调用不同的函数
【发布时间】:2019-04-06 03:57:48
【问题描述】:

不同版本的操作系统上相同的系统调用 ID 值负责调用不同的内核函数。那么当我们在 Windows 7 上使用 Windows XP 时代使用的可执行文件时,为什么整个应用程序可以正常工作?

【问题讨论】:

  • 使用 NT API 的应用程序不进行直接系统调用。它们链接到系统库中的存根函数,该函数反过来进行系统调用,例如由 ntdll.dll 导出的 Nt 前缀函数以及由 win32u 导出的 NtUserNtGdi 前缀函数。 dll(以前的 user32.dll)。有等效的 Zw 前缀导出,但在用户模式下,它们之间没有区别,并且首选使用 Nt 名称。
  • 也就是说,除非应用程序有充分的理由(例如,它是与驱动程序紧密耦合的用户模式服务),否则我认为它应该更喜欢 Windows API 而不是低级系统调用。 IMO,如果CreateFileW 完成了这项工作,那么就使用它。仅在绝对必要时使用NtCreateFileNtOpenFile

标签: windows system-calls


【解决方案1】:

Windows 提供了大量 DLL,其中一些充当系统调用的精简(或有时不那么精简)包装器。

当系统调用 ID 在不同的 Windows 版本之间发生变化时,这些 DLL 也会发生变化。

但是你导入例如CloseHandle() 来自 kernel32.dll 的名称,因此您看不到更改并且一切正常(也就是说,如果我们不考虑更改您的程序可能不幸依赖的行为的错误和错误修复)。

【讨论】:

  • CloseHandle 是 WINAPI 调用,而不是系统调用。它实现了一些额外的行为,例如支持STD_INPUT_HANDLE等标准I/O伪句柄,为此它额外清除PEB进程参数中的进程StandardInput句柄,然后通过NtClose系统调用关闭真实文件句柄. OP 正在谈论的是诸如NtClose 之类的电话。例如,在 x64 中,ntdll.dll 中的NtClose stub 函数将句柄值移动到寄存器 r10;在寄存器rax中加载系统调用号;并发出syscall 指令切换到内核模式。
  • @eryksun 你提到了一个更直接的例子,但没有提到不同的机制。
  • 在 XP 上 ID 0x11B9 负责调用函数 NtGdiFullscreenControl,但在 Windows 7 上它负责调用函数 NtGdiDdUpdateOverlay。你的意思是他们两个有相同的功能,但他们有不同的名字?我理解正确吗?
  • @Farshid,不,当我们在用户模式下调用 NtGdiFullscreenControl 时,我们正在调用一个存根函数,该函数是使用给定版本的 Windows 中该函数的系统调用号编译的,该版本会有所不同。一旦我们通过syscall(或在Windows 的x86 32 位构建中通过int 0x2E)转换到内核模式,内核的NtGdiFullscreenControl 函数就会在系统调用表中查找——在这种情况下是扩展表具有win32k.sys功能。
  • @eryksun,我在一个使用 Ollydbg 的可执行文件中进行了调查。它显示函数的 ID 而不是名称。无论操作系统的版本如何,此 ID 始终保持不变。由于程序已编译一次然后在每个版本的操作系统上使用,如何在运行时更改函数的功能?在另一个表达式中,当控件到达指令 MOV EAX,11B9 然后通过 MOV EDX,7FFE0300 & CALL DWORD PTR DS:[EDX] 切换到内核模式时,它是如何检测到的,应该是哪个函数 NtGdiFullscreenControl 或 NtGdiDdUpdateOverlay换了?
猜你喜欢
  • 2021-10-20
  • 1970-01-01
  • 2021-06-03
  • 2011-12-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-22
  • 2020-01-24
相关资源
最近更新 更多