当我们用汇编读写某一个地址的时候:
Mov dword ptr ds:[0x123456],eax
真正写的地址是 ds.base+0x123456
ES CS SS DS FS GS LATR TR 8个
Base Limit atrribute select
这个代码是没有任何问题的 因为ss可写ds也可写 eax完全可以赋值到var里面
改成cs就崩溃了 cs并没有可写属性
首先fs赋值gs 读取gs:[0]的位置 正常来说0的位置是不可写的 但是此时的gs是fs而fs的base并不是0 如上图 此时gs:[0]的位置是0x7ffde000
读取gs0x1000的地方也就相当于读取fs:0x1000的地方 但是 fs大小为0xfff随意程序崩溃
写段寄存器的时候,只给了16位,剩下80位给什么???16位的数可以随便写吗???
当我们执行类似mov ds,ax指令时,CPU会查表,根据AX的值来决定查找哪一个表,查找表的什么位置,查多少数据
Gdtr是48位 32位存储了GDT表在哪里16位存储了大小
查看gdt表
也就是说 gdt是一张表里面的元素叫段描述符 大小为64位8个字节
段描述符的结构
P位:0 - 无效段 、 1 - 有效段。(查看该段是否有效,最直接的就是查看该位)
G位: G=0表示界限粒度(单位)为1字节,Limit最大值为0x000FFFFF(1MB)
G=1表示界限粒度(单位)为4K字节,Limit最大值为0xFFFFFFFF个4KB(4GB)
注意,界限粒度只对段界限有效,对段基地址无效,段基地址总是以字节为单位。
S位:0 - 系统段、1 - 代码段或数据段。
S == 1 的时候 数据段或者代码段 type域 再通过11位去区分数据段还是代码段
数据段:E标志位=1,向下拓展,E标志位=0向上拓展.
向上拓展与向下拓展:
向上拓展,可以访问的段范围是:Base到Base+Limit 之间. 现在操作系统都采用向上拓展
向下拓展,可以访问的段范围是:小于Base 或 大于Base+Limit
代码段:
一致代码段 c==1: 可以从低特权级别的程序转移到高特权级别的程序执行代码 但是权限不变
非一致代码段c==0:同级别访问 高就是高低就是低 低权限可通过门提升权限
D/B位
该位对于数据段和代码段有着不同的含义,但大体都是与位数大小有关。比如,如果我们使用32位操作系统,一次操作32位,又如何切换到对16位的操作,根本上就是使用这个位。
1)代码段CS:在32位操作系统下,如果DB == 1,则采用32位寻址方式,如果操DB==0,则采用16位寻址方式.
好比汇编代码加上了0x66前缀:
机器码 :50 对应的汇编代码 push eax
机器码 :66 50 对应的汇编代码 push ax
2)数据段:该段作用与不同的数据段其含义不同。
(1) 当特殊情况下,会把数据段ds的段描述符加载到ss段,这种情况下SS的段描述符属性,实际上是DS的,属于数据段描述符,只是放在了ss段中.
mov ax,ds
mov ss,ax
此时,当使用 PUSH POP CALL RETN,类似这种能够改变堆栈指针esp值的代码:
SS段: DB == 1 ,被修改的是 esp
DB == 0 ,被修改的是 sp
和段寄存器不可见部分的对应关系是
8到24字节对应atrribute
三块base address对应base部分
两块Seg.Limit对应limit
段描述符只有64位如何填充80位的????
段限长20位 最大fffff
G为0的时候 但是要填充成32位就变成 000f ffff
G为1的时候 但是要填充成32位就变成 ffff ffff
根据TI决定查哪张表 在根据index找到表中的哪一项 在检查RPL<=DPL 满足则段描述符加载到段寄存器不可见部分
更改段寄存器的其他指令
如何查看当前你的程序在哪一环???
看cs寄存器的最后两位 是几就在几环 ss寄存器最后两位一定是等于cs寄存器最后两位的
针对段选择子而言的每个段的选择子都有自己的RPL 我用什么权限去访问你
举例:
Mov ax,0008 mov ax,000b //段选择子
Mov ds,ax mov ds,ax //段描述
指向同一个段描述符 但是RPL是不一样的
(2)DPL(Descriptor Privilege Level)
DPL存储在段描述符中13位与14位中 规定了该段所需要的特权级别是什么
通俗的理解:
如果你想访问我,那你需要具备什么样的特权
举例:
如果AX指向的段DPL = 0 但当前CX的CPL=3 这行指令是不会成功的
数据段的权限检查
参考如下代码:
比如当前程序于0环 也就是说CPL=0
Mov ax,000b // 1011 RPL= 3
Mov ds,ax //ax指向的段描述符的DPL=0
数据段的权限检查 RPL拉低了CPL的权限
MAX(CPL,RPL)<=DPL
1. 代码间的跳转 jmp 0x20:0x004183D7 cpu如何指向这行代码的哪???
(1)段选择子拆分
0x20 二进制 0000 0000 0010 0000
RPL = 00
TI = 0
INDEX = 4
TL = 0所以查找GDT表
Index = 4 找到相应的段描述符
四种情况可以跳转:代码段,调用门,TSS任务段,任务门
非一致代码段 要求 MAX(CPL,RPL)<=DPL
一致代码段 要求 CPL>=DPL
通过上面的权限检查后,cpu会将段描述符加载到cs段寄存器中
Cpu将cs.base+offset的值写入到EIP然后执行CS:EIP处的代码,段间跳转结束