【windows kernel源码分析】对初学者友好的底层理解,让你对计算机内核不再迷茫

简介: 【windows kernel源码分析】对初学者友好的底层理解,让你对计算机内核不再迷茫

🍃概念梳理


windows kernel


原文


翻译:RobotCode俱乐部


如果你熟悉类似C的语法,那么源代码是非常易读的,即使你错过了一些细节,你也能大致了解正在发生的事情。主要的障碍是缺少对代码的上下文环境的了解,比如它什么时候运行,为什么运行,或者机器的底层特性。这里我希望提供一些背景知识。


在Intel x86引导的故事中,此时处理器是在实模式下运行的,能够处理1 MB的内存,RAM对于现代Linux系统是这样的:


1668319341965.jpg


引导加载程序完成后的RAM内容


内核镜像已经由BIOS中的引导加载程序中的I/O服务加载到内存中。此镜像是包含内核文件的副本,例如/boot/vmlinuz-2.6.22-14-server。镜像被分成两部分:一小部分包含实模式内核代码,加载在640K以下;内核的大部分在保护模式下运行,加载在第一个兆字节内存之后。


该操作从上面所示的实模式内核头部开始。这个内存区域用于在 引导加载程序 和 内核 之间实现Linux引导协议。其中一些值是引导加载程序在执行其工作时读取的。比如包含内核版本的可读字符串,也包含其他重要信息,比如实模式内核块的大小。引导加载程序还将值写入该区域,例如用户在引导菜单中给出的命令行参数的内存地址。引导加载程序完成后,它已经填充了内核头部所需的所有参数。现在是跳到内核入口点的时候了。下图显示了内核初始化的程序流程,以及源目录、文件和行号:


🍑实现过程–还是看原文吧= =


一、内核初始化


1.1 系统启动过程简介


对于系统启动过程,已经有太多的资料介绍过了。这里只是稍作温习,为介绍后续内容做准备。这部分的内容参考了http://www.yesky.com/317/1711317.shtml

系统的启动过程一般分为5个步骤:

(1)预引导过程

[1] 计算机加电自检,同时完成硬件设备的枚举和配置。

[2] BIOS确定引导设备位置,加载引导设备的MBR。

[3] 在MBR中扫描分区表,定位活动分区,并加载活动分区上引导扇区到内存

[4] 加载系统根目录的ntldr。

(2)引导过程

[5] 初始化Ntldr,完成处理器模式切换和文件系统驱动的加载,如果使用SCSI设备,

Ntldr将Ntbootdd.sys加载到内存。

[6] Ntldr读取系统根目录的boot.ini

,在屏幕显示系统启动菜单,等待用户选择所需要加载的操作系统。

[7] Ntldr读取并运行程序Ntdetect.com,完成硬件的检测。

[8] Ntldr根据用户的选择调用系统的硬件配置文件。

(3)内核加载,在[8]后清除屏幕,显示进度条。

[9] 加载执行体ntoskrnl.exe

[10] 加载Hal.dll

[11] 加载%systemroot\System32\Config\System下的注册表项HKEY_LOCAL_MACHINE

SYSTEM。

[12] 选择加载控制集,初始化计算机。

[13] 根据控制集加载低级硬件设备驱动程序。

(4)内核初始化,显示图形界面。

[14] 内核会使用检测到的硬件数据,在注册表中创建HKEY_LOCAL_MACHINE\HARDWA项。

[15] 其次的工作是内核通过复制HKEY_LOCAL_MACHINE\SYSTEM\Select子键Current

项引用的控制集创建Clone控制集。

[16] 内核开始进一步加载和初始化设备驱动程序。

[17] Session Manager(Smss.exe)按顺序启动Windows 2000

更高一层次的子系统和各项服务。

(5)系统登陆过程

[18] 系统首先启动Winlogon.exe。

[19] 启动Local Security Authority(Lsass.exe)

[20] 屏幕显示出登陆对话框。

[21] 系统执行Service Controller(Screg.exe)再次扫描注册表HKEY_LOCAL_MACHINE

SYSTEM\CurrentControlSet\Control项并自动加载其中系统的或用户的服务。

[22] 此时,用户已成功的登陆到了Windows 2000系统,系统随后把Clone控制集拷贝到

LastKnownGood控制集。


1.2 内核初始化


本文所要介绍的重点是ntoskrnl的初始化流程。这个初始化过程大致分为两个阶段:phase0和phase1。对于具体所处的阶段是由一 个全局变量InitializationPhase来标识,当InitializationPhase为0时表示处于phase0,当 InitializationPhase为1时表示处于phase1。

