freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

微处理器权限管理之——描述符表
2021-07-04 15:15:39
所属地 内蒙古

段描述符表格式

段描述符是GDT或LDT中的数据结构,可为处理器提供段的大小和位置以及访问控制和状态信息。 段描述符通常是由编译器,链接器,加载器或操作系统或执行程序创建的,而不是由应用程序创建的。 图1说明了所有类型的段描述符的通用描述符格式。

image.png

图1

图2是在对win10进行内核调试时获取的全局描述符表(GDT)部分内容。


1625369221_60e12a857c6e0084f7a93.png!small?1625369221578

图2

段描述符中的标志和字段含义如下:

1———段限制字段(segment limit):

用来指定段的大小。 处理器将两个段限制字段放在一起以形成一个20bit的值。 处理器根据G(粒度)标志的设置,以两种方式之一解释分段限制:

如果清除了粒度标志,则段大小的范围可以从1字节到1 MB,以字节为增量。

如果设置了粒度标志,则段大小的范围为4 KB至4 GB,以4 KB为增量。

处理器根据段是向上扩展段还是向下扩展段,以两种不同方式使用段限制。

对于向上扩展的段,逻辑地址中的偏移范围可以从0到段限制。大于段限制的偏移量会生成一般保护异常(对于除SS以外的所有段,为#GP)或栈故障异常(对于SS段为#SS)。

对于向下扩展的段,段限制具有相反的功能;偏移量可以在段限制加1到FFFFFFFFH或FFFFH之间,具体取决于B标志的设置。小于或等于段限制的偏移量会生成一般保护异常或栈故障异常。减小扩展段的段限制字段中的值会在段地址空间的底部而不是顶部分配新的内存。

IA-32体系结构栈始终向下增长,从而使该机制便于扩展栈。

2———基地址(base address):

定义段的字节0在4 GB线性地址空间内的位置。 处理器将三个基地址字段放在一起以形成单个32位值。 段基地址应与16字节边界对齐。 尽管不需要16字节对齐,但是此对齐允许程序通过在16字节边界上对齐代码和数据来最大化性能。

3———类型(type):

指示段或门(gate)的类型,并指定可对段进行访问的类型和增长方向。 该字段的解释取决于描述符类型标志是指定应用程序(代码还是数据)描述符还是系统描述符。 对于代码,数据和系统描述符,type字段的编码是不同的。如图3所示,不同类型的段有不同的类型字段。

1625368797_60e128dda36b3d0a57a2c.png!small?1625368796031

图3

4———S标志(S flag):

指定段描述符是用于系统段(清除S标志)还是代码或数据段(已设置S标志)。

5———DPL(descriptor privilege level):

指定段的权限级别。 权限级别的范围可以从0到3,其中0是最高权限级别。 DPL用于控制对段的访问。

6———P标志(P flag):

指示该段是存在于内存中(设置)还是不存在(清除)于内存中。

  • 如果清除此标志,则将指向段描述符的段选择器加载到段寄存器中时,处理器会生成不存在段异常(#NP)。 内存管理软件可以使用此标志来控制在给定时间将哪些段实际加载到物理内存中。 除了分页之外,它还提供了用于管理虚拟内存的控件。图4显示了当P=0(清除)时,段描述符号的格式。清除此标志后,操作系统或程序(executive)可以自由使用标记为“可用”的位置来存储自己的数据,例如有关丢失段(missing segment)下落的信息。

1625369444_60e12b6444fe73726eb10.png!small?1625369442643

图4


7———D/B标志(D/B flag):

根据段描述符是可执行代码段,扩展数据段还是栈段,执行不同的功能。 (对于32位代码和数据段,此标志应始终设置为1;对于16位代码和数据段,此标志应始终设置为0。)

可执行代码段:该标志称为D标志。它指示段中指令引用的有效地址和操作数的默认长度。 如果设置了该标志,则假定使用32位地址和32位或8位操作数; 如果清除,则假定使用16位地址和16位或8位操作数。指令前缀66H可以用于选择默认值以外的操作数大小,而前缀67H可以用于选择默认值以外的地址大小。

扩展数据段:该标志称为B标志。它指定段的上限。 如果设置了标志,则上限为FFFFFFFFH(4 GB);否则,上限为FFFFFFFFH(4 GB)。 如果清除该标志,则上限为FFFFH(64 KB)。

栈段:该标志称为B(大)标志,它指定用于隐式栈操作(例如推入,弹出和调用)的栈指针的大小。 如果设置了该标志,则使用32位栈指针,该指针存储在32位ESP寄存器中。 如果清除该标志,则使用16位栈指针,该指针存储在16位SP寄存器中。 如果将栈段设置为向下扩展数据段(在下一段中描述),则B标志还将指定栈段的上限。

8———G标志(G flag):

确定段限制字段的缩放比例。

清除粒度标志时,将以字节为单位解释段限制。
当设置了标志时,将以4 KB为单位解释段限制。(此标志不影响基地址的粒度;它始终是字节粒度的。)设置了粒度标志后, 当对照段限制检查偏移量时,不测试偏移量。 例如,当设置了粒度标志时,限制为0会导致从0到4095时有效偏移量。

9———L标志(L flag)

在IA-32e模式下,L指示代码段是否包含本机64位代码。

值为1表示此代码段中的指令以64位模式执行。如果设置了L位,则必须清除D位。

值为0表示此代码段中的指令在兼容模式下执行。

当不在IA-32e模式下或对于非代码段时,L应始终设置为0。

10———AVL(Available and reserved bits)

AVL供系统软件使用。

系统描述符表类型

当段描述符中的 S标志清除时,描述符类型为系统描述符。 处理器识别以下类型的系统描述符:

本地描述符表(LDT) 段描述符。

任务状态段(TSS) 描述符。

呼叫门描述符。

中断门描述符。

陷阱门描述符。

任务门描述符。

这些描述符类型分为两类:系统段描述符和门描述符。 系统段描述符指向系统段(LDT 和 TSS 段)。 门描述符本身就是“门”,它保存着指向过程入口的指针。图5显示了系统段描述符和门描述符的类型字段的编码,描述符的type区域通过各种组合来表达各种描述符类型。 注意IA-32e 模式下的系统描述符是 16 字节而不是 8 字节。1625380037_60e154c5841ec102b327b.png!small?1625380038397

图5

段描述符表是段描述符的数组。 描述符表的长度是可变的,最多可以包含18192(213)个8字节描述符。在寻址时重点关注2种描述符:GDT(全局描述符表)和LDT(本地(local)描述符表)。

当段选择器中的TI=0表示使用全局描述符表,TI=1时使用本地描述符表,如图6所示。

1625380573_60e156dd1ef2ebc3fcb68.png!small?1625380572991

图6

GDTR寄存器指向GDT,LDTR寄存器指向LDT。两个寄存器的内容如图7所示。

1625380720_60e157701dc04f2400da1.png!small?1625380720029

图7

注意:GDTR和LDTR寄存器只有在内核模式下才能访问到,使用windbg进行内核调试即可看到。如图8所示。

1625380859_60e157fb70f72b4114f60.png!small?1625380859588

图8

每个系统必须定义一个GDT,该GDT可用于系统中的所有程序和任务。可选地,可以定义一个或多个LDT。例如,可以为正在运行的每个单独的任务定义一个LDT,或者某些或所有任务可以共享同一LDT。

GDT本身并不是一个段;相反,它是线性地址空间中的数据结构。 GDT的基础线性地址和limit必须装入GDTR寄存器。

GDT的基址应在8字节的边界上对齐,以产生最佳的处理器性能。

GDT的limit以字节表示。与段一样,将限制值添加到基址以获取最后一个有效字节的地址。limit值为0时,恰好是一个有效字节。由于段描述符的长度始终为8个字节,因此GDT限制应始终小于8的整数倍(即8N – 1)。

GDT中的第一个描述符未被处理器使用。该“空描述符”的段选择器在加载到数据段寄存器(DS,ES,FS或GS)中时不会生成异常,但在尝试执行时始终会生成通用保护异常(#GP)。使用描述符访问内存。通过使用该段选择器初始化段寄存器,可以确保对未使用的段寄存器的意外引用会产生异常。

LDT位于LDT类型的系统段中。 GDT必须包含LDT段的段描述符。如果系统支持多个LDT,则每个LDT必须在GDT中具有单独的段选择器和段描述符。 LDT的段描述符可以位于GDT中的任何位置。使用其段选择器访问LDT。为了在访问LDT时消除地址转换,LDT的段选择器,基本线性地址,限制和访问权限存储在LDTR寄存器中。

当GDTR寄存器存储了使用SGDT指令存储内容后,一个48位的“伪描述符”被存储在内存中,如图9。

1625381259_60e1598b96343a3c59a0e.png!small?1625381259435

图9


为了避免用户模式(权限级别3)下的对齐检查错误,伪描述符应位于奇数字地址(即,地址MOD 4等于2)。这导致处理器存储对齐的字,然后是对齐的双字。用户模式程序通常不存储伪描述符,但是通过以这种方式对齐伪描述符,可以避免产生对齐检查错误的可能性。当使用SIDT指令存储IDTR寄存器时,应使用相同的对齐方式。当存储LDTR或任务寄存器(分别使用SLDT或STR指令)时,伪描述符应位于双字地址(即地址MOD 4 等于0)。

使用描述符表寻址

先假设线性地址空间就是物理内存空间(即没有使用页),在这种情况下,访问线性地址空间就是访问物理内存。按照图10的方式,不管使用何种寻址方式都会进行如下的寻址。(请直接无视紫色的调用门的寻址)


1625381662_60e15b1e65534daf5abfd.png!small?1625381662495

图10

寻址方式抽象出来的模型如图11所示。通过这种模型,可以把逻辑地址转换为线性地址。要将逻辑地址转换为线性地址,处理器执行以下操作:

使用段选择器中的偏移量在GDT或LDT中找到该段的段描述符,并将其读入处理器。 (仅当将新的段选择器加载到段寄存器中时才需要执行此步骤。)

检查段描述符,以检查段的访问权限和范围,以确保该段可访问并且偏移量在该段的限制之内。

将段描述符的段基地址添加到偏移量中,以形成线性地址。如果不使用分页,则处理器会将线性地址直接映射到物理地址(即,线性地址在处理器的地址总线上消失)

1625382163_60e15d131a8a80f33fe0a.png!small?1625382162899

图11

在保护模式下的系统架构级别,处理器使用地址转换的两个阶段来获得物理地址:逻辑地址转换和线性地址空间分页。

处理器将每个逻辑地址转换为线性地址。 线性地址是处理器的线性地址空间中的32位地址。 与物理地址空间一样,线性地址空间是一个平坦的(未分段的)232字节地址空间,地址范围从0到FFFFFFFFH。 线性地址空间包含为系统定义的所有段和系统表。

@@@@@@欢迎大佬批评指正@@@@@@

下一篇:微处理器权限管理之——描述符表

# 汇编 # 内核 # 系统
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录