Windows是如何防止用户模式线程任意将CPU转换为内核模式的呢?
我了解以下几点:
- 当通过NTDLL进行系统调用时,用户模式线程确实会转换为内核模式。
- 转换到内核模式是通过处理器特定的指令完成的。
那么,这些通过NTDLL进行的系统调用有什么特殊之处?为什么用户模式线程不能伪造它并执行处理器特定的指令以转换到内核模式?我知道我在这里缺少了一些关键的Windows架构知识... 那是什么呢?
Windows是如何防止用户模式线程任意将CPU转换为内核模式的呢?
我了解以下几点:
那么,这些通过NTDLL进行的系统调用有什么特殊之处?为什么用户模式线程不能伪造它并执行处理器特定的指令以转换到内核模式?我知道我在这里缺少了一些关键的Windows架构知识... 那是什么呢?
英特尔CPU使用所谓的“保护环”来强制执行安全性。
这里有4个保护环,从0到3编号。在0环中运行的代码拥有最高的权限;它(实际上)可以随心所欲地操作您的计算机。另一方面,在3环中运行的代码则受到严格限制;它只有有限的影响力。而1和2环目前没有任何用途。
在更高权限的环(如0环)中运行的线程可以随意转换到较低的权限环(如1、2或3环)。然而,反过来的转换是严格受控制的。这就是如何维护高权限资源(如内存)等的安全性。
自然地,您的用户模式代码(应用程序和所有内容)在3环中运行,而操作系统的代码在0环中运行。这确保了用户模式线程无法干扰操作系统的数据结构和其他关键资源。
如果想了解所有这些是如何实现的细节,您可以阅读this文章。此外,您可能还想查看Intel手册,特别是Vol 1和Vol 3A,您可以从here下载。
这是适用于Intel处理器的情况。我相信其他架构也有类似的情况发生。
我认为(但我可能错了),它用于转换的机制很简单:
防止用户模式代码篡改的方法如下:需要具备特权才能写入IDT;所以只有内核能够指定执行中断时发生什么。
运行在用户模式(Ring 3)的代码不能任意切换到内核模式(Ring 0)。它只能通过特殊路由——跳转门、中断和sysenter向量来执行。这些路由受到高度保护,输入数据会被清理,以防止坏数据引起不良行为。
所有这些都是由内核设置的,通常在启动时进行配置。它只能在内核模式下进行配置,因此用户模式代码无法修改它。
可以说它的实现方式与Linux的实现方式(相对而言)很相似。两种情况下都会是针对特定CPU的,但在x86上可能是通过INT指令的软中断或通过SYSENTER指令进行。
研究Linux的实现优势在于您可以在没有Windows源代码许可证的情况下进行。
用户空间源码在这里,内核空间代码在这里 - 查看entry_32.S和entry_64.S
在x86上的Linux有三种不同的机制:int 0x80、syscall和sysenter。
内核在运行时构建了一个名为vdso的库,C库调用该库来实现syscall函数,具体取决于CPU和系统调用类型使用不同的机制。然后内核为这些机制(如果在特定CPU变体上存在)提供处理程序。