首页
论坛
课程
招聘
[原创]Windows内核学习笔记之系统架构
2021-12-1 18:25 7809

[原创]Windows内核学习笔记之系统架构

2021-12-1 18:25
7809

Windows内核学习笔记目录:

一.架构概述

下图显示了Windows的基本结构。Windows采用双模式来保护操作系统本身,以避免被应用程序的错误所波及。操作系统核心运行在内核模式下,应用程序的代码运行在用户模式下。每当应用程序需要用到系统内核或内核的扩展模块(内核驱动程序)所提供的服务时,应用程序通过硬件指令从用户模式切换到内核模式中;当系统内核完成了所请求的服务以后,控制权又回到了用户模式代码。

在Windows中,用户代码和内核代码有各自的运行环境,而且它们可以访问的内存空间也不相同。在32位系统中,内核代码可以访问当前进程的整个4GB虚拟地址空间,而用户代码只能访问低端的2GB虚拟地址(或3GB,如果打开了内核启动开关/3GB的话)。

不同的模块工作在不同的模式下提供不同的服务,一些重要的组件及工作模式如下表:

文件名组件模式
Ntoskrnl.exe
经典32位分页模式下的执行体和内核内核
Ntkrnlpa.exePAE分页模式下的执行体和内核内核
Hal.dll硬件抽象层内核
PCI.sys,Win32k.sys
内核态驱动程序内核
Ntdll.dll
内部支持函数和执行体函数的存根函数
用户
Kernel32.dll,Advapi32.dll,User32.dll,GDI32.dll等DLL核心的Win32子系统DLL用户
Smss.exe,WinLogon.exe,Lass.exe等系统进程用户
Csrss.exe,PSXSS.exe,OS2SS.exe等子系统进程用户
Winspool.drv,UMDF等用户态驱动程序用户
Explorer.exeShell进程用户
Svchost.exe系统服务进程用户
Notepad.exe等应用程序用户

二.内核模式

简单来说,内核空间就是供操作系统内核使用的内存空间。内核的核心任务是管理硬件资源,为上层提供服务。对下要面对五花八门的硬件,内核的复杂程度可想而知。为了降低复杂度和便于开发维护,内核代码也是模块化的,按照职能分成若干个部分,相互协作。从这个角度来说,内核空间中,出了狭义的内核模块(操作系统核心之核心),还有一些其他模块。具体如下图所示:

1.硬件抽象层(HAL)

HAL的功能在Hal.dll中实现,该模块的主要作用就是隔离硬件的差异性,使内核和顶层模块可以通过统一的方式来访问硬件。值得说明的是,HAL负责的硬件类型只限于CPU架构层面的核心硬件,比如中断控制器,固件接口等,HAL并不负责外设类型的硬件,外设硬件的差异性问题是通过I/O管理器加载不同的设备驱动程序来解决的。

为了适应不同的硬件平台,硬件抽象层模块有多个不同的版本。

版本作用
hal.dll支持标准平台
halacpi.dll支持符合ACPI标准的硬件平台
halapic.dll支持APIC(高级可编程中断控制器)的硬件平台
halaacpi.dll同时支持ACPI和APIC的硬件平台
halmps.dll系统中有一个多处理器
halmacpi.dll支持ACPI的多处理器系统

当安装Windows系统时,安装程序会根据检测到的情况选择一个合适的hal文件,复制到系统目录中。

2.执行体和内核

从文件角度看,内核和执行体都位于同一文件中,即通常所说的NT内核文件。NT内核文件有几种版本,它们是使用同一套源代码通过不同的编译选项而编译出来的。

  • 针对单处理器系统优化的单处理器版本,在64位的Windows系统中,它的原始文件名为ntoskrnl.exe;在32位的Windows系统中,根据是否支持物理扩展(PAE),它是原始文件名是ntkrnlpa.exe(支持PAE)或ntoskrnl.exe(不支持PAE)。

  • 可用于多处理器系统的多处理版本,在64位的Windows系统中,它的原始文件名为ntkrnlmp.exe;在32位的Windows系统中,支持PAE的版本的原始文件名是ntkrpamp.exe,不支持PAE版本的是ntkrnlmp.exe。

