为了深入了解微处理器的内部的权限管理模式,则需要先了解段寄存器的完整结构。后续根据intel发布的手册为主结合其他资料来说明微处理器内部权限管理的模式。
预备知识点
权限等级
处理器的段保护机制可以识别4个权限级别,编号从0到3。数字越大,权限就越小。 下图显示了如何将这些权限级别解释为保护环(ring)。
中心,即level0,保留用于权限最高的代码,数据和栈。包含关键软件(通常是操作系统内核)的段。
外圈,即level3,用于不太重要的软件。
处理器使用权限级别来防止以较低权限级别运行的程序或任务访问具有较高权限的段,除非在受控情况下。 当处理器检测到权限级别违规时,它将生成一般保护异常(#GP)。
段描述符
段描述符是GDT或LDT中的数据结构,可为处理器提供段的大小和位置以及访问控制和状态信息。 段描述符通常是由编译器,链接器,加载器或操作系统或执行程序创建的,而不是由应用程序创建的。
后续对段描述符进行详细的描述。
调试工具和方法
为了查看平常不可见的寄存器或内存,强力推荐使用windbg神器。现在微软又推出了windbg的升级版WinDbg Preview。可以在应用市场上下载,颜控的人员强烈推荐使用WinDbg Preview。使用起来的感觉比windbg舒服,巴适的很!!!
有些寄存器只有在内核模式下才能看到。下面说明一下如何使用windbg进行内核调试。windbg虽然能进行本地内核调试,但是在多个win平台测试,发现工具会出现各种奇葩的灵异问题,而且有些windbg命令不支持本地内核调试,所以还是推荐使用2台主机通过网络的形式进行内核调试。
windbg支持3种调试模式:
1、ethernet
2、usb2.0/user3.0
3、serial(也称为null modem)
为了调试的速度和可靠性,推荐第一种方式。在两台虚拟机环境下这种方式最方便。使用ethernet方式时运行调试器的主机被称为主机电脑(host computer),被调试的电脑成为目标电脑(target computer)。主机电脑必须是win7或更高版本,目标电脑必须是win8或更高版本。
主机电脑可以使用任何网络适配器,但目标电脑必须使用 Windows 调试工具支持的网络适配器。 有关支持的网络适配器的列表,请参阅win10相关,win8.1相关。
安装调试工具
从Windows 10 SDK页面下载sdk包,然后安装windbg。
调试配置
1、获取主机电脑的ip地址。
2、在目标主机上执行ping -4 ,确保网络畅通。
3、选择网络调试端口。可以选择49152-65535之间的端口,官方推荐50000 – 50039之间的端口。
4、配置目标电脑。
⚠️在使用 BCDEdit 更改启动信息之前,您可能需要在测试 PC 上暂时暂停 Windows 安全功能,例如 BitLocker 和安全启动。 测试完成后重新启用这些安全功能,并在禁用安全功能时适当管理测试 PC。使用管理员权限运行下面的命令
bcdedit /debug on
bcdedit /dbgsettings net hostip:172.16.217.23 port:50000
执行完毕后bcdedit会生成一个密钥,该密钥需要在主机电脑上使用。
使用设备管理器确定要用于调试的适配器的 PCI 总线、设备和功能编号。 这些值显示在“设备管理器”中“常规”选项卡上的“位置”下。使用
bcdedit /set "{dbgsettings}" busparams b.d.f
命令时,b/d/f 分别表示bus number,device number, 适配器的function number :
5、在主机电脑上配置调试会话。可以通过图形界面或命令行的方式来配置。
图形界面:
命令行:
windbg -k net:port=<n>,key=<MyKey>
6、重启目标电脑。shutdown -r -t 0。重启期间,在主机电脑上会看到如下信息
然后点击中断
然后就能看到中断信息
然后就可以调试了。
例如下图所示,可以看到GDTR寄存器,该寄存器存储了全局描述符表的基址。
段寄存器可见部分
如上图所示,这就是日常的调试和逆向中我们看到的段寄存器内容。这部分内容是用户可见的部分。微处理器通过段选择器和偏移地址来寻址。
完整的段寄存器
每个段寄存器都有一个“可见”部分和一个“隐藏”部分。(隐藏部分有时称为“描述符缓存/“descriptor cache”或“影子寄存器/shadow register”。) 当将段选择器加载到段寄存器的可见部分时,处理器还将从段选择器指向的段描述符中加载基址,段限制和访问控制信息,从而将段寄存器的隐藏部分加载。 存储在段寄存器中的信息(可见和隐藏)允许处理器转换地址,而无需花费额外的总线周期从段描述符读取基地址和限制。 在多个处理器可以访问相同描述符表的系统中,修改描述符表后,软件有责任重新加载段寄存器。 如果不这样做,则在修改其内存驻留版本后,可能会使用缓存在段寄存器中的旧段描述符。
如上图所示,完整的段寄存器可以认为是由2部分组成,分别是可见部分的段选择器(segment selector)和隐藏部分(存储了基址、limit,访问信息)。可见部分的16bit由3部分组成。在index和TI部分用来寻址,RPL部分用来做权限校验。
由于CS和SS段寄存器涉及到程序(可能是程序,可能是任务,暂时统称为程序。)内部和程序之间的调用跳转,在调用或跳转时会进行各类校验,其中包含权限校验。所以CS和SS段寄存器隐藏部分的2bit包含了CPL信息用来做权限校验。
为了使程序访问段,段的段选择器必须已加载到段寄存器之一中。 因此,尽管系统可以定义数千个段,但只有6个段可立即使用。 通过在程序执行期间将其他段的选择器加载到这些寄存器中,可以使其他段可用。
段寄存器加载方式
方法1:直接加载指令。例如MOV,POP,LDS,LES,LSS,LGS和LFS指令。 这些指令明确引用了段寄存器。
方法2:隐含的加载指令。例如CALL,JMP和RET指令的远指针版本,SYSENTER和SYSEXIT指令以及IRET,INT n,INTO,INT3和INT1指令。 这些指令将CS寄存器(有时是其他段寄存器)的内容作为其操作的附带部分进行更改。
段选择器详解
段选择器是段的16bit标识符如下图所示。 段选择器不直接指向段,而是指向定义段的段描述符。
段选择器包含以下各项:
index:描述符索引。 处理器将索引值乘以8(段描述符中的字节数),并将结果加到描述符表寄存器存储的基地址上。
TI: 指定要使用的描述符表。如果清除此标志将选择GDT(全局描述符表);否者设置该标志将选择当前的LDT(局部描述符表)。
RPL: 指定选择器的权限级别。
段选择器作为指针变量的一部分对应用程序可见,但是选择器的值通常是由链接编辑器或链接加载程序(而不是应用程序)分配或修改的。
本篇完。下一篇:
微处理器权限管理之——描述符表
来源:freebuf.com 2021-06-26 22:54:59 by: lhkhk
请登录后发表评论
注册