Windows保护模式学习笔记(二)—— 代码跨段跳转
原创 lzyddf 最后发布于2019-10-16 19:17:08 阅读数 46
Windows保护模式学习笔记(二)—— 代码跨段跳转
-
- 前言
- 要点回顾
- 代码跨段跳转
-
- 执行流程
-
- 1)段选择子拆分
- 2)查表得到段描述符
- 3)权限检查
- 4)加载段描述符
- 5)代码执行
- 6)总结
-
- 一致代码段(共享的段)
- 非一致代码段(普通代码段)
- 实验
-
- 第一步:
- 第二步:
- 第三步:
- 第四步:
- 总结
前言
一、学习自中级班课程,
滴水编程达人
二、海东老师牛逼!
官网:https://bcdaren.com
要点回顾
段寄存器:
ES,CS,SS,DS,FS,GS,LDTR,TR
除CS外,其他的段寄存器都可以通过
MOV,LES,LSS,LDS,LFS,LGS
指令进行修改
思考:CS为什么不可以直接修改呢?
CS的改变意味着EIP的改变,改变CS的同时必须修改EIP,所以我们无法使用上面的指令来进行修改.
代码跨段跳转
段间跳转分为两种情况:
- 要跳转的段是一致代码段
- 要跳转的段是非一致代码段
同时修改CS与EIP的指令:
JMP FAR / CALL FAR / RETF / INT /IRETED
只改变EIP的指令:
JMP / CALL JCC / RET
执行流程
思考:CPU如何执行
JMP 0x20:0x004183D
这行指令
1)段选择子拆分
0x20 二进制:0000 0000 0010 0000 即
RPL = 00
TI = 0
Index = 4
- 1
- 2
- 3
2)查表得到段描述符
TI=0:查GDT表
Index=4:找到对应的段描述符
四种情况可以跳转:
- 代码段
- 调用门
- TSS任务段
- 任务门
3)权限检查
一致代码段:要求
CPL >= DPL
非一致代码段:要求
CPL == DPL
并且
RPL <= DPL
4)加载段描述符
通过上面的权限检查后,CPU会将段描述符加载到CS段寄存器中
5)代码执行
CPU 将
CS.Base + Offset
的值写入EIP,然后执行CS:EIP处的代码
段间跳转到此结束
6)总结
一致代码段(共享的段)
- 特权级高的程序不允许访问特权级低的数据:核心态不允许访问用户态的数据
- 特权级低的程序可以访问到特权级高的数据,但特权级不会改变:用户态还是用户态
非一致代码段(普通代码段)
- 只允许同级访问
- 绝对禁止不同级别的访问:核心态不是用户态,用户态也不是核心态
注意:直接对代码段进行JMP 或者 CALL的操作,无论目标是一致代码段还是非一致代码段,CPL都不会发生改变.如果要提升CPL的权限,只能通过调用门
实验
第一步:
复制一个非一致代码段描述符,写入GDT表空白处

第二步:
在OD中执行 JMP FAR 命令
执行前,CS = 001B
执行后,CS = 004B
执行成功!
第三步:
将段描述符的 DPL 置为 0,再在OD中执行JMP FAR命令
执行后,程序进入了ntdll,也就是异常模块,说明执行失败
失败原因:
要跳转的代码段是一个非一致代码段(DPL=0),而程序的CPL=3,权限检查未通过
非一致代码段要求CPL=DPL时才允许跳转
这样设计的目的是防止3环的程序跳转到系统段执行
第四步:
将段描述符Type域的C位改为1,令其成为一致代码段
再次执行JMP FAR命令
执行成功!
总结
一、为了对数据进行保护,普通代码段禁止用户态的代码/数据和内核态的代码/数据相互访问
二、如果选择一致代码段,低级别的程序就可以在不提升CPL权限等级的情况下进行访问,并且不会破坏内核态的数据
三、如果想访问普通代码段,必须通过"调用门"等方式提升CPL权限