zoukankan      html  css  js  c++  java
  • 段间跳转之TSS段

    TR寄存器,TSS描述符,TSS段

    TR寄存器与普通的段寄存器一样都有可见部分和不可见部分。TR的可见部分为16位为其段选择子,不可见部分是32位的TSS基地址和16位的大小。

    TSS描述符存在GDT表中,注意其G位为0,所以TSS段的大小Limit的单位为字节,TYPE位为10B1(B为忙碌标志)。cpu利用TSS描述符来填充TR寄存器不可见部分。

    TSS段是一个104个字节的内存,是Inter用来提供实现任务切换的,但是windows和linux都没有使用。TR寄存器隐藏部分的基地址就是TSS段的基地址。TSS可以保存一堆寄存器实现一次替换所有寄存器。Previous Task Link用来保存旧的段选择子,iretd指令利用此字段返回。

    读写TR寄存器

    Ring 0

    ldt指令是一个特权指令,其能够为TR寄存器的可见部分提供一个值。
    sdt指令是一个不同指令,其能够从TR寄存器中读取可见部分的值。

    Ring 3

    在应用层只能通过jmp far和call far指令更改TR寄存器,读TR寄存器与在0环相同都是通过SDT指令。

    利用jmp far更改TR寄存器

    构造一个TSS段描述符,0000E95D`00000068,即TSS段的基地址为0x005D0000,长度为0x68(104)个字节。

    我们构造TSS段,给各个字段赋值。其中我们让cs为8,cpl为0是为了提权。

    TSS[0] = 0x00000000; // Previous Task Link
    TSS[1] = 0x00000000; // ESP0
    TSS[2] = 0x00000000; // SS0
    TSS[3] = 0x00000000; // ESP1
    TSS[4] = 0x00000000; // SS1
    TSS[5] = 0x00000000; // ESP2
    TSS[6] = 0x00000000; // SS2
    TSS[7] = dwCr3;      // CR3
    TSS[8] = (DWORD)TestPorc; // EIP
    TSS[9] = 0x00000000; // EFLAGS
    TSS[10] = 0x00000000; // EAX
    TSS[11] = 0x00000000; // ECX
    TSS[12] = 0x00000000; // EDX
    TSS[13] = 0x00000000; // EBX
    TSS[14] = (DWORD)esp; // ESP
    TSS[15] = 0x00000000; // EBP
    TSS[16] = 0x00000000; // ESI
    TSS[17] = 0x00000000; // EDI
    TSS[18] = 0x00000023; // ES
    TSS[19] = 0x00000008; // CS 0x0000001B
    TSS[20] = 0x00000010; // SS 0x00000023
    TSS[21] = 0x00000023; // DS
    TSS[22] = 0x00000030; // FS 0x0000003B
    TSS[23] = 0x00000000; // GS
    TSS[24] = 0x00000000; // LDT Segment Selector
    TSS[25] = 0x20ac0000; // I/O Map Base Address
    

    执行jmp far 0x48:0x00000000,执行后我们发现代码跳转到了TestPorc地址处。EFLAGS的NT位被置位0,所以jmp far的TSS切换不能利用iret指令返回,如果要返回应该利用指令jmp far旧的TSS段选择子返回。

    而且jmp far不会将旧的TSS段选择子保存在TSS段的Previous Task Link中,如果我们需要返回应该在跳转前保存旧的TSS段选择子,然后在利用jmp far指令返回。

    注意其CPU在切换任务时,会将现在的TSS段描述符的TYPE的B忙位置1。

    利用call far更改TR寄存器

    构造一个TSS段描述符,0000E93F`00000068,即TSS段的基地址为0x003F0000,长度为0x68(104)个字节。

    我们构造和jmp far一样的TSS段,给各个字段赋值。执行jmp far 0x48:0x00000000,执行后我们发现代码跳转到了TestPorc地址处。EFLAGS的NT位被置为1,所以call far的TSS切换能利用iret指令返回,其返回利用保存在TSS段中的
    Previous Task Link保存的旧的TSS段选择子。

    我们查看其TSS段,发现Previous Task Link的值为0x28,所以旧的TSS段选择子为0x28。

    我们查看堆栈,发现call far 更改TR寄存器并不会更改堆栈的内容。

    同样其也会将现在的TSS段描述符的TYPE的忙位B置1。

    疑问

    当jmp far 和 call far改变TR寄存器时我们使用的段选择子的RPL都为0,当RPL为3时会出错。
    当jmp far 和 call far改变TR寄存器时我们的TSS段的cs的CPL为3会出错。

  • 相关阅读:
    Who Gets the Most Candies? POJ
    Chrome DevTools谷歌浏览器开发者工具评估资源加载时间
    Array.isArray (Array) – JavaScript 中文开发手册
    CSS3 @keyframes 规则
    inherit (Values & Units) – CSS 中文开发手册
    CSS #id 选择器
    isgraph (Strings) – C 中文开发手册
    PHP juliantojd() 函数
    Navigator javaEnabled() 方法
    ionic checkbox
  • 原文地址:https://www.cnblogs.com/revercc/p/14468330.html
Copyright © 2011-2022 走看看