为了根据需要加载正确的版本,安装程序在安装时会根据系统中的处理器个数,选择单处理器版本或多处理器版本中的一个并复制到用户系统(system32)目录中。如果复制的是多处理器版本,那么会将其改为与单处理器版本相同的名字。这也就是上面强调的“原始文件名”的原因,它是相对于安装在用户系统中的文件名而言的。

在32位系统中,由于可以在启动选项中自由选择是否开起PAE,所以安装程序会将支持PAE的版本和不支持PAE的版本都复制到用户系统(system32)目录中,但是会根据上面的原则选择多处理器版本和单处理器版本中的一种,并将其改为单处理器版本名字。因此,在安装好的Windows系统中就会看到ntoskrnl.exe和ntkrnlpa.exe两个NT内核文件。在Windows系统启动过程中,系统加载程序(NTLDR或WinLoad)会根据启动选择中是否启用了PAE加载其中一个。

在64位内核中,CPU大多基于AMD64或Intel64的x64架构,x64可以看作是对PAE的一种扩展(页表由3级扩展到4级,支持更长的线性地址和物理地址)。这就意味着,运行在x64硬件上的64位内核都是"PAE"版本的,不再有非PAE版本,因此在这也的系统中,system32目录中只有一个内核文件,而且没有必要提是否是PAE版本了。

想要查看NT内核文件的原始文件名,只需要右击文件,选择"属性",在弹出的对话框中单击"详细信息"选项卡中的"原始文件名",就可以看到内核文件的原始文件名

另外,由PE工具可以看到,有6个模块被内核模块直接导入使用

A.执行体

Windows执行体是Ntoskrnl.exe的上层,包含操作系统的基础服务,例如线程调度,进程和线程管理,安全性,I/O,网络以及进程间的通信。它的作用就是帮助内核行驶(执行)某一方面的职能,比如内存管理器负责管理和分配内存资源,进程管理器负责管理系统中的所有进程,输入输出(I/O)管理器负责协调系统的硬件资源等待。如果把操作系统内核比喻程系统的最高权力机构,那么执行体便是它的一个个职能部门,负责各方面的事务。为了完成这些事务,执行体提供了下列类型的函数

类型说明
可在用户模式下导出和调用的函数
这些函数叫系统服务,可通过Ntdll.dll导出。大部分此类服务均可通过Windows API或其他环境子系统的API访问。然而也有少数服务无法通过任何文档化的子系统函数访问,例如ALPC和多种查询函数(如NtQueryInformationProcess),以及一些专用函数(如NtCreatePagingFile等)。
通过DeviceIoControl调用的设备驱动程序函数这为从用户模式到内核模式调用设备驱动程序中的函数提供了通用接口,借此可调用读/写操作无关的函数
只能从内核模式调用,并在WRK中导出且未文档化的函数这些函数包括多种支持例程,如I/O管理器(以Io开头),常规执行体函数(Ex)等,主要适用于设备驱动程序的开发者
定义为全局符号但不可导出的函数这些函数包括在Ntoskrnl.exe中内部调用的支持函数,例如以Iop(内部I/O管理器支持函数)或Mi(内部内存管理支持函数)开头的函数
位于模块内部但未定义为全局符号的函数这些函数为执行体和内核专用

B.Windows内核

操作系统内核包含底层操作系统函数,负责线程调度,中断处理,异常分发,多处理器同步等关键任务,是操作系统最核心的部分,我们将其称为微观意义的内核。内核提供了一系列的例程和基本对象,执行体和其他部分会使用它们实现更高层次的功能。

内核由Ntoskrnl.exe中一系列用于提供基础机制的函数组成,例如被执行体使用的线程调度和同步服务,以及与底层硬件架构独立的支持(例如每种处理器架构均各异的中断和执行调度)。内核代码主要用C语言编写,不过对于需要使用特殊处理器指令和寄存器的任务,由于难以用C语言代码访问,因此继续使用了汇编代码。

