7- 代码段权限检查与 jmp

来源:互联网 发布:中科大计算机 知乎 编辑:程序博客网 时间:2024/06/10 07:56

概述

这一篇 hin 重要。

一般来说,我们在 Windows 中写的代码,都运行在 3 环(应用层)。只有在调用一些系统接口的时候,或者中断等情况的时候,才会进入 0 环(内核)。

为什么 CPU 要给代码赋予不同的权限?这是为了防止你任意妄为。在 Windows 中,如果你随意更改了内核的重要数据,操作系统必然面临着危险——蓝屏。

为了防止这种情况发生,CPU 把执行权限分成了4个等级,0,1,2,3. 其中 0 表示最高级,可以执行任意代码,而执行权限为 3 的程序,只能执行普通的指令。Windows 和 Linux 只使用了 0 和 3 这两种。

而 CPU 的有些指令,只能在 0 环执行。有些内存的访问,也只能在 0 环。这就是所谓的保护

之前已经学过,代码段描述符中,有 DPL 字段,它是专门用来描述代码段级别的。前面分析过 Windows 的GDT 表中段描述符,就发现有 0 环的代码段和 3 环代码段。这里的 DPL 表示,只允许相同级别的下的程序跳过来执行,除非被我同意,低特权级的程序才能跳进来执行。

所谓的特定级别下的程序,是指的当前 CPL 的级别。见后文。

CPU 是不允许 CPL = 3 的程序直接跳转到 DPL=0 的代码中去执行。

当前特权级

为了防止意外,有必要再次重复下 CPL。

这个值可以始终保存在 cs 或者 ss 段寄存器的低 2 位。在OD里打开一个程序,如果你细心观察,你总会发现,cs 的最低2位一定是2进制 11,也就是3. 你绝对不可能看到这个值变成 0. 因为 OD 本身就是运行在 3 环的调试器。

这是不是意味着,当前特权级永远不会变成 0?

不会的,后面的实验将验证这一点。

如果你想在 VC6.0 中写程序,直接去读取高 2G 地址的数据,一定会报错。如果你当前的特权级被提升为 0 环(简称提权),这时候再去读取高 2G 地址数据,就没有问题了。然而提权并不是这么简单。后文会陆续介绍。

跨段执行——就是改变 CS 段寄存器

跨段执行,就是指改变当前的 cs 段寄存器,把另一个代码段的描述符加载到 cs 段寄存器。千万不要想当然的使用 mov ax, 0x08; mov cs, ax,编译器都不会让你通过。前面你也发现,也不存在lcs这样的指令加载段寄存器。

改变 cs 段寄存器,可以使用 jmp farcall far 等等。注意,除了这两个指令,还有别的,这里不能讲太多。本篇只介绍 jmp,原因还是那样,因为它简单。

指令 jmp 可以实现跨段执行代码,但是它并不能提权(无法改变当权特权级),也就是说,即便你跨到了 DPL = 0 的段,你的 CPL 也不会发生任何改变。 除非你原来就是 0.

使用 jmp 跨到 0 环代码段,也是有要求的,除非这个0环代码段描述符同意(这就是所谓的一致代码段)。

一致代码段与非一致代码段

当段描述符描述代码段时,TYPE 字段的 c 位置 1 说明该段是一致代码段,否则是非一致代码段。

  • 只有得到段描述符的同意,才允许低权限的程序跳转进去执行。这种段称为一致代码段
  • 而有些代码段描述符,绝对不允许低权限的程序跳转进去执行,这种段称为非一致代码段

实现跨段:一致代码段(比当前权限高的)

要求:CPL >= DPL
步骤:

1.8003f048 处添加描述符 00cf9f00`0000ffff,该描述符描述的段为一致代码段,DPL = 0    命令 eq 8003f048 00cf9f00`0000ffff2.  打开 OD,修改当前指令为 jmp 48:0044420c3.  执行指令后跳转到了 0044420c 处,且 cs 变为 0x4b


这里写图片描述
图1 安装描述符
这里写图片描述
图2 跨段跳转

实现跨段:非一致代码段(与当前权限一致)

要求:CPL == DPL 并且 RPL <= DPL
步骤:

1.8003f048 处添加描述符 00cffb00`0000ffff,该描述符描述的段为非一致代码段,DPL = 3    命令 eq 8003f048 00cffb00`0000ffff2.  打开 OD,修改当前指令为 jmp 48:0044420c3.  执行指令后跳转到了 0044420c 处,且 cs 变为 0x4b


这里写图片描述
图3 安装段描述符
这里写图片描述
图4 跨段跳转

总结

使用 jmp 跨段,并不能改变当前特权级 CPL。后续文章将介绍其它方法,可以实现跨段并提权。另外,需要注意的是,只有一致代码段,才允许低特权级的程序跳转进去访问。

0 0
原创粉丝点击