Category 竞猜大厅

CPU中的“模式位”

操作系统(OS)处于软件和硬件之间,它管理内存、磁盘、网络、外设,并为用户程序提供接口。但问题来了:

为什么用户程序不能直接操作硬件?为什么一定要通过操作系统?

因为硬件资源是共享的。操作系统必须防止恶意程序(或者有bug的程序)直接操作硬件,否则可能导致数据损坏、隐私泄露甚至系统崩溃。

为了实现这个隔离,处理器使用了一个非常关键的机制:CPU模式控制(mode bit)

CPU的两种运行模式

现代处理器至少支持两种运行模式:

模式

权限

举例

内核模式

可执行所有指令

OS内核、驱动、BIOS等

用户模式

禁止特权操作(如I/O)

普通程序如微信、Chrome等

这种设计是一种“硬件隔离”:即使你用C语言写了个访问硬件端口的程序,CPU也不会让你执行——因为你在用户模式中,执行不了特权指令。

模式位(Mode Bit)如何工作?

在x86架构中,控制权限的是某些控制寄存器,但在抽象层面我们可以理解为:

+----------------------------+

| Mode Bit |

+----------------------------+

| 0 = 用户模式(User Mode) |

| 1 = 内核模式(Kernel Mode) |

+----------------------------+

处理器每次执行指令时会检查当前模式位,只有在内核模式下,CPU才允许执行敏感操作:

操作磁盘寄存器

修改页表

控制中断

修改系统定时器

重启或关闭系统

例子:用户程序访问显卡失败

假设你有一段C代码:

unsigned char* vmem = (unsigned char*) 0xB8000;

vmem[0] = 'X';

你试图通过直接写显存来在屏幕上打印字符 'X'。这在裸机环境(如操作系统开发)中有效,但在用户态运行时会出错:

Segmentation fault (core dumped)

因为地址 0xB8000 是显卡显存,操作系统不会允许你直接写这个地址,更别说现代系统早已开启虚拟内存,映射规则也不同。

那用户程序怎么访问硬件?

通过系统调用(System Call),也就是“请求内核帮忙做特权操作”。

整个过程大致如下:

用户程序(用户模式,Mode Bit = 0)

│ 触发系统调用,如 write()

CPU触发软中断(如 INT 0x80)

CPU自动:

- 切换到内核栈

- 设置 Mode Bit = 1(内核模式)

- 跳转到内核中断处理例程

内核执行 write(),将内容写入磁盘/屏幕

内核返回:

- Mode Bit = 0(用户模式)

- 返回用户程序继续运行

这就是所谓的“陷入(Trap)”机制,CPU在硬件上强制完成模式切换,用户程序不能伪造这一过程。

系统调用举例:write()

write(fd, "Hello", 5);

write() 是 libc 提供的函数,看似普通函数,其实底层执行的是 syscall 或 int 0x80

CPU自动切换到内核态执行真正的硬件写入

完成后返回用户态

这是为什么C语言中“标准库函数”并不等于“系统调用”:只有那些最终陷入内核的才算。

硬中断 vs 软中断

类型

触发源

举例

硬中断

硬件设备

键盘按键、鼠标移动

软中断

程序主动触发

系统调用(如 int 0x80)

两者都会进入中断处理流程,但:

用户程序无法触发硬中断

用户程序只能通过指定接口请求软中断

为什么需要硬件支持?

你可能会问:我是不是可以直接调用系统调用的汇编指令伪造操作?

不能!因为系统调用入口地址是只读的、隐藏的,而且你的用户程序根本不能修改模式位。

CPU内部电路强制规定:

只有通过受控中断门(Interrupt Gate)才能切入内核

模式位切换只能由 CPU 控制

用户态不能访问内核态栈或页表

内核模式危险吗?

非常危险。内核中的错误不像用户程序那样“Segfault退出”,而是直接导致整个系统崩溃(kernel panic)。