与前文提到的各自执行体支持函数类似,很多内核函数均在WDK中提供了文档("Ke"开头的函数),因为设备驱动程序的实现也需要它们。

3.空闲进程和系统进程

在内核模式中包含了两个特殊的进程,分别是空闲进程和系统进程。之所以说它们特殊,是因为这两个进程都具有如下特征。

  1. 普通的Windows进程都是通过CreateProcess或类似的API并指定一个可执行映像文件而创建的,但这两个进程不是,它们没有对应的磁盘映像文件,是在系统启动时“捏造”出来的。

  2. 普通的Windows进程都有用户空间和内核空间两个部分,但是这两个进程都只有内核空间,没有用户空间。或者说,这两个进程只在高特权级的内核空间中运行。

  3. 具有固定的进程ID,空闲进程的ID总是0,系统进程的ID总是4。

A.空闲进程

空闲进程也叫Idle进程,是空闲线程的载体。由于当CPU一旦加电工作以后,就会不断的取指令并执行指令,如果当前系统中并没有需要运行的线程,就需要给CPU一些指令,组成循环,让它在那里空转。所以,今天的操作系统中,都会设计Idle进程,Idle进程负责占用CPU的闲置时间,当CPU空闲的时候,就让它执行空闲线程。

由于每个CPU都需要空闲线程,所以空闲线程的个数就是系统中启用的处理器的个数,比如下面这张图可以看出该电脑的空闲线程有4个,那么CPU个数就是4。另外,空闲线程占用CPU的比例越高越好,因为此时说明CPU可以对程序有更快的响应。

在NT内核启动时,就会创建空闲进程。更准确的说,是在执行体的阶段0初始化时,进程管理器的初始化函数便会创建空间进程和第一个空闲线程。可以说,第一个空闲线程是从系统初始启动线程“蜕化”而来的,是系统中的第一个线程。

B.系统进程

在系统启动阶段,进程管理器在创建空闲进程后,便创建系统进程,因此,系统进程是系统创建的第二个进程,它的进程ID为4,父进程ID是0,即空闲进程。系统进程的映像文件名是System,这个名称是杜撰的,磁盘上并不存在System.exe。

系统进程是一类运行在内核模式下的特殊线程的主体,这种特殊线程也叫做内核模式系统线程,其作用是为操作系统提供独立的进程空间和进程对象。系统线程具备普通用户线程所拥有的属性和上下文,例如硬件上下文和优先级等,但与普通用户模式线程不同之处在于,它只能在内核模式下运行,进而执行系统空间加载的代码。这些代码可能来自Ntoskrnl.exe或其他已加载的设备驱动程序。此外,系统进程的PEB为0,在用户空间的运行时间也是0,这是因为它并没有用户空间。因此,系统线程不具备用户进程地址空间,任何动态存储都必须从操作系统内存堆(例如换页或非换页内存)中分配。

系统线程是由PsCreateSystemThread或IoCreateSystemThread函数创建的,这两个函数都在WDK中有相关文档。这些线程只能在内核模式调用。Windows及各种设备驱动会在系统初始化过程中创建系统线程,借此执行需要线程上下文的操作,例如发起和等待I/O或其他对象,查询对象。例如,内存管理器会使用系统线程实现诸如将脏页面写入页面文件或映像文件中,将进程换出/换入内存等操作;内核会创建一个名为平衡机管理器的系统线程,该线程每秒被唤醒一次,从而有可能发起各种与调度和内存管理有关的事件;缓存管理器也会使用系统线程实现预读取和滞后写入的I/O;文件服务器设备驱动(Srv2.sys)会使用系统线程响应网络I/O请求,并将共享磁盘分区中的文件数据传输到网络;甚至软盘驱动器也会使用系统线程查询软盘设备。

默认情况下,系统线程属于System进程的,但设备驱动程序可以在任何进程中创建系统线程。例如,Windows子系统设备驱动(Win32k.sys)可以在Windows子系统进程(Csrss.exe)的规范显式驱动程序(Cdd.dll)中创建一个系统线程,这也就可以轻松访问该进程在用户模式地址空间中的数据。

