【Windows源码分析】(一)初始化内核与执行体子系统

Linux内核实现PE加载器——Longene源码分析 Longene是一个源自中国的自由、开源的操作系统项目,目的是要把Linux的内核扩充成一个既支持Linux应用、也支持Windows应用,既支持Linux设备驱动、也支持Windows设备驱动的兼容内核;使用户可以直接在Linux操作系统上高效运行Windows应用。2006年发布了其第一个版本,但是自2014年以来,项目开发已停止,2018年5月其官网无法访问。这里就不多做介绍了,直接开始从源... 阅读详情
  作 者: 北极星2003
时 间: 2008-03-22,23:59
链 接: http://bbs.pediy.com/showthread.php?t=61749

对于那么没有相关经验的朋友,在阅读本文时最好对照windows源码来看,否则光看着这么多数据结构就足以头大。对于这篇文章,严格来说,应该是属于学习笔记型,如有分析不当的地方,请各位多指教!
    本文的主要目标是根据windows源码分析内核与执行体初始化流程,过程中会涉及大量的内核数据结构与函数,文中并不会介绍每个结构的含义及作 用。内核中有很多晦涩难懂且枯燥的代码,我在分析过程尽可能的去分析每一行代码,否则如果只分析思路而不注重细节那么就跟没分析一样。      
==========================================================
本文结构:
一、内核初始化
1.1  系统启动过程简介
1.2  内核初始化
二、源码分析
2.1 内核初始化KiInitializeKernel
2.2 初始化内核数据结构KiInitSystem
2.3 [phase0]Ntoskrnl初始化ExpInitializeExecutive
2.4 [phase0]初始化进程管理器PsInitPhase0
2.5 [phase1]Ntoskrnl初始化Phase1Initialiation

==========================================================
一、内核初始化
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阶段的初始化。

关于内核初始化流程可以用下图表示,从上到下表示时间顺序:
名称:  init.JPG
查看次数: 1514
文件大小:  30.6 KB
图示说明:
[1] 关于KiInitializeKernel的具体实现参见2.1小节。
[2] 关于KiInitSystem的具体实现参见2.2小节
[3] 关于phase0阶段ExpInitializeExecutive的具体实现参见2.3小节。
[4] 关于phase0阶段进程管理器初始化(PsInitSystem)的具体实现参见2.4小节。
[5] 关于Phase1Initialization线程实现phase1阶段初始化的具体过程参见2.5小节。

二、源码分析
2.1  内核初始化KiInitializeKernel
      这个函数在系统由bootstrapped启动后且系统未被初始化之前取得控制权。当新的处理器加入时,调用这个例程可以初始化处理器相关的数据结构。主要功能是:
(1)初始化内核数据结构
(2)初始化处理控制块(Processor Control Block)
(3)调用内核执行体初始化例程
(4)最后返回系统启动例程(KiSystemStartup)   
      下面就是KiInitializeKernel的执行流程:
代码:
VOID KiInitializeKernel (
          IN PKPROCESS Process,
          IN PKTHREAD Thread,
          IN PVOID IdleStack,      // IDLE线程的内核堆栈基地址
          IN PKPRCB Prcb,      // 指向处理器控制块结构
          IN CCHAR Number,      // 指定当前正在初始化的处理器索引号
          PLOADER_PARAMETER_BLOCK LoaderBlock
          )
{
  // 初始化Prcb的部分成员
  // ……

  // 在系统初始化过程(KiSystemStartup)会枚举所有CPU,
  // 然后循环调用KiInitializeKernel依次初始化每个CPU
  // 在初始化号CPU时,会初始化一部分内核数据结构
  if (Number == 0) {

    // 初始化处理器相关的全局信息
    // 例如KeI386NpxPresent,KeI386CpuType,KeI386CpuStep,KeI386FxsrPresent等
    // ……

    // 初始化体系无关的内核数据结构
    KiInitSystem();

    // 初始化idle线程的进程对象
    KeInitializeProcess(Process,…… );
  } 
  else
  {
    // ……
  }

  // ……

  // 初始化线程对象
  KeInitializeThread(Thread, (PVOID)((ULONG)IdleStack),
    (PKSYSTEM_ROUTINE)NULL, (PKSTART_ROUTINE)NULL,
    (PVOID)NULL, (PCONTEXT)NULL, (PVOID)NULL, Process);

  // ……

  // 调用内核执行体的初始化例程
  try {
    ExpInitializeExecutive(Number, LoaderBlock);
  } except (EXCEPTION_EXECUTE_HANDLER) {
    KeBugCheck (PHASE0_EXCEPTION);
  }

  // ……

  // 如果是启动CPU(0号),动态分配内核堆栈空间和K的IOPM存储区域
  if (Number == 0) {
    PVOID DpcStack = MmCreateKernelStack(FALSE);
    if (DpcStack == NULL) {
      KeBugCheckEx(NO_PAGES_AVAILABLE, 1, 0, 0, 0);
    }
    Prcb->DpcStack = DpcStack;

    // 分配K的IOPM存储区域,用于BiosCall交换
    Ki386IopmSaveArea = ExAllocatePoolWithTag(PagedPool,PAGE_SIZE * 2,'  eK');
    if (Ki386IopmSaveArea == NULL) {
      KeBugCheckEx(NO_PAGES_AVAILABLE, 2, PAGE_SIZE * 2, 0, 0);
    }
  }
  
    // 设置IRQL为DISPATCH_LEVEL级别,允许线程派发
    KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);

    // 设置当前线程优先级为0,这样才能调度Phase1Initialization线程
    KeSetPriorityThread(Thread, (KPRIORITY)0);
 
    // 检测是否存在就绪线程,如果不存在则把当前CPU添加到KiIdleSummary
    KiAcquireQueuedSpinLock(KiQueuedSpinLockContext(LockQueueDispatcherLock));
    if (Prcb->NextThread == (PKTHREAD)NULL) {
        SetMember(Number, KiIdleSummary);
    }
    KiReleaseQueuedSpinLock(KiQueuedSpinLockContext(LockQueueDispatcherLock));

    // 提升IRQL到HIGH_LEVEL,屏蔽中断
