12558网页游戏私服论坛

 找回密码
 立即注册
游戏开服表 申请开服
游戏名称 游戏描述 开服状态 游戏福利 运营商 游戏链接
攻城掠地-仿官 全新玩法,觉醒武将,觉醒技能 每周新区 经典复古版本,长久稳定 进入游戏
巅峰新版攻 攻城掠地公益服 攻城掠地SF 新兵种、新武将(兵种) 进入游戏
攻城掠地公 散人玩家的天堂 新开 进入游戏
改版攻城掠 上线即可国战PK 稳定新区 全新改版,功能强大 进入游戏
少年江山 高福利高爆率 刚开一秒 江湖水落潜蛟龙 进入游戏
太古封魔录 开服送10亿钻石 福利多多 不用充钱也可升级 进入游戏
神魔之道 签到送元宝 稳定开新区 送豪华签到奖励 进入游戏
神奇三国 统帅三军,招揽名将 免费玩新区 激情国战,征战四方 进入游戏
龙符 三日豪礼领到爽 天天开新区 助你征战无双 进入游戏
王者之师 免费领豪华奖励 免费玩新区 6元送6888元宝 进入游戏
查看: 375|回复: 0

3.段描述符(Segment Descriptor)

[复制链接]
发表于 2022-1-28 20:46:35 | 显示全部楼层 |阅读模式
章节介绍

  • 段寄存器基本概念
  • 段形貌符存储位置GDT(Global Descriptor Table)全局形貌符表,每个段形貌符大小为8字节.
  • GDTR寄存器结构,以及查找方式.
  • 段形貌符与段选择子关系(通过段选择子添补段结构(96BIT)).
  • 段形貌符常用属性探测(代码示例),不同段对应属性探测.
0.全局形貌符表GDT(Global Descriptor Table)

当我们执行类似MOV DS, AX指令时,CPU会查表,根据AX的值来决定查找GDT表还是LDT表,查找什么位置,查多少数据.
GDT(Global Descriptor Table)结构如下:
高4字节: GDT.Base
低2字节: GDT.Limit

intel白皮书介绍如下:
2.4.1 Global Descriptor Table Register (GDTR)
The GDTR register holds the base address (32 bits in protected mode; 64 bits in IA-32e mode) and the 16-bit table limit for the GDT. The base address specifies the linear address of byte 0 of the GDT; the table limit specifies the number of bytes in the table.
0.1 通过Windbg查找GDT表