4.内核空间的其他模块

除了上面的内容,内核空间中还存在以下的这些模块,不同的模块有着不同的分工。

模块名作用
Win32k.sysWindows子系统的内核空间模块,与用户空间的CSRSS进程互相配合一起管理窗口世界,包括窗口对象,用户输入,消息分发,显示输出等。
DxgKrnl.sys管理GPU的核心模块
KS.sys管理流媒体的核心模块,使用图的模式管理音视频的编解码和处理节点,各个节点之间可以用引脚(pin)方式动态建立连接
AFD.sys网络套接字(WinSock)的内核空间接口驱动,与硬件厂商的网卡驱动配合一起管理网卡设备
Wfplwf.sys用于管理网络过滤驱动的核心模块,全称为Windows过滤平台轻量过滤驱动驱动
ACPI.sys负责与平台固件接口的内核模块,是用于支持高级配置和电源接口编制的核心驱动程序,其内部除了包含用于解释执行ACPI源语言脚本的解释器,还包含一些ACPI标准设备的驱动程序,比如电源开关,笔记本电脑盖板检测器,风扇等
PCI.sys是PCI总线的核心驱动程序,用于支持PCI总线标准,枚举和管理PCI总线上的设备。每当发现新的设备后,便尝试让即插即用管理器为其加载驱动程序,加载的驱动程序可能是Windows系统自带的,也可能是从硬件厂商那里获得和后来安装的。
NTFS.sys是NTFS文件系统的实现,用于访问NTFS格式的磁盘卷

三.用户空间

用户空间是应用程序代码和各种用户态运行的内存空间。所谓应用程序,就是实现某一方法应用的软件程序,比如办公软件,浏览器,即时通信程序等。用户空间的各个模块具体如下图

可以看到,除了用户安装的或者系统预装的普通应用程序,用户空间中还运行着操作系统的一些进程,一般将它们称为常规进程。从职能角度看,常规进程的角色和内核空间的执行体有些类似,它们分别负责某一方面的职能,帮助内核一起维护系统的秩序。

1.Ntdll.dll

Ntdll.dll是一个特殊的系统支持库,主要被子系统DLL和原生应用程序使用,用户空间的代码通过这个DLL来进入系统空间使用内核提供的各种服务。同时,Ntdll.dll也是操作系统内核在用户空间中的“代理”,系统会在启动阶段便把它加载到内存中,并把它映射到所有用户进程的进程空间中,而且映射在相同的虚拟地址中。当内核需要与用户空间配合是,它会使用这个DLL中的函数,因为只有这个DLL才存在于每个用户进程的用户空间的固定位置上。

对于内核的每一个系统服务,该DLL都提供一个相应的存根函数,这些存根函数名称以"Nt"作为前缀,例如NtCreateProcess,NtOpenFile和NtSetTimer。另外,ntdll.dll还提供了许多系统级的映像加载函数(以"Ldr"为前缀),Windows子系统进程通信函数(以"Csr"为前缀),调试函数(以"Dbg"为前缀),系统事件函数(以"Etw"为前缀),以及一般的运行支持函数(以"Rtl"为前缀)和字符串支持函数等。

2.环境子系统

为了能够在Windows系统上运行多种类型的应用软件,Windows设计者在定义Windows架构时便设计了环境子系统的概念。不同类型的应用程序运行在不同的环境子系统。Windows2000支持如下三种环境子系统:

  • POSIX子系统:用于运行符合POSIX标准的程序。系统目录(system32)下的PSXSS.EXE和PSXDLL.DLL是POSIX子系统的核心文件。

  • OS/2子系统:支持16位的OS/2程序,系统目录下的OS2.EXE,OS2SRV.EXE和OS2SS.EXE是OS/2子系统的核心文件。

  • Windows子系统:即支持Windows程序运行的子系统,包括Windows子系统服务器进程(CSRSS.EXE),子系统驱动程序(Win32K.sys),子系统DLL(Kernel32.dll,User32.dll,Advapi32.dll,GDI32.dll),以及和设备相关的显示和打印驱动程序等

