Windows如何保护转换到内核模式?

Windows如何防止用户模式线程从CPU任意转换到内核模式?

我明白这些事情是真的:

  1. 当通过NTDLL进行系统调用时,用户模式线程实际上转换到内核模式。
  2. 内核模式的转换是通过特定于处理器的指令完成的。

那么通过NTDLL这些系统调用有什么特别之处呢? 为什么用户模式线程不能伪造它,并执行特定于处理器的指令来转换到内核模式? 我知道我在这里错过了一些关键的Windows体系结构…这是什么?

你可能认为在用户模式下运行的线程正在调用Ring 0,但这不是实际发生的事情。 用户模式线程正在引起由Ring 0代码捕获的异常。 用户模式线程暂停,CPU切换到内核/环形0线程,然后可以检查用户模式线程的上下文(例如调用堆栈和寄存器)以找出要执行的操作。 在系统调用之前,它确实是一个异常,而不是调用环0代码的特殊例外。

如果您接受其他响应的建议并阅读英特尔手册 ,您将会看到syscall / sysenter不带任何参数 – 操作系统决定发生什么。 你不能调用任意代码。 WinNT使用映射到用户模式代码将执行的内核模式函数的函数编号(例如,在我的Windows XP机器上NtOpenFile是fnc 75h(数字始终在变化; NTDll的作业之一是映射函数调用一个fnc号码,把它放在EAX中,将EDX指向传入的参数,然后调用sysenter)。

英特尔CPU使用所谓的“保护环”来强化安全性。

其中有4个,编号从0到3. Ring 0中运行的代码的权限最高, 它可以(几乎)根据你的电脑做任何事情。 另一方面,第三环中的代码总是紧绷的, 它只有有限的权力来影响事物。 而环1和环2目前根本不用于任何目的。

运行在更高权限的环(例如环0)中的线程可以随意转换到更低权限环(例如环1或2或3)。 但是,相反的过渡是严格规定的。 这就是如何保持高特权资源(如内存)的安全性。

当然,您的用户模式代码(应用程序和所有)运行在环3中,而OS的代码运行在环0中。这确保用户模式线程不会混淆操作系统的数据结构和其他关键资源。

有关如何实际执行的详细信息,请阅读本文。 此外,您可能还需要阅读英特尔手册,特别是第一卷和第三卷,您可以从这里下载。

这是英特尔处理器的故事。 我相信其他架构有类似的事情发生。

我想(我可能是错的),它用于过渡的机制很简单:

  • 用户模式代码执行软件中断
  • 这个(中断)使分支到达在中断描述符表(IDT)中指定的位置,

防止用户模式代码篡改的事情如下:你需要被授权写入IDT; 所以只有内核能够指定执行中断时会发生什么。

用户模式(Ring 3)中运行的代码不能任意更改为内核模式(Ring 0)。 它只能使用特殊路由 – 跳闸,中断和sysenter向量。 这些路由受到高度保护,并且输入被清理,以便坏数据不能(不应该)导致不良行为。

所有这些都是由内核设置的,通常在启动时设置。 它只能在内核模式下配置,所以用户模式代码不能修改它。

这可能是公平的,它与Linux所做的(相对)相似。 在这两种情况下它都是CPU特有的,但是在x86上可能是带有INT指令的软件中断,或者是通过SYSENTER指令。

查看Linux如何执行的好处是,您可以在没有Windows源许可证的情况下执行此操作。

用户空间源部分在这里在LXR和内核空间位 – 在entry_32.S和entry_64.S

在x86上的Linux下有三种不同的机制,int 0x80,syscall和sysenter。

由C库调用由内核调用的vdso在运行时构建的库来实现syscall函数,该函数根据CPU和系统调用的不同使用不同的机制。 然后内核拥有这些机制的处理程序(如果它们存在于特定的CPU变体中)。