当前位置: 首页 > news >正文

[Windows内核源码分析0] 引导过程(Phase0部分分析)

第一个能显示出源码并下到断点的函数是ExpInitializeExecutive上面的描述说该例程会被调用2次, 首先在Phase0阶段初始化执行体层和所有它的子组件, 接着在Phase1阶段再次执行初始化工作。
在这里插入图片描述
来看看当前的调用堆栈:
在这里插入图片描述
可以看到调用顺序是KiSystemStartup调用了KiInitializeKernel接着在调用了ExpInitializeExecutive
接下来在这三个函数上下断点, 然后再次尝试, 发现在KiInitializeKernel上断了下来, 先尝试调试KiInitializeKernel
在这里插入图片描述
KiSystemStartup是有源码的, 但是我在这个函数上下断点没断下来, 所以我在单步补过后直接进入了KiInitializeKernel内。
这个函数的的描述说明了该函数的作用:
该函数的主要目的是初始化内核数据结构, 初始化空闲线程和处理器对象, 初始化PCB结构即进程控制块, 并调用执行体层的初始化例程, 并且也用于新处理器上线时的初始化。
进入KiInitializeKernel后首先:
在这里插入图片描述
接着填充R0和R3都共享的SharedUserData区域关于引导选项的信息, 这些信息都是从boot.ini中设置的
在这里插入图片描述
下面同样都是初始化PRCB中的数据结构初始化一些分发器内核对象
在这里插入图片描述
如果主处理器初始化成功了,则继续初始化处理器控制块PRCB中的内容,并将处理器的一些信息保存下来
在这里插入图片描述
调用了KiInitSystem, 初始化各类分发器对象和内核对象
在这里插入图片描述
初始化了DPC对象, 一些自旋锁以及各类链表
在这里插入图片描述
初始化了定时器链表对象等
在这里插入图片描述
SSDT和Shadow SSDT的初始化
在这里插入图片描述
接下去调用了KeInitializeProcess初始化内核进程对象
在这里插入图片描述
说白了就是把一些信息填充到这个结构体里:
在这里插入图片描述初始化内核线程对象
在这里插入图片描述
KeInitializeThread内部首先调用了KeInitalThread初始化了线程对象后调用KeStartThread启动该线程
在这里插入图片描述
看一下KeStartThread内部做了什么, 首先继续填充线程对象包括线程优先级, 处理器亲和性等信息
在这里插入图片描述
从处理器亲和性数值判断出该线程最适合使用哪一个处理器(WRK必须运行在多核处理器上, 所以要选择一个处理器)
在这里插入图片描述
将该对象插入到进程的线程链表中,等待处理器调度,至此该线程便要开始运行了。
在这里插入图片描述
初始化处理器控制块
在这里插入图片描述
接下去调用了ExpInitializeExecutive函数
在这里插入图片描述
进入后调用的第一个判断是ExpIsLoaderValid
在这里插入图片描述
来看看这个函数的原型:
在这里插入图片描述
其内部使用了一个名为LOADER_PARAMETER_BLOCK的结构体,看一下这个结构体的数据结构:

typedef struct _LOADER_PARAMETER_BLOCK {
    LIST_ENTRY LoadOrderListHead; // 加载模块链表
    LIST_ENTRY MemoryDescriptorListHead; // 内存描述符链表
    LIST_ENTRY BootDriverListHead; // 引导驱动链表
    ULONG_PTR KernelStack; 
    ULONG_PTR Prcb;  
    ULONG_PTR Process;
    ULONG_PTR Thread;
    ULONG RegistryLength;
    PVOID RegistryBase;
    PCONFIGURATION_COMPONENT_DATA ConfigurationRoot;
    PCHAR ArcBootDeviceName;
    PCHAR ArcHalDeviceName;
    PCHAR NtBootPathName;
    PCHAR NtHalPathName; 
    PCHAR LoadOptions;
    PNLS_DATA_BLOCK NlsData;
    PARC_DISK_INFORMATION ArcDiskInformation;
    PVOID OemFontFile;
    struct _SETUP_LOADER_BLOCK *SetupLoaderBlock;
    PLOADER_PARAMETER_EXTENSION Extension;

    union {
        I386_LOADER_BLOCK I386;
        // ALPHA_LOADER_BLOCK Alpha;
        // IA64_LOADER_BLOCK Ia64;
    } u;


} LOADER_PARAMETER_BLOCK, *PLOADER_PARAMETER_BLOCK;

