NT4系统启动流程

windows引导过程

Windows 内核中的各个组件和各种机制在起作用以前,必须首先被初始化。此初始化工作是在系统引导时完成的。当用户打开计算机的电源开关时,计算机便开始运行,但操作系统并不立即获得控制权,而是BIOS 代码首先获得控制,它执行必要的硬件检测工作,并允许用户通过一些功能键来配置当前系统中的硬件设置,甚至诊断硬件问题,然后才将控制权交给操作系统。

内核加载

在Intel x86 系统上,Windows 操作系统获得控制首先从硬盘的主引导记录(MBR,Master Boot Record)开始,Windows Setup 程序在安装Windows 时填充MBR(其他的磁盘管理程序也可能填充MBR)。MBR 包含代码和数据,其代码称为引导代码,在系统引导时首先获得控制;MBR 中的数据是一张分区表,指定了每个分区在磁盘上的位置和大小,以及分区的类型。当MBR 中的引导代码被执行时,它检查分区表中的每一个分区,若找到一个已被标记为可引导的分区(称为引导分区),则将该分区的第一个扇区(称为引导扇区)读到内存中。由于分区表包含了每一个分区的磁盘位置,所以,引导扇区的位置很容易被确定。然后MBR 的代码将控制权交给引导扇区中的代码。Bios验证mbr,55aa,。Mbr验证vbr。

bios验证mbr,mbr验证vbr

relocated_org   equ 0600h
buildtime_org   equ 0100h
org_delta       equ (relocated_org - buildtime_org)
_data   segment public
        assume  cs:_data,ds:_data
        org buildtime_org
; 这段代码读出位于主引导记录末尾的分区表,找到标志为可引导的分区,把它的引导扇区拷贝到内存中并执行
start:
        cli             ;开始的时候并没有中断,他要确保不会被更高级别关中断
        xor ax,ax
        mov ss,ax
        mov sp,7c00h    ;位于地址0:7c00处的新堆栈
        mov si,sp        ; 0:7c00为标准引导地址  
        push ax		;mov es,ax
        pop es          
        push ax        
        sti             ;允许中断
        cld
        mov di,relocated_org         mov cx,100h
        rep movsw      ;复制,从esi复制edi,复制100h次word 
 ;重定位到地址 0000:0600,跳到这里从分区表中读取可引导分区的入口,把引导分区拷贝到内存的标准引导地址(0000:7C00)

;       jmp entry2 + org_delta	;指令会被平移
        db   0eah
        dw   $+4+org_delta,0
entry2:
        mov si,(offset tab) + org_delta  ;表示分区表
        mov bl,4        ;分区表项的个数
next:
        cmp byte ptr[si],80h  ;判断是否是可以引导的入口,cmp必须是80,test不用
        je boot         ;yes
        cmp byte ptr[si],0    ;再次判断是否为0
        jne bad         ;不是,只有 x"00" 或者x"80" 是有效的
        add si,16       ;执行到下一个入口点
        dec bl
        jnz next
        int 18h         ;未检测到可引导的入口,返回
boot:
        mov dx,[si]     ;引导开始处
        mov cx,[si+2]  
        mov bp,si       ;保存表入口地址并传给分区引导记录
next1:
        add si,16       ;下一个表项
        dec bl          ;表项数目递减
        jz tabok        
        cmp byte ptr[si],0    ;所有剩余的表入口都要从0开始
        je next1        ;满足上述判断条件
bad:
        mov si,(offset m1) + org_delta ;无法找到一个从0开始的表项入口,该表为坏表



msg:
        lodsb           ;获取显示信息的字符
        cmp al,0
        je  hold
        push si
        mov bx,7
        mov ah,14
        int 10h          ;显示信息
        pop si
        jmp msg         ;循环打印完整信息

hold:   jmp hold        ;此处自旋,不做任何事
tabok:
        mov di,5        ;计数值,读几次磁盘机会
rdboot:
        mov bx,7c00h    ;读取系统引导记录的位置,vbr读到这个位置
        mov ax,0201h    ;读取一个扇区
        push di
        int 13h          ; 获取引导记录
        pop di
        jnc goboot      ;成功得到引导记录,交与控制权
        xor ax,ax        ;出现错误
        int 13h          ;重新校准
        dec di           ;递减计数值
        jnz rdboot       ;只要计数值仍大于0,就继续尝试
        mov si,(offset m2) + org_delta ;所有的入口都已检测完毕,错误无法避免
        jmp msg          ;跳转到显示错误信息



goboot:
        mov si,(offset m3) + org_delta 
        mov di,07dfeh
        cmp word ptr [di],0aa55h ;判断引导记录是否有效
        jne msg         ;无效,则显示无效的系统引导记录信息
        mov si,bp       ;有效,则将分区表入口地址传给它
        db 0eah
        dw 7c00h,0
include x86mboot.msg 
        org 2beh     ;此处显示了主引导记录的结构
