我读了这篇文章:http ://static.patater.com/gbaguy/day3pc.htm
它包括句子
永远不要改变 CS!
但是如果你确实修改了CS
段寄存器会发生什么呢?为什么这么危险?
我读了这篇文章:http ://static.patater.com/gbaguy/day3pc.htm
它包括句子
永远不要改变 CS!
但是如果你确实修改了CS
段寄存器会发生什么呢?为什么这么危险?
cs
是代码段。cs:ip
,这意味着cs
与ip
(指令指针)一起指向下一条指令的位置。因此,对或对两者的任何更改cs
都会ip
更改将获取和执行下一条指令的地址。
通常你会cs
用jmp
(跳远)、call
(长呼)、retf
、int3
或int
来改变iret
。在 8088 和 8086pop cs
中也可用(操作码 0x0F)。pop cs
在 186+ 中不起作用,其中操作码 0x0F 保留用于多字节指令。 http://en.wikipedia.org/wiki/X86_instruction_listings
跳远或远叫没有本质上的危险。您只需要知道您跳转或呼叫的位置,并且在保护模式下您需要有足够的权限来执行此操作。在 16 位实模式(例如 DOS)中,您可以跳转并调用您想要的任何地址,例如。jmp 0xF000:0xFFF0
设置cs
为0xF000
和ip
,0xFFF0
这是 BIOS 代码的起始地址,从而重新启动计算机。不同的内存地址有不同的代码,因此会导致不同的结果,理论上一切可能都会发生(如果你跳转到用于格式化硬盘驱动器的 BIOS 代码,具有有效的寄存器和/或堆栈值,那么硬盘驱动器将被格式化'按照要求')。在实践jmp
中和call
's 到大多数地址可能很快就会导致无效的操作码或其他一些异常(除以零、除法溢出等)。
在保护模式和长模式(即不是16位模式)下,包括CS在内的段寄存器不再只是额外的4位地址。它们索引到段描述符表中,具有基数+限制(正常基数=0 限制=4GiB,即平面内存模型),但也具有其他属性。
代码段描述符决定了 CPU 模式(例如 32 位兼容模式与 64 位长模式)。在 64 位内核上,64 位用户空间进程可以far jmp
生成一些 32 位代码。这在实践中没有用,甚至可能在操作系统在上下文切换后返回您的进程时中断。
TODO:挖掘一个链接,其中有人展示了如何做到这一点。我认为最近甚至有一个关于此的问题,其中详细回答了如何找到正确的段号。