r指令为查看寄存器
r gdtr指令为查看GDT.Base
r gdtl指令为查看GDT.Length
dq 有效所在 指令为查看内存数据8字节方式显示(xxxxxxxx(高4字节)`xxxxxxxx(低4字节))

0.2 通过代码查找

#include #include int main(){        char szBuf[6] = { 0 };        __asm        {                SGDT szBuf//高4字节存储GDT.Base 低2字节存储GDT.Limit        }        printf("GdtBase[0x%08x] GdtLength[0x%x] \r\n",*(LPDWORD)&szBuf[2],*(LPWORD)&szBuf[0]);        system("pause");        return 0;}1.段形貌符(Segment Descriptor)

GDT中存储段形貌符(数据段形貌符,代码段形貌符,系统段形貌符) 段形貌符大小为8个字节
intel白皮书介绍如下:
3.4.5 Segment Descriptors
A segment descriptor is a data structure in a GDT or LDT that provides the processor with the size and location of a segment, as well as access control and status information. Segment descriptors are typically created by compilers, linkers, loaders, or the operating system or executive, but not application programs. Figure 3-8 illustrates the general descriptor format for all types of segment descriptors.

2.段选择子与段形貌符关系


intel白皮书介绍如下:
A segment selector is a 16-bit identifier for a segment (see Figure 3-6). It does not point directly to the segment, but instead points to the segment descriptor that defines the segment. A segment selector contains the following items:
Index ( 段形貌符在GDT/LDT(windows并未使用LDT)表中的索引值 索引值 * 8 + GDTBase 为要加载的段形貌符 )(Bits 3 through 15) — Selects one of 8192 descriptors in the GDT or LDT. The processor multiplies the index value by 8 (the number of bytes in a segment descriptor) and adds the result to the base address of the GDT or LDT (from the GDTR or LDTR register, respectively).
Requested Privilege Level (RPL)( 哀求特权级别 用什么样的权限去哀求加载一个段形貌符 )(Bits 0 and 1) — Specifies the privilege level of the selector. The privilege level can range from 0 to 3, with 0 being the most privileged level.
TI (table indicator) flag( 0查GDT表 1查LDT表)(Bit 2) — Specifies the descriptor table to use: clearing this flag selects the GDT; setting this flagselects the current LDT.

2.1 通过段选择子查找对应段形貌符

当前测试环境 Win7 x86

CS: 0x001B 拆分为二进制为: 0000 0000 0001 1011
RPL: 3(哀求特权级别 用什么样的权限去哀求加载一个段形貌符)
TI: 0(0查GDT表 1查LDT表)
INDEX: 3(段形貌符在GDT/LDT(windows并未使用LDT)表中索引值) 索引值 * 8 + GETBase 为要加载的段形貌符
RPL = 3哀求特权级别为3(最低权限)只能加载DPL = 3的段形貌符(段权限检查介绍) TI = 0查找GDT表 INDEX = 3 通过windbg查看对应形貌符

得到段形貌符为: 00CFFB00 - 0000FFFF 对照段形貌符结构图得到如下值:
段形貌符属性文章后续具体分析
P: 1 (有效段形貌符)
DPL: 11(段形貌符特权级别3)
S: 1 (数据或代码段形貌符)
TYPE: 1011 (代码段 非一致代码段 可读 可执行 已被访问(加载))
G: 1 (粒度为PAGE)
D/B: 1 (CS段影响为采用32位寻址方式)
AVL: 0
BASE: 00000000
LIMIT: FFFFFFFFh (通过段形貌符结构显式Limit为FFFFFh) G = 1粒度为(PAGE) (0xFFFFF + 1) * 4KB - 1 0xFFFFFFFF
此时段寄存器结构为:
struct Segment{    WORD Selector;  //16位可见部分段选择子      WORD Attribute; //16位隐蔽部分段属性    段形貌符高4字节23:08       DWORD Base;     //32位隐蔽部分段基址    段形貌符高4字节31:24->Base31:24  7:0->Base23:16  段形貌符低4字节31:16->Base15:00       DWORD Limit;    //32位隐蔽部分段线长    段形貌符高4字节19:16->Limit19:16 段形貌符低4字节15:00->Limit15:00}; 3.段形貌符属性探测

通过windbg在GDT表中查找一个空缺位置通过eq指令(修改8字节数据)插入本身构建的段形貌符
3.1 P位

P == 1 段形貌符有效
P == 0 段形貌符无效
P (segment-present) flag -Indicates whether the segment is present in memory (set) or not present (clear). If this flag is clear, the processor generates a segment-not-present exception (#NP) when a segment selector that points to the segment descriptor is loaded into a segment register. Memory management software can use this flag to control which segments are actually loaded into physical memory at a given time. It offers a control in addition to paging for managing virtual memory.
//测试P位                                   #include #include int main(){        //00cff300`0000ffff (从0开始计数高4字节)16进制位第3位>=8为有效段形貌符 2进制位第15位=1为有效段形貌符        WORD Segment = 0;        DWORD dwData = 0;        //P位        __asm        {                mov Segment, ss                //0023                //0000 0000 0010 0011                //00cff300`0000ffff                //P == 1 DPL == 3 S == 1 TYPE == 0011                mov eax, ss:[esp + 8]                mov dwData, eax        }        printf("SS:[0x%04x] DATA:[0x%08x]  \n",Segment,dwData);        __asm        {                //构建段形貌符                //00cf7300`0000ffff                //P == 0                //windbg input eq 80b99048 00cf7300`0000ffff                mov ax, 0x4B                mov ss, ax//加载失败段形貌符无效                mov eax, ss:[esp]        }        system("Pause");        return 0;} 3.2 G位

假设显式Limit为0xFFFFF环境下:
G == 0 粒度为(BYTE) (0xFFFFF + 1) * 1 - 1 0x000FFFFF(Limit最终大小)
G == 1 粒度为(PAGE) (0xFFFFF + 1) * 4KB - 1 0xFFFFFFFF(Limit最终大小)
G (granularity) flag - Determines the scaling of the segment limit field. When the granularity flag is clear, the segment limit is interpreted in byte units; when flag is set, the segment limit is interpreted in 4-KByte units.(This flag does not affect the granularity of the base address; it is always byte granular.) When the granularity flag is set, the twelve least significant bits of an offset are not tested when checking the offset against the segment limit. For example, when the granularity flag is set, a limit of 0 results in valid offsets from 0 to 4095.
//测试G位#include #include int main(){        //00cff300`0000ffff (从0开始计数高4字节)16进制位第5位>=8为G = 1 2进制位第23位= 1 G = 1        WORD Segment = 0;        DWORD dwData = 0;        //G位        __asm        {                mov Segment, ds                //0023                //0000 0000 0010 0011                //00cff300`0000ffff                //G == 1 Limit == 0xFFFFFFFF BASE == 0x00000000                mov eax, ds:[0x400000]                mov dwData, eax        }        printf("SS:[0x%04x] DATA:[0x%08x]  \n",Segment,dwData);        __asm        {                //构建段形貌符                //004ff300`0000ffff                //G == 0 Limit = 0xFFFFF BASE == 0x00000000                //windbg input eq 80b99048 004ff300`0000ffff                mov ax, 0x4B                mov ds, ax                mov eax, ds:[0x400000]//错误超出段线长        }        system("Pause");        return 0;}  3.3 S位

S == 0 系统段形貌符
S == 1 代码段或数据段形貌符
S (descriptor type) flag - Specifies whether the segment descriptor is for a system segment (S flag is clear) or a code or data segment (S flag is set).
通过windbg中断后查看段寄存器值:

CS:0008h 转换二进制为:0000 0000 0000 1000
RPL:0
TI:0
INDEX:1
段形貌符:00CF9(1001)B00 - 0000FFFF 代码段S = 1
FS:0030h 转换二进制为:0000 0000 0011 0000
RPL:0
TI:0
INDEX:6
段形貌符:83409(1001)3F6 - CC003748 数据段 S = 1
TR:0028h 转换二进制为:0000 0000 0010 1000
RPL:0
TI:0
INDEX:5
段形貌符:80008(1000)B1E - 400020AB 任务段S = 0

3.4 TYPE域

Type field -Indicates the segment or gate type and specifies the kinds of access that can be made to the segment and the direction of growth. The interpretation of this field depends on whether the
descriptor type flag specifies an application (code or data) descriptor or a system descriptor.
S位 = 1环境下 TYPE域如下图:

3.4.1 数据段测试

S == 1 TYPE < 8 数据段(默认可读)
E = 扩展方向
E == 0 向上扩展 可访问Base ~ Base + Limit
E == 1 向下扩展 可访问线长取决于DB
DB == 1 有效的所在范围Base + Limit + 1 ~ Base + Limit + 0xFFFFFFFF 4GB
DB == 0 有效的所在范围Base + Limit + 1 ~ Base + Limit + 0xFFFFH 64K
W = 是否可写
A = 访问 (表示该位最后一次被操作系统清零后,该段是否被访问过.每当处置处罚器将该段选择符置入某个段寄存器时,就将该位置1)
#include #include int main(){        WORD Segment = 0;        DWORD dwData = 0;        //TYPE          __asm        {                //构建段形貌符                //windbg input eq 80b99048 00cff100`0000ffff                //P == 1                //DPL == 11                //S == 1                //TYPE == 0001 不可写                //mov ax, 0x4B                //mov ds, ax                //mov eax, ds:[esp + 8]       //可读                //mov ds:[esp + 8], 0x12345678//不可写        }        __asm        {                //构建段形貌符                //windbg input eq 80b99048 00cff700`0000ffff                //P == 1                //DPL == 11                //S == 1                //TYPE  == 0111 可读 可写 访问 向下扩展                //BASE  == 0x00000000                //Limit == 0xFFFFFFFF                 //mov ax, 0x4B                //mov ds, ax                //mov eax, ds:[esp + 8]//访问失败        }        __asm        {                //构建段形貌符                //windbg input eq 80b99048 0040f740`0000000F                //P == 1                //DPL == 11                //S == 1                //G     == 0                //TYPE  == 0111 可读 可写 访问 向下扩展                //BASE  == 0x00400000                //Limit == 0x0000000F                //mov ax, 0x4B                //mov ds, ax                //mov eax, ds:[0x10]//[0x400000 + 0x10]                //mov eax, ds:[0xC] //访问失败        }        system("Pause");        return 0;}3.4.2 代码段测试

S == 1 TYPE > 7 代码段(默认可执行)
C = 一致位
C == 0 非一致代码段 (跨段跳转同级权限)
C == 1 一致代码段 (跨段跳转不同权限)
R = 可读
A = 访问 (表示该位最后一次被操作系统清零后,该段是否被访问过.每当处置处罚器将该段选择符置入某个段寄存器时,就将该位置1)
#include #include _declspec(naked) VOID CodeSegmentAttribute(){  __asm  {      //构建段形貌符    //windbg input eq 80b99048 00cff900`0000ffff    //TYPE == 1001 可执行 访问 不可读    //访问失败    //mov eax, cs:[esp]    //构建段形貌符    //windbg input eq 80b99048 00cffb00`0000ffff    //TYPE == 1011 可执行 访问 可读 非一致代码段    //CPL == 3    //DPL == 3    //跳转成功    //构建段形貌符    //windbg input eq 80b99048 00cf9b00`0000ffff    //TYPE == 1011 可执行 访问 可读 非一致代码段    //CPL == 3    //DPL == 0    //跳转失败    //构建段形貌符    //windbg input eq 80b99048 00cf9f00`0000ffff    //TYPE == 1111 可执行 访问 可读 一致代码段    //CPL == 3    //DPL == 0    //跳转成功但CPL仍是3    retf  }}int main(){        WORD Segment = 0;        DWORD dwData = 0;        CHAR calldata[6] = {0};        *(LPWORD)&calldata[4] = 0x4B;        *(LPDWORD)&calldata[0] = (DWORD)CodeSegmentAttribute;        __asm        {                call fword ptr [calldata]        }        system("Pause");        return 0;}   S位 = 0环境下 TYPE域如下图:

S == 0
TYPE: 0001 == 1 16位任务段(空闲)
TYPE: 0011 == 3 16位任务段(占用)
TYPE: 0100 == 4 16位调用门
TYPE: 0101 == 5 任务门 (任务门详解)
TYPE: 0110 == 6 16位中断门
TYPE: 0111 == 7 16位陷阱门
TYPE: 1001 == 9 32位任务段(空闲) (任务段详解)
TYPE: 1011 == B 32位任务段(占用)
TYPE: 1100 == C 32位调用门 (调用门详解)
TYPE: 1110 == E 32位中断门 (中断门详解)
TYPE: 1111 == F 32位陷阱门 (陷阱门详解)
3.5 DB位

3.5.1 CS段的影响

D = 1 采用32位寻址方式
D = 0 采用16位寻址方式
前缀67 改变寻址方式
#include #include _declspec(naked) VOID CodeSegmentAttribute(){        __asm        {                  //构建段形貌符                //00cffb00`0000ffff                //DB == 1 32BIT                mov eax, [esp]//0040f021                                        retf        }}int main(){        WORD Segment = 0;        DWORD dwData = 0;        CHAR calldata[6] = {0};        *(LPWORD)&calldata[4] = 0x4B;        *(LPDWORD)&calldata[0] = (DWORD)CodeSegmentAttribute;        __asm        {                //构建段形貌符                //windbg input eq 80b99048 008ffb00`0000ffff                //DB == 0 16BIT                  //CALL执行错误                call fword ptr [calldata]        }        system("Pause");        return 0;}  3.5.2 SS段的影响

D = 1 隐式堆栈访问指令(如:PUSH POP CALL) 使用32位堆栈指针寄存器ESP
D = 0 隐式堆栈访问指令(如:PUSH POP CALL) 使用16位堆栈指针寄存器SP
#include #include int main(){  //构建段形貌符  //windbg input eq 80b99048 00cff300`0000ffff  //DB == 1  __asm  {    mov ax, 0x4B    mov ss, ax    mov eax, esp//12FEFC    PUSH 1    PUSH 2    mov eax, esp//12FEF4    add esp, 0x8  }  //构建段形貌符  //windbg input eq 80b99048 008ff300`0000ffff  //DB == 0  __asm  {    mov ax, 0x4B    mov ss, ax    mov eax, esp    PUSH 1    PUSH 2    mov eax, esp  }  system("Pause");  return 0;} 3.5.3 向下扩展数据段

D = 1 段上线为4GB
D = 0 段上线为64KB
#include #include int main(){  //构建段形貌符  //windbg input eq 80b99048 0000f740`00000000  //DB == 0  //G  == 0  //TYPE == 0111  //BASE == 0x00400000  //Limit == 0  __asm  {    //mov eax, ds:[0x400001]//0300905a    //mov eax, ds:[0x410000]//cccccccc    //mov ax, 0x4b    //mov ds, ax        //mov eax, ds:[0x1]                //0300905a  da.Base(0x400000) + 1 = 0x400001    //mov eax, ds:[0x10000] //error段线长为64KB  }  //构建段形貌符  //windbg input eq 80b99048 0040f740`00000000  //DB == 1  //G  == 0  //TYPE == 0111  //BASE == 0x00400000  //Limit == 0  __asm  {    mov ax, 0x4b    mov ds, ax    mov eax, ds:[0x1]    mov eax, ds:[0x10000]  }  return 0;}
来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
楼主热帖
回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|12558网页游戏私服论坛 |网站地图

GMT+8, 2024-4-26 07:37 , Processed in 0.125000 second(s), 31 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表