tab:                     ;partition table
        dw 0,0          ;partition 1 begin
        dw 0,0          ;partition 1 end
        dw 0,0          ;partition 1 relative sector (low, high parts)
        dw 0,0          ;partition 1 # of sectors (low, high parts)
        dw 0,0          ;partition 2 begin
        dw 0,0          ;partition 2 end
        dw 0,0          ;partition 2 relative sector
        dw 0,0          ;partition 2 # of sectors
        dw 0,0          ;partition 3 begin
        dw 0,0          ;partition 3 end
        dw 0,0          ;partition 3 relative sector
        dw 0,0          ;partition 3 # of sectors
        dw 0,0          ;partition 4 begin
        dw 0,0          ;partition 4 end
        dw 0,0          ;partition 4 relative sector
        dw 0,0          ;partition 4 # of sectors
signa   db 55h,0aah     ;引导区有效签名值
_data   ends
        end  start

Windows Setup 程序在确定了要将Windows 系统安装到哪个分区中以后,除了可能会写入MBR 以外,还会写入该分区的引导扇区。所以,严格意义上讲,Windows 操作系统的真正入口点应该是引导扇区中的代码。引导分区必须被格式化成Windows 所支持的文件系统,典型的文件系统格式是NTFS 和FAT,其中NTFS 是Windows NT 的原生文件系统,而FAT 则是从MS-DOS 时代继承和发展过来的。

引导扇区中的代码随硬盘文件系统格式的不同而有所不同,其职责是,给Windows提供有关该硬盘上卷的结构和格式方面的信息,并且从该卷的根目录中读入Windows 的加载程序,即ntldr 文件;然后将控制权交给ntldr 的入口函数。(6.0以后Bootmdr bootload)为了能够从根目录中读入加载程序,引导扇区包含了能理解文件系统结构和读取文件的代码,这通常只是文件系统极其简单的一部分功能,而并非完整的实现。尽管引导扇区的职责相对简单,但是单个扇区(512 B)的代码和数据往往不足以完成其功能,为此,Windows 的做法是,让引导扇区中的代码读入其他扇区的数据,然后跳转到下一个扇区的代码区。这样就可以不受单个引导扇区长度的限制,这种做法相当于将第一个引导扇区当做一个加载器(loader),而真正完成引导扇区功能的扇区随后被加载进来并执行。这一过程对于MBR 是透明的,从而保持良好的兼容性。

Intel x86 处理器支持实模式和保护模式,在实模式下,处理器的寄存器都是16 位的,而且不支持虚拟地址转译,只能访问物理内存空间中最低的1 MB 内存。计算机系统的BIOS 工作在实模式下,并且,当ntldr 获得控制权时,处理器仍然在实模式下运行。Ntldr文件实际上是由两部分组成的:第一部分是实模式代码,即首先获得控制的代码区;第二部分是一个标准的Windows 可执行二进制文件,在ntldr 中这部分被称为os loader。

Ntldr 的实模式代码首先获得控制,它的任务是,完成需在16 位模式下执行的初始化工作,例如清除键盘缓冲区,然后为切换到保护模式做好基本的环境准备,之后将处理器切换到保护模式(32 位模式)下,这样它就可以访问整个32 位地址空间了。最后它将控制权交给os loader。

 loader 刚接获控制时,处理器虽然已经工作在保护模式下,但是它的虚拟地址转译机制尚未开启,所以,处理器仍然直接使用物理地址。Os loader 首先做的工作是把物理内存管起来,用一个内存描述符(memory descriptor)数组把每一段内存的大小和用途记录下来,然后构造页目录和页表,使得16 MB 以下的内存能够通过页面映射(paging)机制进行访问,再设置好页目录寄存器,并打开页面映射机制。之后,os loader 继续执行其他的初始化工作,包括I/O 设备的初始化等。如果它还需要调用BIOS 中的服务(比如中断13h、中断15h 等),则必须保护好保护模式下的设置,并暂时切换回到实模式,待服务完成以后再切换到保护模式,并恢复设置。

(cr0)

Windows 的引导选项可以用来指示当前这次引导的各种参数,包括内核模块的文件名称、HAL 的文件名称、CPU 参数、各种内存参数、调试参数,等等。关于这些引导选项的全面列表和介绍,可参考[MSDN-BOOT]。接下来os loader 加载并执行NTDETECT.COM 程序,这是一个16 位实模式程序,它利用系统的BIOS 来查询系统的基本设备和配置信息,包括系统的日期和时间、总线的类型、磁盘的信息、输入/输出的接口信息等。这些信息被收集起来,在引导过程的后期被存放到注册表HKLM\HARDWARE\DESCRIPTION 键的下面。

接下来,os loader 从系统分区(即引导分区)的根目录下读入boot.ini 文件。注意,os loader 包含了读取当前文件系统的代码,它能够读取NTFS 文件系统的子目录。然后,os loader 清除屏幕,并检查在系统分区的根目录下是否有一个有效的hiberfil.sys 文件,如果存在的话,这一次引导过程转移到休眠系统的恢复过程。因此,os loader 将控制权交给一段能恢复休眠系统的内核代码。