Ntoskrnl在入口函数中调用KiSystemStartup,而KiSystemStartup又依次为每个CPU调用 HalInitializeProcessor和KiInitializeKernel。如果KiInitializeKernel运行在引导CPU上, 则会调用KiInitSystem执行系统范围全局的内核初始化。然后KiInitializeKernel调用 ExpInitializeExecutive函数,负责实现phase0阶段的初始化工作。

(注:引导CPU,即0号CPU,每个CPU都以整数标识,0号CPU是第一个被初始化的CPU。当初始化第1个CPU时需要进行额外的操作,因而称之为引导CPU)

在phase0阶段的初始化过程中首先调用HalInitSystem初始化HAL,然后依次初始化内存管理器、对象管理器、安全引用监视器、进 程管理器和即插即用管理器。其中在调用PsInitSystem执行进程管理器在phase0阶段初始化时,创建了一个新的系统线程即为 Phase1Initialization,用于执行phase1阶段的初始化。由于此时并不允许中断,Phase1Initialization线程并 不立即执行。当完成phase0阶段初始化并返回到KiInitializeKernel时,设置IRQL到DISPATCH_LEVEL并使CPU调度 Phase1Initialization线程,从而进行phase1阶段的初始化。


关于内核初始化流程可以用下图表示,从上到下表示时间顺序:


图示说明:

[1] 关于KiInitializeKernel的具体实现参见2.1小节。

[2] 关于KiInitSystem的具体实现参见2.2小节

[3] 关于phase0阶段ExpInitializeExecutive的具体实现参见2.3小节。

[4] 关于phase0阶段进程管理器初始化(PsInitSystem)的具体实现参见2.4小节。

[5] 关于Phase1Initialization线程实现phase1阶段初始化的具体过程参见2.5小节。


🌸参考原文链接


windows内核编程 谭文_内核启动过程分析


Windows内核源码分析 1.初始化内核与执行体子系统