因此,驱动程序、内核模块、系统调用实现必须极度谨慎:

// 错误的驱动代码

*null_ptr = 42; // 会内核崩溃

内核态驱动程序:既强大又危险的系统组件

驱动程序(Device Driver) 是一种特殊的系统软件,它运行在 内核态(Ring 0),负责操作系统与硬件之间的通信,比如磁盘、键盘、显卡、网卡,甚至是虚拟设备(如反作弊模块)都靠驱动控制。

但驱动不仅仅用于硬件控制 —— 很多软件功能,如杀毒、调试器、虚拟机、反作弊系统等,也会以“驱动”的形式直接在内核中运行,从而获得对系统的最高访问权限。

Ring 0:驱动程序的特权地位

在现代操作系统(如 Windows、Linux)中,系统执行权限分为多个级别,称为 “环(Ring)”。

Ring 0:内核态(最高权限) → 操作系统内核、驱动程序运行于此

Ring 3:用户态(最低权限) → 应用程序(浏览器、游戏等)运行于此

处于 Ring 0 的驱动程序拥有绝对控制权,可以:

访问任何进程内存(包括用户态程序的数据)

直接调用 CPU 指令、操纵中断表(IDT)或系统服务表(SSDT)

控制硬件 I/O,例如读写磁盘、网络通信

修改内核行为或替换系统函数(Hook)

统一的内核地址空间:风险根源

内核态的驱动程序共享同一个地址空间,这意味着:

所有驱动、公用内核代码都位于同一块高地址内存区域,没有隔离。

简化内存结构(x64 架构):

+--------------------------+

| 内核空间(共享区域) |

| - 操作系统核心模块 |

| - 所有加载的驱动程序 |

+--------------------------+

| 用户空间(每进程独立) |

| - 进程 A |

| - 进程 B |

+---------------------------+

这使得驱动:

能操作一切,但

一旦出错就影响全局

驱动程序出错可能导致蓝屏

因为驱动运行在核心地址空间,一旦有 bug 或错误操作,比如:

访问了无效内存地址(空指针或越界)

使用了已释放的对象

锁顺序错误导致死锁

非法操作页表或中断向量

Windows 就会立刻触发蓝屏(BSOD)来保护系统。

常见驱动相关蓝屏错误:

IRQL_NOT_LESS_OR_EQUAL

PAGE_FAULT_IN_NONPAGED_AREA

KERNEL_SECURITY_CHECK_FAILURE

DRIVER_IRQL_NOT_LESS_OR_EQUAL

驱动程序在安全软件与反作弊中的作用

许多软件会出于“系统控制”的需要,在用户同意下安装自己的驱动模块,典型包括:

1. 杀毒软件(Antivirus)

如 BitDefender、ESET、360、Windows Defender 等会安装内核驱动,以实现:

实时拦截系统调用(监控文件读写、网络连接)

检测 Rootkit、隐藏进程、非法驱动加载

控制防火墙规则

修复关键内核结构(如 SSDT、IDT)

2. 游戏反作弊系统(Anti-Cheat)

如 Vanguard(Valorant)、EasyAntiCheat(EAC)、BattlEye、XIGNCODE 等,使用驱动来:

拦截外挂读取游戏内存(如 NtReadVirtualMemory)

阻止 DLL 注入、内联 Hook

扫描内核模块列表,识别未签名驱动

禁止调试器、虚拟机运行

用户启动游戏 → 驱动加载 → 监视所有系统行为

↘ 阻止注入/调试

↘ 扫描非法驱动/模块

为什么它们都要用内核驱动?

因为外挂、病毒本身也常以驱动形式运行在内核态

如果反作弊/杀毒只在用户态运行,无法检测也无法阻止 Ring 0 的行为

所以只能用“以毒攻毒”的方式——同样用驱动进入内核,与其抗衡

Copyright © 2088 竞技暴风-网游赛事活动中心 All Rights Reserved.
友情链接