没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
Gloomy 对 Windows 内核的分析(介绍)
文章整理 By sunsjw QQ:509207758
INTRO (写给 NT 研究者)
=============================
Мы всего лишь момент во времени
Отблеск в глазах,
Мечты о слепоте,
Образы умирающего ра с с у д к а ...
(c) by Anathema
00.系统组件
01.Windows NT 操作系统的内存格局
02.Windows NT 与 FLAT 模型
03.线程信息块(THREAD INFORMATION BLOCK)
04.进程控制域(PROCESSOR CONTROL REGION)
00.系统组件
=====================
实际上,所有的 Windows NT 组件其本身都是 DLL、PE 格式的.EXE 文件、导入导出函数。
Windows NT 的主要组件有:
*Ntoskrnl.exe
系统核心。系统执行函数都集中于此,这些函数又会调用其它组件。核心组件有:对象
管理器、内存管理器、进线程创建、进线程控制、LPC、安全管理、异常处理、文件系统、
输入输出、VDM、和т .д .一般都位于大于 80100000h 的地址上。
*Hal.dll
硬件抽象层(Hardware Abstraction Layer)- 硬件相关的模块。该隔离层将操作系
统中硬件相关的部分隔离出来以增强系统的可移植性。主要的模块实现了非常底层的函数:
程序控制中断、硬件输入输出等等。一般位于大于 80100000h 的地址上。
*Ntdll.dll
实现某些 Win32 API 函数。提供了核心模式与用户模式之间的接口。位于用户空间。换
句话说,系统函数调用主要由这里导出。
*Kernel32.dll
实现了一些函数,类似于 Win9x 的核心。其中有很多的函数封装在 ntdll.dll 中。
*Csrss.exe
进程服务器子系统。其是一个单独的进程,因此受到保护以免受其它进程(位于其它进
程的地址空间中)影响。对服务的请求要借助于 LPC 产生。
*Win32k.sys
驱动程序。用以减少调用 Csrss 服务开销损失。在此程序中实现了 GDI 和 USER 函数。
不用 LPC 而用系统调用-这很明显提高了 Windows NT4.0 和 2K 的图形处理性能。
01.Windows NT Windows NT 操作系统的内存格局
=============================
在 Windows NT 中高 2G 的 32 位线性地址空间保存了供系统使用的程序。这种格局,地
址空间 80000000 - ffffffff 为系统组件:驱动程序、系统表、系统数据结构等等。系统
内存的精确格局是不可能得到的,但是通过其功能用途和大致位置可以区分出各个区域。
*80000000-9FFFFFFF
系统代码。在这里驻留的是 Hal 和 ntoskrnl 的代码和数据,还有驱动程序(boot 驱动和
加载 ntosldr 的驱动)。GDT、IDT 和 TSS 结构体同样驻留在这些区域中。
*C0000000-C0FFFFFF
系统表的区域。这个线性地址空间区域保存着进程的页表,页目录和其它与进程结构体
有关的东西。这个区域不是全局性的,不像其它的系统空间区域,而且对于于每一个进程来
说会映射到不同的物理空间,其保存着当前进程的数据结构。
*E1000000-E57FFFFF
分页池。这个区域可以换出到磁盘上。操作系统中的大多数对象都在这个区域中产生。
实际上一些内存池位于这个区域中。
*FB000000-FFDFEFFF
不可换出页的区域,即非分页区(Non Paged Poll)。这个区域中的数据永远不能换出到
磁盘上。这个区域中的数据总是系统必需的数据。例如,这里有进程与线程的信息块(Thread
environment block, Process Environment block)。
*FFDFF000-FFFFFFFF
PCR - Processor Control Region (进程控制域) 用于每一个进程。这个区域中保存着 PCR
结构体。在此结构体中保存着系统状态的信息。例如,关于 IRQL、当前线程、IDT 等的信息。
低 2G 线性地址空间(00000000-0FFFFFFFF)为进程用户模式的地址空间(每个进程自
己的空间)。Win32 地址空间看上去一般是下面这个样子:
*00000000-0000FFFF
保护区域。访问此区域会引发异常。被用于检测 NULL 指针。
*00xx0000
通常,应用程序加载在这样的地址上。
*70000000-78000000
Win32 子系统的库通常映射到这里。
*7FFB0000-7FFD3FFF
代码页。
*7FFDE000-7FFDEFFF
用户模式的 Thread Environment Block。
*7FFDF000-7FFDFFFF
用户模式的 Process Environment Block。
*7FFE0000-7FFE0FFF
共享数据区。
*7FFFF000-7FFFFFFF
保护区域。
02.Windows NT 与 FLAT 模型
===========================
自 i286 开始,在 Intel 的处理器里实现了四级保护机制,相应的就有四个特权级。代码
与数据能够拥有某级别的特权。这样,应用程序、系统程序、内核等等都运行在自己的特权
级上,而且不能随意访问比自己特权级高的代码和数据。实际上没有一个基于 Intel 处理器
的操作系统能用到所有的四个特权级(不为人知的那些不算在内)。Windows NT 操作系统也
不例外,只用到了两个特权级(ring)。 0 级(最高特权级)下运行内核,3 级(最低特权级)
为用户级。Intel 处理器提供了强大的内存分段机制,其与特权级一起实现了直到段级的保
护(例如,程序的每一个逻辑段都可以由一个描述符表来描述)。但是 Windows NT 实现的
是 FLAT 模型。这就将选择子的使用降到了最低限度。处理器的全局描述符表 GDT(Global
Descriptor Table),由 Windows NT 操作系统管理,其包含以下描述符(由 SoftIce'a 得到):
Sel. Type Base Limit DPL Attributes
GDTbase=80036000 Limit=03FF
0008 Code32 00000000 FFFFFFFF 0 P RE
0010 Data32 00000000 FFFFFFFF 0 P RW
001B Code32 00000000 FFFFFFFF 3 P RE
0023 Data32 00000000 FFFFFFFF 3 P RW
0028 TSS32 8024D000 000020AB 0 P B
0030 Data32 FFDFF000 00001FFF 0 P RW
003B Data32 7FFD9000 00000FFF 3 P RW
0043 Data16 00000400 0000FFFF 3 P RW
0048 LDT E1190000 000001FF 0 P
0050 TSS32 80149F60 00000068 0 P
0058 TSS32 80149FC8 00000068 0 P
0060 Data16 00022940 0000FFFF 0 P RW
0068 Data16 000B8000 00003FFF 0 P RW
0070 Data16 FFFF7000 000003FF 0 P RW
0078 Code16 80400000 0000FFFF 0 P RE
0080 Data16 80400000 0000FFFF 0 P RW
0088 Data16 00000000 00000000 0 P RW
0090 Reserved 00000000 00000000 0 NP
...
00E0 Reserved 00008003 00006100 0 NP
00E8 Data16 00000000 0000FFFF 0 P RW
00F0 Code16 80117DB0 0000028D 0 P EO
00F8 Data16 00000000 0000FFFF 0 P RW
0100 Reserved 00008003 00006108 0 NP
...
03F8 Reserved 00000000 00000000 0 NP
前 四 个选 择子 全都 位于 线性 地 址空 间。 而且 前两 个选 择子 的 描述 符特 权级 DPL
(Descriptor Privilege Level)等于 0,而后面两个的都是 3。选择子 8 和 10 由用户应用程序
使用。在 FLAT 模型下,应用程序本身并不关心段寄存器的内容。在 ring3 工作时,CS、DS、
SS 寄存器总是分别为值 8、10、10。这样,系统代码就可以监视段寄存器的值。选择子 1b
和 23 用于内核(驱动程序、系统代码)工作时的寻址。选择子 30 和 3b 分别指向 Kernel Process
Region 和 Thread Information Block。当代码运行在 ring0 时,FS 寄存器的值为 30,如过运行
在 ring3,则 FS 的值为 3b。选择子 30 总是指向基址为 FFDFF000 的描述符。选择子 3b 指示
的基址则依赖于用户线程。选择子 48 定义了局部描述符表 LDT(Local Descriptor Table)。 LDT
只在 Virtual DOS machine(VDM)应用程序下使用。当运行该进程时,在处理器的 LDTR
寄存器中加载着相应的指针,否则,LDTR 的值为 0。LDT 主要用在 Windows 3.x 应用程序下。
Windows 3.x 应用程序运行在 WOW(Windows On Windows)下,而 WOW 则实现在 VDM 进
程里。VDM 进程的 LDT 使用上和 Win3.x 里的一样。在 GDT 表里总会有两个 TSS 类型的选择
子。这是因为运行在 Intel 处理器上的 Windows NT 操作系统没有使用基于任务门的任务切换
机制。IDT 包含以下描述符(由 SoftIce'a 得到):
Int Type Sel:Offset Attributes Symbol/Owner
IDTbase=F8500FC8 Limit=07FF
0000 IntG32 0008:8013EC54 DPL=0 P _KiTrap00
...
0007 IntG32 0008:8013F968 DPL=0 P _KiTrap07
0008 TaskG 0050:00001338 DPL=0 P
0009 IntG32 0008:8013FCA8 DPL=0 P _KiTrap09
...
0012 IntG32 0008:80141148 DPL=0 P _KiTrap0F
...
001F IntG32 0008:80141148 DPL=0 P _KiTrap0F
0020 Reserved 0008:00000000 DPL=0 NP
...
0029 Reserved 0008:00000000 DPL=0 NP
002A IntG32 0008:8013E1A6 DPL=3 P _KiGetTickCount
002B IntG32 0008:8013E290 DPL=3 P _KiCallbackReturn
002C IntG32 0008:8013E3A0 DPL=3 P _KiSetLowWaitHighThread
002D IntG32 0008:8013EF5C DPL=3 P _KiDebugService
002E IntG32 0008:8013DD20 DPL=3 P _KiSystemService
002F IntG32 0008:80141148 DPL=0 P _KiTrap0F
0030 IntG32 0008:80014FFC DPL=0 P _HalpClockInterrupt
0031 IntG32 0008:807E4224 DPL=0 P
0032 IntG32 0008:8013D464 DPL=0 P _KiUnexpectedInterrupt2
0033 IntG32 0008:80708864 DPL=0 P
0034 IntG32 0008:807CEDC4 DPL=0 P
0035 IntG32 0008:807E3464 DPL=0 P
0036 IntG32 0008:8013D48C DPL=0 P _KiUnexpectedInterrupt6
0037 IntG32 0008:8013D496 DPL=0 P _KiUnexpectedInterrupt7
0038 IntG32 0008:80010A58 DPL=0 P _HalpProfileInterrupt
0039 IntG32 0008:8013D4AA DPL=0 P _KiUnexpectedInterrupt9
...
00FF IntG32 0008:8013DC66 DPL=0 P _K iUnexpectedInterrupt207
表中主要的门类型为中断门。中断任务只是用在关键的时刻,保证特殊情况下能正确完
成应急处理,比如说,双重异常(8 号中断)。中断 2e 是系统调用。中断 30 到 3f 对应于 irq0
- irq15。于是,总是有两个 TSS 选择子。其中一个(50)用于双重异常。TSS 中除了其自己
必需部分所占空间外,还在 104 个字节中保存了一个输入输出位图。在执行 Win32 应用程
序的时候,TSS 中的指针保存着不正确的值,这样任何对端口的操作都会引发异常。在 VDM
工作的时候,位图用来选择是否禁止对端口的访问。我们来看一下在 FLAT 模型下是如何进
行保护的。要研究这个问题需要将注意力转向下面这个条件——保护的原则应该是:保护内
核不受用户进程的干扰、保护一个进程不受另一个进程的干扰、保护子系统的代码和数据不
受用户进程的干扰。Windows NT 的线性地址空间可以分成用户空间(通常为 0-7fffffff)和
系统与内核空间(通常为 80000000-ffffffff)。切换上下文时,内核空间对于所有进程几乎都
是一样的。在 Windows NT 中使用了分页保护的内存。这样,实现内核同用户进程隔离方法
就是将核心空间地址页的页表项指针的 U/S 位置零。这样就不能在 ring3 下随意访问 ring0
下的代码和数据了。同样页的寻址也使得进程彼此间的地址空间得到隔离。Windows NT 保
留了 4KB 的页作为区域 c0300000 中的页目录,该页目录映射了所有的 4GB 物理地址空间。
在页目录中有 1024 个页目录项。每个页目录项都应是 4B 大小(4KB/1024)。 1024 个页目录
项指向 1024 个页表,每个页表指向一个 4KB 的页。页目录的基地址在上下文切换时会相应
发生变化并指向将被使用的页目录,当执行新线程时这个页目录被用于线性地址向物理地址
的转换(在 Intel 处理器中这个物理基地址位于 CR3 寄存器中)。
结果,不同的上下文中里的地址空间(00000000-7fffffff)中一样的线性地址能够映射到
不同物理地址上,实现了进程地址空间的彼此隔离。内核空间实际上对所有的上下文都是一
样的,其被保护起来不能由用户代码访问,内核代码的页表项的 U/S 位为零。下面我们将不
剩余102页未读,继续阅读
资源评论
- pediype2012-07-06这本书我找了许久了,网上找到的都只有对象管理器这章
glasses_sun
- 粉丝: 2
- 资源: 2
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功