代码段段间跳转流程
修改cs段寄存器#
除了cs段寄存器之外,其他的段寄存器都可以通过mov,les,lds这样的指令修改。但是cs不行,cs的修改涉及到eip指令指针的修改。
只修改eip#
jmp,call,ret等都是段内跳转指令,他们都是在不改变cs的情况下只改变eip。因为jmp,call是段内跳转指令,所以不需要进行权限的检查。
同时修改eip和cs#
jmp far,call far,retf,int等都是段间跳转指令,他们改变cs跳向其他的代码段,同时也改变了eip。因为jmp far,call far指令是段间跳转指令,所以需要进行必要的权限检查。
跳转形式#
jmp far,call far根据段选择子指向的段描述符的不同分成四种形式进行段间跳转。
- 段选择子指向的段描述符是一个普通的代码段的段描述符
- 段选择子指向的段描述符是一个调用门的门描述符
- 段选择子指向的段描述符是一个TSS任务段的描述符
- 段选择子指向的段描述符是一个任务门的门描述符
段选择子指向的段描述符是一个普通代码段的段描述符#
jmp far跳转流程#
例如指令 jmp far 0x20:0x00401005
-
拆分段选择子
段选择子为0x20,Index索引为4,TI位为0,RPL为0。 -
查找段描述符
因为其TI位为0,所以CPU会向GDT表中查找索引为4的段描述符。
其会先检查此段描述符的P位是否为1,如果为0此段描述符就无效。因为是代码段跳转,所以要求此段描述符为代码段或者是系统段(调用门,TSS任务段,任务门),但是不能为数据段。 -
权限检查
如果是非一致代码段,要求CPL == DPL (权限要一致)且 RPL <= DPL。
如果是一致代码段,要求 CPL >= DPL(低权限使用) -
加载段描述符
cpu将段描述符加载到cs段寄存器中(可见与不可见部分) -
代码执行
CPU将cs.base + offset值写入EIP,执行cs:eip完成段间跳转
call far跳转流程#
call far和jmp far差不多,但是其涉及到堆栈的变化(返回地址和cs寄存器的保存与还原)。
注意:对于段选择子指向的段描述符是一个普通代码段的段描述符时,无论是一致代码段还是非一致代码段,CPL都不会变(CPL不变其堆栈也不会切换)。无论什么时候段选择子的RPL并不会影响CPL。
例如:cs本来是0x1b,CPL为3,如果jmp far 0x48:0x004014FD
,段选择子的RPL为0。执行此指令CS会变为0x4B,而不是0x48,CPL没有改变还是3。要想改变CPL(提升权限)只能通过调用门等一些门。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】