尽管Windows系统的基本设计思想是支持多个独立的环境子系统,但是为了避免多个子系统都重复实现类似的功能,Windows子系统有着与其他子系统不同的低位,Windows子系统可以独立存在而且是系统中不可或缺的部分,其他子系统以Windows子系统为基础,必须依赖于Windows子系统,而且按需要运行(当第一次运行相应类型的应用程序时,才启动所需的子系统)。

以下是Windows子系统的重要文件,大多数Windows API是由Windows子系统的DLL输出的。

名称模式描述
CSRSS.EXE用户模式Windows子系统服务进程的主程序
ADVAPI32.DLL用户模式

Windows子系统的DLL之一,包含如下API的入口

  • 数据加密(以Crpt开头)

  • 用户和账号管理(以Lsa开头)

  • 注册表操作(以Reg开头)

  • WMI(以Wmi开头)

  • 终端服务(以Wts开头)

GDI32.DLL用户模式Windows子系统的DLL之一,包含各种图形文字描绘API(GDI)的入口,如TextOut(),BitBlt()等。其中大多数API是被转换为系统服务并发给内核模式的Windows子系统驱动程序(Win32K.sys)
KERNEL32.DLL用户模式

Windows子系统的DLL之一,包含如下的API入口

  • 进程/线程管理,如CreateThread

  • 调试(以DeBug开头)

  • 文件操作,包括创建,打开,读写,搜索等

  • 内存分配(以Local开头和Global开头)

其中大多数API是被转换为系统服务并发给内核态的执行体

USER32.DLL用户模式Windows子系统的DLL之一,包含窗口管理,消息处理和用户输入API,如EndDialog,BeginPaint,SetWindowPos,MessageBox等。其中大多数API是被转换为系统服务并发给内核模式的Windows子系统驱动程序(Win32k.sys)

3.常规进程

在一个典型的Windows系统中,一般都运行着以下这些常规进程。

名称作用
会话管理进程(SMSS.EXE)它是系统中的第一个根据映像文件创建的进程,是在系统启动后期由执行体的初始化函数创建的。它运行后,会加载和初始化Win32子系统的内核模块Win32K.sys,创建Win32子系统服务进程(CSRSS.EXE),以及登录进程(WinLogon.exe)
Windows子系统服务器进程(CSRSS.EXE)负责维护Windows子系统的“日常事务”,为子系统的各个进程提供服务。例如登记进程和线程,管理控制台窗口,管理DOS程序虚拟机(VDM)进程等。CSRSS是Client/Server Runtime Server Sybsystem的缩写,即客户端/服务器运行时子系统
登录进程(WinLogon.EXE)负责用户登录和安全相关的事务。它启动后,会创建LSASS进程和系统服务管理进程(Services.EXE)。Windows XP的文件保护(WFP)功能也是在这个进程中实现的(sfc.dll和sfc_os.dll)
本地安全和认证进程(LSASS.EXE)负责用户身份验证
服务管理进程(SERVICES.EXE)

负责启动和股那里系统服务程序。系统服务程序是按照NT系统服务规范编写的EXE程序,通常没有用户界面,只在后台运行。常见的几个系统服务如下

  • SpoolSv.exe:打印机脱机服务

  • WmiPrvSE.exe:是WMI提供其管理服务

  • SvcHost.exe:通用的服务宿主程序

OS/2子系统和POSIX子系统服务进程用于在Windows系统中运行OS/2和符合POSIX标准的程序。它们只在需要时才启动,在环境子系统部分将进一步分析
外壳(Shell)程序默认为Explorer.exe,负责显示"开始"菜单,任务栏和桌面图标等

四.参考资料

  • 《软件调试》(第二版)卷2:Windows平台调试(上册)

  • 《深入解析Windows操作系统》(第七版)(卷一)

  • 《Windows内核原理与实现》


【公告】看雪团队招聘安全工程师,将兴趣和工作融合在一起!看雪20年安全圈的口碑,助你快速成长!

最后于 2022-1-10 14:34 被1900编辑 ,原因:
收藏
点赞5
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回