来看看监视里该结构的内容, 其中红框框出的部分实际上是在C:\boot.ini中的配置信息, 这个信息会在windows刚开启位于实模式时显示,并让用户选择引导选项。由于当前还没有任何一个进程被创建, 所以Prcb和Process都是0.
在这里插入图片描述
设置InitializationPhase为0代表我们在Phase0
在这里插入图片描述
调用HalInitSystem来初始化HAL硬件抽象层
在这里插入图片描述
这部分没有源码, 但从反汇编里可以看到其是从halacpim.dll中导出的。
在这里插入图片描述
从其内部的函数名可以看出与硬件关系非常大,HAL硬件抽象层原本就是微软用于屏蔽不同物理设备上不同接口的不一致从而提供一组同一的接口。其中包含了关于PIC可编程控制器, CMOS等硬件相关,这里不做深究。
在这里插入图片描述
初始化完HAL后将中断打开
在这里插入图片描述
拼搭出路径C:\WINDOWS:
在这里插入图片描述
将其转成ANSI:
在这里插入图片描述
调用ExInitSystem初始化执行体各个组件和数据结构:
在这里插入图片描述
进入ExInitSystem后根据之前设置的InitializationPhase来判定是对Phase0的初始化还是Phase1的,这里很显然是Phase0
在这里插入图片描述
进入ExpInitSystemPhase0后对各类执行体资源进行初始化
在这里插入图片描述初始化分页内存池的链表
在这里插入图片描述
以及其他各类自旋锁和链表
在这里插入图片描述
返回后调用MmInitSystem初始化内存管理器和内存池, 在阶段0其只要工作是初始化内存管理页函数, 分页内存池即堆空间和PFN数据库:
获取页表地址:
在这里插入图片描述
设置堆区信息:
在这里插入图片描述
初始化各类执行体对象
在这里插入图片描述
确定用户态与内核态之间的界限
在这里插入图片描述
MmInitSystem函数代码量非常大, 分别分了2个阶段来进行初始化,这里不做详细讨论。
接下去遍历当前的PRCB中的模块链表并加载对应的符号
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
看了下之后加载了APCI.sys, pci.sys, isapnp.sys, compbatt.sys, intelide.sys, MountMgr.sys, ftdisk.sys等等
接着执行了ObInitSystem初始化对象管理器, SeInitSystem初始化安全子系统, PsInitSystem初始化进程线程管理器, PpInitSystem初始化即插即用管理器, DbgkInitialize初始化调试子系统等。
由于篇幅都比较长这4个部分我都会专门用博客来记录详细过程。
在这里插入图片描述
完成这四部分的初始化后, 对SharedUserData设置一些关于操作系统的信息后便返回了
在这里插入图片描述
ExpInitializeExecutive返回后, 对PRCB和线程对象进行最后的一些设置后返回
在这里插入图片描述
返回后发现程序竟然回到了KiSystemStartup内
在这里插入图片描述
把当前线程设为idle线程
在这里插入图片描述
蜕变成Idle线程后就是执行KiIdleLoop, Idle线程不停的自旋。
在这里插入图片描述
(完)

相关文章:

  • 【HJ53 杨辉三角的变形】
  • Vue移动端 / PC端适配解决方案:postcss-px-to-viewport
  • CAD图清晰打印设置
  • SSM+基于Vue框架的在线投票系统的设计与实现 毕业设计-附源码221604
  • 华为开源自研AI框架昇思MindSpore CPU-Ubuntu版本 Pip自动安装教程
  • git-secret:在 Git 存储库中加密和存储密钥(上)
  • [PAT练级笔记] 44 Basic Level 1044 火星数字
  • LeetCode题目笔记——01.09. 字符串轮转
  • 玩转Vue3全家桶02丨上手:一个清单应用帮你入门Vue
  • 武汉东西湖区小进规市场主体奖励申报条件、材料及流程梳理
  • 数据模型dataModel遍历图元时并且要移除指定时,不能在遍历循环中dm.remove(),需要做好标记在新的循环中移除,否则会影响前面循环遍历本身!
  • 高等数学(第七版)同济大学 习题8-1 个人解答
  • 如何顺时针或者逆时针记录多边形的每个点
  • 体验 Shifu 解决报错流程
  • SpringBoot+Vue项目在线学习网站
  • 【笔记】你不知道的JS读书笔记——Promise
  • 0x05 Python数据分析,Anaconda八斩刀
  • 2018天猫双11|这就是阿里云!不止有新技术,更有温暖的社会力量
  • 345-反转字符串中的元音字母
  • gitlab-ci配置详解(一)
  • HTTP中的ETag在移动客户端的应用
  • JAVA SE 6 GC调优笔记
  • Java基本数据类型之Number
  • Laravel 中的一个后期静态绑定
  • MQ框架的比较
  • scrapy学习之路4(itemloder的使用)
  • ubuntu 下nginx安装 并支持https协议
  • 力扣(LeetCode)56
  • 驱动程序原理
  • 详解移动APP与web APP的区别
  • Hibernate主键生成策略及选择
  • #中的引用型是什么意识_Java中四种引用有什么区别以及应用场景
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (多级缓存)多级缓存
  • (二) Windows 下 Sublime Text 3 安装离线插件 Anaconda
  • (二)构建dubbo分布式平台-平台功能导图
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (黑马C++)L06 重载与继承
  • (三分钟)速览传统边缘检测算子
  • .Net Core 中间件验签
  • .NET Framework 的 bug?try-catch-when 中如果 when 语句抛出异常,程序将彻底崩溃
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径
  • .NET 使用 XPath 来读写 XML 文件
  • .Net7 环境安装配置
  • .NET简谈互操作(五:基础知识之Dynamic平台调用)
  • .net专家(高海东的专栏)
  • @angular/cli项目构建--Dynamic.Form
  • @requestBody写与不写的情况
  • [AMQP Connection 127.0.0.1:5672] An unexpected connection driver error occured
  • [C#]C#学习笔记-CIL和动态程序集
  • [C++]命名空间等——喵喵要吃C嘎嘎
  • [HNOI2008]Cards
  • [k8s系列]:kubernetes·概念入门
  • [LeetCode][LCR178]训练计划 VI——使用位运算寻找数组中不同的数字
  • [LOJ 6213]「美团 CodeM 决赛」radar