首页
社区
课程
招聘
[原创]Windows 7中的段和门
发表于: 2011-8-21 22:20 14389

[原创]Windows 7中的段和门

2011-8-21 22:20
14389
收藏
免费 6
支持
分享
最新回复 (16)
雪    币: 27
活跃值: (127)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
2
学习一下..
2011-8-22 01:23
0
雪    币: 113
活跃值: (100)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
想到一些东西,和大家分享。在网上看到保护模式的文章中看到这么一句话:只有用CALL指令+调用门方式跳转,且目标代码段是非一致代码段时,才会引起CPL的变化,即引起代码执行特权级的跃迁,这是目前得知的改变执行特权级的唯一办法。(http://user.qzone.qq.com/31731705/blog/1313393846)

当时看到这句话的时候很困惑,那么中断门,陷阱门呢?.sysenter呢?这些不都是从用户态到内核态的跳转。CPL都是从3变成了0啊。上面这句话有很大的局限性。
2011-8-25 10:23
0
雪    币: 242
活跃值: (473)
能力值: ( LV11,RANK:188 )
在线值:
发帖
回帖
粉丝
4
支持,学习
保护模式中,已经不再需要让各个节(如.text,.data)和保护模式的段对应了

int 2e或者.sysenter一条指令,
做的事情就是修改代码段CS的值为一个GDT中合适的R0执行权限的值,SS段寄存器,这时也会被修改成合CS一样的值。EIP也修改成为要执行的被操作系统指定的调度接下来怎么执行的代码。同时ESP也会被修改成为新的ESP,也就是R0的ESP,就当systen它做一个特殊用途中断,操作系统的R0代码就当是在异常处理里面执行的,win98时就可以这样进入R0的。当然,还是要一般而言下,sysenter修改之后,代码段CS包含的新的段描述的DPL位的值是0的。
那个陷阱和中断的,我自己的机子上是对劲的,vmware里的XP SP3
kd> !idt 0;!idt 1;!idt 3;
Dumping IDT:
00:        8053f19c nt!KiTrap00
Dumping IDT:
01:        8053f314 nt!KiTrap01
Dumping IDT:
03:        8053f6e4 nt!KiTrap03

kd> !pcr
KPCR for Processor 0 at ffdff000:
    Major 1 Minor 1
        NtTib.ExceptionList: 8054a4b0
            NtTib.StackBase: 8054acf0
           NtTib.StackLimit: 80547f00
         NtTib.SubSystemTib: 00000000
              NtTib.Version: 00000000
          NtTib.UserPointer: 00000000
              NtTib.SelfTib: 00000000

                    SelfPcr: ffdff000
                       Prcb: ffdff120
                       Irql: 00000000
                        IRR: 00000000
                        IDR: ffffffff
              InterruptMode: 00000000
                        IDT: 8003f400
                        GDT: 8003f000
                        TSS: 80042000

kd> dyd 8003f400
           3          2          1          0
          10987654 32109876 54321098 76543210
          -------- -------- -------- --------
8003f400  00000000 00001000 11110001 10011100  0008f19c
8003f404  10000000 01010011 1000|1110| 00000000  80538e00
8003f408  00000000 00001000 11110011 00010100  0008f314
8003f40c  10000000 01010011 1000|1110| 00000000  80538e00
8003f410  00000000 01011000 00010001 00111110  0058113e
8003f414  00000000 00000000 1000|0101| 00000000  00008500
8003f418  00000000 00001000 11110110 11100100  0008f6e4
8003f41c  10000000 01010011 1110|1110| 00000000  8053ee00
除了第三个是?101的中断类型的元素的。其他的都是1110的trap元素

上面那句话是错的,只要能够修改CS段寄存器的指令,都会影响的。因为现在所用的DPL就保存在段寄存器中啊。CS决定代码的执行权限,是因为执行代码时,默认所用的是cs作为段寄存器的,也就说,有可能ES段中保存一个R0的段描述符,然后你就可以通过ES:0x80004000来访问内核的地址,而正常的访问还是DS段寄存器,不能访问到内核的范围 :P 当然那样有点无厘头。
2011-8-28 01:34
0
雪    币: 220
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
恩 受教了 不错
2011-8-28 01:38
0
雪    币: 113
活跃值: (100)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
不明白的就是PE加载之后,各个节之间会被load到内存中,然后应用段的属性,当然不是代码段就是数据段,能不能修改这个过程,比如把.data节的段属性变成dpl=0的,,这个过程具体是怎么样的?hehe,想的有些多了。

另外:虽然函数名KiTrap**,
0101是task gate.
1110是interrupt gate.
2011-8-28 21:41
0
雪    币: 437
活跃值: (110)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
7
来学习了。
2011-8-29 08:08
0
雪    币: 113
活跃值: (100)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
我的调试日志在我的空间里,http://user.qzone.qq.com/31731705/blog/
2011-8-29 13:17
0
雪    币: 693
活跃值: (108)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
9
你们都想多了,数据段等的特权级即ds、es等寄存器是不会变的,他们还是R3,因为进入R0,CS中的CPL就是最高级别,他可以访问一切特权级的代码和数据包括R3的,数据访问的保护主要比较CPL与数据段的DPL。例如在内核空间ds指向一个R3级别的数据段描述符,只要该数据段的段长为4G,即可用ES:[80008000h]一类的了,因为此时的CPL已经是0。
其实在R3空间中,cs和es都指向的是r3的段,那么用ES:[80008000h]在段保护一级上也可以通过,因为是CPL为3来访问DPL为3的数据段。但是之所以会失败是因为页保护,内核的页面有U/S位的限制,限制了只有CPL为0的权限才能访问。所以是只有通过了段保护和页保护才能成功。
所以也不需要更改ds、es等寄存器了。
至于楼主说的更改DPL为0,也不是办不到只需在GDT找到DPL为0的段的索引,用mov ax,***    mov ds,ax即可,只不过需要写个patch来修改PE加载器。但是这样程序就完蛋了,因为在R3中执行时,你要求CPL为3来访问DPL为0的段,肯定是通不过的。
2011-8-31 10:27
0
雪    币: 100
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
受教了,谢谢楼主
2011-8-31 11:05
0
雪    币: 113
活跃值: (100)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
11
CS中的CPL就是最高级别,他可以访问一切特权级的代码和数据包括R3的

我觉得CPL=0的代码段访问DPL=3的数据段没有问题,但CPL=0的代码段应该是不能访问DPL=3的代码段的。

另外,ds,es在进入Ring0后是会变的,只不过数值还是0x23,和用户态下的一样。KiTrap**大多是这么实现的。不知道为什么有这样的代码,可能为变化作准备。

[QUOTE=zyqqyz;996068]你们都想多了,数据段等的特权级即ds、es等寄存器是不会变的,他们还是R3,因为进入R0,CS中的CPL就是最高级别,他可以访问一切特权级的代码和数据包括R3的,数据访问的保护主要比较CPL与数据段的DPL。例如在内核空间ds指向一个R3级别的数据段描述符,只要该数据段的段长为4G,即可用ES:[8...[/QUOTE]

这段话给了我些启发,只要段是4G的,不管DPL=0还是DPL=3,80008000这个线性地址都是唯一的,因为是段页式内存管理,所以相应的存在双重保护,既要检查段的安全属性,也会检查页的安全属性。
2011-8-31 14:29
0
雪    币: 693
活跃值: (108)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
12
请牢记,在flat模式下内存中是没有数据段代码段之分的,通过段寄存器查GDT表得到的段基本上都是4g的平坦地址,至于你说R0代码段访问R3代码段这个说法本身就不准确。你可能说的是在R0中执行R3空间的代码吧,这个是没有问题的,而且有些内核漏洞的利用就是这样的。通过在R3地址下写入一些shellcode,然后利用内核漏洞以R0的模式执行R3的代码完成对IDT,SSDT,GDT等关键数据的修改。因为在R0模式下是可以执行一切的代码访问一切数据的除了cr寄存器中的写保护除外。另外既然ds,es的数值没变,GDT没变,那么它们所代表的段及属性能变吗?建议楼主看一些linux、windows源码的相关资料,再加强一下对IA-32手册第三卷的阅读。
2011-8-31 16:50
0
雪    币: 113
活跃值: (100)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
13
你的说法很给力啊,我还是头一次听到。内存中没有数据段代码段之分。,你的意思应该是指代码段和数据段是混在一起的,共享一个4G的地址空间吧。

另外,JMP指令还是CALL指令,代码段之间切换时的要求都是当前代码段的CPL=目标代码段的DPL,只有通过门时可以用CPL>=DPL。不知道你说的代码段之间的跳转是通过什么样的跳转方式,允许当前代码段的CPL<目标代码段的DPL?
2011-8-31 18:55
0
雪    币: 113
活跃值: (100)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
14
又想起了另一个例子,用户模式下CS段的DPL=3,但也是4G空间,(和内核模式下的CS段是共享地址空间的),因此代码是可能直接访问80000000以上的地址处的代码的,如直接使用JMP或者CAll一个内核的API,不能访问的原因不是因为DPL通不过,而应该也是U/S标志位的限制。
2011-8-31 22:16
0
雪    币: 693
活跃值: (108)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
15
你的思维囿于了8086的段模式,冯诺依曼结构的数据与代码本来就是不区分的,否则缓冲区溢出就很难了,intel也就不搞什么DEP了;哈佛结构类似于51单片机才有数据代码的区分。
至于你说的R0访问R3,当然从CPL为0的远跳到DPL为3的肯定办不到。但是为什么要跳呢,在R0下除了FS,其余的段寄存器都是4g的属性,直接用CPL为0的cs访问不就行了。在flat模式下一定要忘记段的概念,因为windows这样设计就是为了简化段的作用的。
2011-9-1 10:13
0
雪    币: 57
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
mark......学习.....
2012-1-16 17:17
0
雪    币: 113
活跃值: (100)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
17
第2篇在这里:Win7下的段和门 (2)

最近看了下手册

从R3到R0,DS,ES可以使用DPL=3的,SS必须使用新的。

Before the processor loads a segment selector into a segment register, it performs a privilege check by comparing the privilege levels of the currently running program or task (the CPL), the RPL of the segment selector, and the DPL of the segment’s segment descriptor. The processor loads the segment selector into the segment register if the DPL is numerically greater than or equal to both the CPL and the RPL. Otherwise, a general-protection fault is generated and the segment register is not loaded.

CPL=0的代码段可以加载DPL=3的数据段,

PRIVILEGE LEVEL CHECKING WHEN LOADING THE SS REGISTER
Privilege level checking also occurs when the SS register is loaded with the segment selector for a stack segment. Here all privilege levels related to the stack segment must match the CPL; that is, the CPL, the RPL of the stack-segment selector, and the DPL of the stack-segment descriptor must be the same. If the RPL and DPL are not equal to the CPL, a general-protection exception (#GP) is generated.

CPL=0的代码段只能加载DPL=0的栈段。

关于CPL,RPL和DPL参考:保护模式下的保护
2012-5-13 13:17
0
游客
登录 | 注册 方可回帖
返回
//