相关文章
|
4月前
|
监控 安全 API
5.9 Windows驱动开发:内核InlineHook挂钩技术
在上一章`《内核LDE64引擎计算汇编长度》`中,`LyShark`教大家如何通过`LDE64`引擎实现计算反汇编指令长度,本章将在此基础之上实现内联函数挂钩,内核中的`InlineHook`函数挂钩其实与应用层一致,都是使用`劫持执行流`并跳转到我们自己的函数上来做处理,唯一的不同的是内核`Hook`只针对`内核API`函数,但由于其身处在`最底层`所以一旦被挂钩其整个应用层都将会受到影响,这就直接决定了在内核层挂钩的效果是应用层无法比拟的,对于安全从业者来说学会使用内核挂钩也是很重要。
40 1
5.9 Windows驱动开发:内核InlineHook挂钩技术
|
4月前
|
监控 Windows
7.4 Windows驱动开发:内核运用LoadImage屏蔽驱动
在笔者上一篇文章`《内核监视LoadImage映像回调》`中`LyShark`简单介绍了如何通过`PsSetLoadImageNotifyRoutine`函数注册回调来`监视驱动`模块的加载,注意我这里用的是`监视`而不是`监控`之所以是监视而不是监控那是因为`PsSetLoadImageNotifyRoutine`无法实现参数控制,而如果我们想要控制特定驱动的加载则需要自己做一些事情来实现,如下`LyShark`将解密如何实现屏蔽特定驱动的加载。
32 0
7.4 Windows驱动开发:内核运用LoadImage屏蔽驱动
|
21天前
|
监控 安全 API
7.3 Windows驱动开发:内核监视LoadImage映像回调
在笔者上一篇文章`《内核注册并监控对象回调》`介绍了如何运用`ObRegisterCallbacks`注册`进程与线程`回调,并通过该回调实现了`拦截`指定进行运行的效果,本章`LyShark`将带大家继续探索一个新的回调注册函数,`PsSetLoadImageNotifyRoutine`常用于注册`LoadImage`映像监视,当有模块被系统加载时则可以第一时间获取到加载模块信息,需要注意的是该回调函数内无法进行拦截,如需要拦截则需写入返回指令这部分内容将在下一章进行讲解,本章将主要实现对模块的监视功能。
37 0
7.3 Windows驱动开发:内核监视LoadImage映像回调
|
4月前
|
监控 安全 API
7.2 Windows驱动开发:内核注册并监控对象回调
在笔者上一篇文章`《内核枚举进程与线程ObCall回调》`简单介绍了如何枚举系统中已经存在的`进程与线程`回调,本章`LyShark`将通过对象回调实现对进程线程的`句柄`监控,在内核中提供了`ObRegisterCallbacks`回调,使用这个内核`回调`函数,可注册一个`对象`回调,不过目前该函数`只能`监控进程与线程句柄操作,通过监控进程或线程句柄,可实现保护指定进程线程不被终止的目的。
31 0
7.2 Windows驱动开发:内核注册并监控对象回调
|
4月前
|
监控 安全 API
7.6 Windows驱动开发:内核监控FileObject文件回调
本篇文章与上一篇文章`《内核注册并监控对象回调》`所使用的方式是一样的都是使用`ObRegisterCallbacks`注册回调事件,只不过上一篇博文中`LyShark`将回调结构体`OB_OPERATION_REGISTRATION`中的`ObjectType`填充为了`PsProcessType`和`PsThreadType`格式从而实现监控进程与线程,本章我们需要将该结构填充为`IoFileObjectType`以此来实现对文件的监控,文件过滤驱动不仅仅可以用来监控文件的打开,还可以用它实现对文件的保护,一旦驱动加载则文件是不可被删除和改动的。
29 1
7.6 Windows驱动开发:内核监控FileObject文件回调
|
4月前
|
监控 安全 API
6.9 Windows驱动开发:内核枚举进线程ObCall回调
在笔者上一篇文章`《内核枚举Registry注册表回调》`中我们通过特征码定位实现了对注册表回调的枚举,本篇文章`LyShark`将教大家如何枚举系统中的`ProcessObCall`进程回调以及`ThreadObCall`线程回调,之所以放在一起来讲解是因为这两中回调在枚举是都需要使用通用结构体`_OB_CALLBACK`以及`_OBJECT_TYPE`所以放在一起来讲解最好不过。
45 1
6.9 Windows驱动开发:内核枚举进线程ObCall回调
|
4月前
|
监控 安全 API
6.8 Windows驱动开发:内核枚举Registry注册表回调
在笔者上一篇文章`《内核枚举LoadImage映像回调》`中`LyShark`教大家实现了枚举系统回调中的`LoadImage`通知消息,本章将实现对`Registry`注册表通知消息的枚举,与`LoadImage`消息不同`Registry`消息不需要解密只要找到`CallbackListHead`消息回调链表头并解析为`_CM_NOTIFY_ENTRY`结构即可实现枚举。
54 1
6.8 Windows驱动开发:内核枚举Registry注册表回调
|
4月前
|
存储 API 开发者
6.7 Windows驱动开发:内核枚举LoadImage映像回调
在笔者之前的文章`《内核特征码搜索函数封装》`中我们封装实现了特征码定位功能,本章将继续使用该功能,本次我们需要枚举内核`LoadImage`映像回调,在Win64环境下我们可以设置一个`LoadImage`映像加载通告回调,当有新驱动或者DLL被加载时,回调函数就会被调用从而执行我们自己的回调例程,映像回调也存储在数组里,枚举时从数组中读取值之后,需要进行位运算解密得到地址。
32 1
6.7 Windows驱动开发:内核枚举LoadImage映像回调
|
4月前
|
网络协议 API C++
6.6 Windows驱动开发:内核枚举Minifilter微过滤驱动
Minifilter 是一种文件过滤驱动,该驱动简称为微过滤驱动,相对于传统的`sfilter`文件过滤驱动来说,微过滤驱动编写时更简单,其不需要考虑底层RIP如何派发且无需要考虑兼容性问题,微过滤驱动使用过滤管理器`FilterManager`提供接口,由于提供了管理结构以及一系列管理API函数,所以枚举过滤驱动将变得十分容易。
52 1
6.6 Windows驱动开发:内核枚举Minifilter微过滤驱动
|
4月前
|
存储 算法 数据安全/隐私保护
6.5 Windows驱动开发:内核枚举PspCidTable句柄表
在 Windows 操作系统内核中,PspCidTable 通常是与进程(Process)管理相关的数据结构之一。它与进程的标识和管理有关,每个进程都有一个唯一的标识符,称为进程 ID(PID)。与之相关的是客户端 ID,它是一个结构,其中包含唯一标识进程的信息。这样的标识符在进程管理、线程管理和内核对象的创建等方面都起到关键作用。
31 1
6.5 Windows驱动开发:内核枚举PspCidTable句柄表