KeRaiseIrql(HIGH_LEVEL, &OldIrql);

  return;
}
这里有3个关键处:
(1)当初始化0号CPU时调用KiInitSystem用于初始化内核数据结构。
(2)调用执行体初始化例程ExpInitializeExecutive。
(3)在调用ExpInitializeExecutive返回后,首先设置IRQL为DISPATCH_LEVEL
级别,允许线程派发,然后设置当前线程优先级为0,表明当前线程放弃下一个时间片,使得CPU可以执行Phase1Initialization线程,最后提升IRQL为HIGH_LEVEL,屏蔽系统中断,保证phase1阶段的初始化不可中断。

2.2  初始化内核数据结构KiInitSystem
KiInitSystem
初始化了一些比较重要也比较常见的内核数据结构,这些数据结构中大量地使用了
LIST_ENTRY结构。如下所示:
代码:
VOID KiInitSystem (VOID)
{
  ULONG Index;

  // 初始化调度队列链表头,每一个优先级都有一个独立的进程链表
  for (Index = 0; Index < MAXIMUM_PRIORITY; Index += 1) {
    InitializeListHead(&KiDispatcherReadyListHead[Index]);
  }

  // 初始化BugCheck回调函数链表,及其旋转锁
  InitializeListHead(&KeBugCheckCallbackListHead);
  KeInitializeSpinLock(&KeBugCheckCallbackLock);

  // 初始化定时器过期的DPC对象
  KeInitializeDpc(&KiTimerExpireDpc,
    (PKDEFERRED_ROUTINE)KiTimerExpiration, NIL);

  // 初始化profile链表,及其旋转锁
  KeInitializeSpinLock(&KiProfileLock);
  InitializeListHead(&KiProfileListHead);

  // 初始化当前活动的profile链表
  InitializeListHead(&KiProfileSourceListHead);

  // 初始化定时器链表
  for (Index = 0; Index < TIMER_TABLE_SIZE; Index += 1) {
    InitializeListHead(&KiTimerTableListHead[Index]);
  }

  // 初始化swap通知事件
  KeInitializeEvent(&KiSwapEvent,SynchronizationEvent,FALSE);

  InitializeListHead(&KiProcessInSwapListHead);
  InitializeListHead(&KiProcessOutSwapListHead);
  InitializeListHead(&KiStackInSwapListHead);
  InitializeListHead(&KiWaitInListHead);
  InitializeListHead(&KiWaitOutListHead);

  // 初始化SSDT
  KeServiceDescriptorTable[0].Base = &KiServiceTable[0];
  KeServiceDescriptorTable[0].Count = NULL;
  KeServiceDescriptorTable[0].Limit = KiServiceLimit;
#if defined(_IA64_)
  KeServiceDescriptorTable[0].TableBaseGpOffset =
    (LONG)(*(KiServiceTable-1) - (ULONG_PTR)KiServiceTable);
#endif
  KeServiceDescriptorTable[0].
Mythos:首个可规模化自主攻防的AI安全执行体 漏洞挖掘正从人工驱动转向AI原生自动化,其核心是具备符号执行、POC生成与exploit构造能力的自主攻防系统。这类模型不再依赖提示工程,而是通过代码理解、二进制逆向与动态推理实现端到端漏洞闭环,技术价值在于将传统数周的安全审计压缩为分钟级API调用。典型应用场景覆盖云基础设施扫描、开源组件零日挖掘、DevSecOps实时响应等关键环节。Mythos作为当前最具代表性的实践范例,标志着AI安全已跨越辅助工具阶段,进入可调度、可复现、可规模化部署的工程化新纪元。 阅读详情

相关推荐

ProcessHacker 源码分析1

ProcessHacker 的版本在不断更新,版本2.33相应的开发环境也于是俱进地更新到了VS2013.之前研究的是2.88版本相应的是VS2010.  下定决心好好研究 ProcessHacker 和 ReatOS的代码。结合的参考资料有:毛德操的《windows 内核情景分析》还用潘爱民的《windows内核原理与实验》、经典的《Windows Internal》系列书籍、零散资料。

laoli0007的专栏 3166

深入理解Windows文件系统过滤驱动开发与FileMon源码解析

文件系统过滤驱动是操作系统中一个核心组件,它位于文件系统与应用程序之间,用于监控、记录或修改文件系统与进程间的交互。本章将为读者介绍文件系统过滤驱动的基本概念、功能及开发入门。WinDbg是一个功能强大的调试器,用于调试Windows操作系统中的内核模式驱动程序,以及用户模式应用程序和进程。它提供了一组丰富的命令用于分析和诊断系统问题,其核心是一个命令行接口,但也可以通过图形用户界面(GUI)扩展如KD、CDB和NTSD来使用。

weixin_42405592的博客 930

VirtualKD-3.0,支持win10--VMWare双机调试Windows神器

VirtualKD-3.0,支持win10--VMWare双机调试Windows神器

从MRF8P9040N数据手册到ADS仿真:手把手教你搞定LDMOS功放设计(附完整模型下载)

本文详细解析了MRF8P9040N LDMOS功率放大器的数据手册关键参数,并提供了在ADS中进行仿真的完整指南。从模型导入、直流工作点验证到负载牵引与阻抗匹配设计,逐步指导工程师完成高效功放设计。文章还包含调试技巧和常见问题解决方案,帮助优化射频功放性能。

weixin_27015733的博客 491

UDS 诊断 - CommunicationControl(通信控制)(0x28)服务 诊断

字节参数名称字节值#1CommunicationControl(通信控制)请求SID0x28#2#3communicationType(通信类型)#4nodeIdentificationNumer(节点标识符)(高位字节)controlType 为 0x04 或 0x05 时,使用该参数#5nodeIdentificationNumer(节点标识符)(低位字节)controlType 为 0x04 或 0x05 时,使用该参数。

耳朵东金子千的博客 1822

AD元件库构建及维护之——DbLib公共元件库的使用教程

AD元件库构建及维护之——DbLib元件库的使用教程

qq_43105486的博客 2万+

vba 修改下拉列表_Excel联想式下拉菜单制作教程II

?点击关注Excel表哥公众号上期我们分享了Excel联想式下拉菜单制作教程,可以简化大家在下拉菜单过长时的数据录入工作。文章末尾给大家提出了一个问题:为什么下拉列表数据源需要先排序?今天我们继续分享一个不用对数据源排序也能实现的下拉列表制作方法。先看最终的效果动图:今日分享难度指数:★★★★☆01创建辅助列在需要设置下拉列表的工作表中创建一列辅助列,如下图所示:在辅助列F3单元格输入下...

weixin_39593718的博客 1576

时空智友企业信息管理系统任意文件读取漏洞复现

时空智友企业信息管理系统是一个用于企业流程管理和控制的软件系统。它旨在帮助企业实现流程的规范化、自动化和优化,从而提高工作效率、降低成本并提升管理水平。时空智友企业信息管理系统存在任意文件读取漏洞,攻击者可以在未授权的情况下读取系统上的文件。没有人规定,一朵花一定要成长为向日葵或者玫瑰。

The current road is different, love needs to distinguish between right and wrong 971

如何修改网页中的文本内容改成自己希望的数值?

本篇文章主要讲解,通过浏览器命令和浏览器自带的F12开发者工具,进行修改网页内容的方法教程 日期:2021年12月5日 作者:任聪聪 一、通过F12开发者工具进行修改 进入方式汇总: 1.右击鼠标,显示菜单找到审查 2.通过快捷键F12进入,笔记本需要先关闭fnlk功能键。 开发者工具介绍 说明: 1.表示选择元素,点击后可以选择文本的元素所在地 2.表示显示方式,手机还是电脑 3.表示div元素,点击后可以展开,对div内的html和文本进行编辑。 双击文本,即可进行修改成自己想要的,但是刷新后.

任聪聪的博客 2万+

SAP ABAP SSSLERR_PEER_CERT_UNTRUSTED 证书过期+证书导入+案例详解+注意事项

出于 IT 审计与安全管理,外部系统间通讯发布的 API 主流都是 HTTPS 协议,SAP 支持 SSL 证书。SSL 证书是有效期的,当证书失效时将返回错误 SSSLERR_PEER_CERT_UNTRUSTED ,此时需要导入新效期的证书。这篇文章完整讲解了证书过期处理的全过程。

SAP李斌,本人承诺所有原创文章均不使用任何AI生成技术,请大家放心阅读。 2370

笔试题-2023-芯动-数字IC设计【纯净题目版】

笔试题-2023-芯动-数字IC设计【纯净题目版】

w0shishabi的博客 6397

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

上一篇: 运行程序前执行自己的代码
下一篇: MS09-001漏洞基本分析
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值