如果当前这次引导不是休眠恢复,那么,os loader 解析boot.ini 文件,如果该文件中有多个引导选项,则os loader 显示一个引导选择菜单;如果boot.ini 文件中只包含一个引导选项,那么,此菜单不显示,而是立即应用该引导选项。

 

然后,os loader 加载内核模块映像文件,默认为ntoskrnl.exe,以及HAL 映像文件,默认为hal.dll。再加载注册表的SYSTEM 储巢,即\WINDOWS\system32\config\system 文件。通过检查SYSTEM 储巢中的设置信息,它可以知道哪些设备驱动程序必须被加载进来,即被标记为“引导-启动”(SERVICE_BOOT_STARTboot必须放在规定路径下,因为系统文件驱动还没加载,放其他地方不识别)的设备驱动程序。然后它加载所有这些被标记为“引导-启动”的设备驱动程序,以及访问系统目录所必需的文件系统驱动程序。注意,在此之前os loader 也可以访问系统分区,但并非通过文件系统驱动程序。

在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\xxxx 都有个start,有0boot,1NTOSKERL,2系统加载,3手动,4禁止

注意boot0驱动有ntldr加载,这时候文件系统还没起来之放放在system32,这时候只能访问系统分区,而且文件系统有他加载,所以肯定不能放在其他位置。

boot0驱动不能操作其他路径下的注册表。boot0驱动DriverEntry需要注册一个driverinitalize例程操作其他路径注册表,因为在boot0驱动开始此时很多都没加载。

xxxx

引导系统所需的模块(包括内核映像、HAL,以及必要的设备驱动程序)都已经被加载到内存中。而且,在此过程中os loader 也已经构造了一个参数块,记录下了这次引导过程中加载器所获得的各种参数信息。参数块的类型为LOADER_PARAMETER_BLOCK,Windows 内核在初始化过程中将会用到这些参数信息。WRK 中包含有它的定义,如下(见public\internal\base\inc\arc.h 文件):

typedef struct _LOADER_PARAMETER_BLOCK {

    LIST_ENTRY LoadOrderListHead;   //加载的模块链表,每个元素都为KLDR_DATA_TABLE_ENTRY

LIST_ENTRY MemoryDescriptorListHead;

//内存描述符链表,每个元素都为MEMORY_ALLOCATION_DESCRIPTOR     

    LIST_ENTRY BootDriverListHead; //引导驱动程序链表,每个元素都为BOOT_DRIVER_LIST_ENTRY

    ULONG_PTR KernelStack;      //内核栈顶

    ULONG_PTR Prcb;                 //进程环境,指向一个进程控制块

    ULONG_PTR Process;            //初始进程,EPROCESS

    ULONG_PTR Thread;             //初始线程,ETHREAD

    ULONG RegistryLength;         //系统储巢的长度

    PVOID RegistryBase;             //系统储巢的基地址

PCONFIGURATION_COMPONENT_DATA ConfigurationRoot;    

//配置树,包含ISA,磁盘和ACPI的配置数据

    PCHAR ArcBootDeviceName;                      //引导分区的ARC名称

    PCHAR ArcHalDeviceName;                //系统分区的ARC名称

    PCHAR NtBootPathName;                  //OS目录的路径名称,比如"\Windows"

    PCHAR NtHalPathName;                             //OD加载器的路径名称,比如"\"

    PCHAR LoadOptions;                                 //引导选项,来自boot.ini

    PNLS_DATA_BLOCK NlsData;                       //包含ANSI代码页,OEM代码页和Unicode码表

    PARC_DISK_INFORMATION ArcDiskInformation;     //所有磁盘的签名结构

    PVOID OemFontFile;                                   //OEM字体文件

    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;

由上述代码的注解可以看出,LOADER_PARAMETER_BLOCK 参数块中包含了有关这次引导的各种参数信息和系统配置,这里ARC 名称是指符合ARC(Advanced RISCComputing)命名规范的字符串,例如“multi(0)disk(0)rdisk(0)partition(1)”是指0 号磁盘控制器第一块硬盘上的第一个分区。注意,参数块中的绝大多数信息由os loader 来填充,而在接下来的内核初始化过程中使用,但也有例外,比如有关线程和进程的信息需要在内核初始化过程中填充。

 

最后,os loader 将控制权交给内核模块的入口函数,该函数将不再返回,所以,接下来的引导过程由内核模块继续进行,引导扇区和系统加载器(ntldr 或os loader)的使命已经完成。下图显示了以上介绍的引导步骤。

bootkit就是在MBR这时劫持,挂钩int13h,目的是在ntldr加载时候获得控制权,目的是当ntldr加载好ntoskrnl.exe系统驱动时候获得控制权,读取上面的链表,找到ntoskrnl所在的内存空间,对notoskrnl进行hook,当下次notskrnl执行时候进行操作,直到内核加载完就可以做需要做的事情了。

 

 

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值