最开始的是loadros.asm,它会将ntoskrnl.exe等各个模块读入内存,并跳到0:901000。同时它还会初始化一个_LOADER_PARAMETER_BLOCK数据结构。
typedef struct _LOADER_PARAMETER_BLOCK
{
ULONG Flags;
ULONG MemLower;
ULONG MemHigher;
ULONG BootDevice;
ULONG CommandLine;
ULONG ModsCount;
ULONG ModsAddr;
UCHAR Syms[12];
ULONG MmapLength;
ULONG MmapAddr;
ULONG DrivesCount;
ULONG DrivesAddr;
ULONG ConfigTable;
ULONG BootLoaderName;
} LOADER_PARAMETER_BLOCK, *PLOADER_PARAMETER_BLOCK;
并且初始化_LOADER_MODULE数据结构的数组,每个pe文件对应一个。
typedef struct _LOADER_MODULE
{
ULONG ModStart;
ULONG ModEnd;
ULONG String;
ULONG Reserved;
} LOADER_MODULE, *PLOADER_MODULE;
通过跳转0:901000,来到ntoskrnl.exe的_NtProcessstartup模块,它是一段16位的代码。初始化页目录、页表。初始化GDT、IDT。最后跳到main.c中的_main函数。
_main将bootloader中得到信息进一步处理。例如bootloader是将各个模块读入到低端内存,而经过分页后,ntoskrnl.exe被应设在0xc0000000的位置。重新修改LOADER_PARAMETER_BLOCK结构和LOADER_MODULE结构的信息。
然后调用LdrSafePEProcessModule,将ntoskrnl.exe hal.sys重定向内存。
最后调用KiSystemStartup