调用门使代码段从ring3调用到ring0再回到ring3的过程

GDT和LDT分别为全局描述表和局部描述表,其中表中每一项又叫做段描述符。段描述符,由段地址,以及段类型,特权级DPL等组成,其中段类型说明此段是代码段还是数据段,还是各种门,还是TSS等。通过GDT访问某个段的时候需要使用段选择符来进行调用。普通调用下,是根据是否是一致代码段进行同级权限代码段之间的调用,或者是低权限向高权限代码的调用,但是CPL不会改变。如果想要从低权限向高权限调用,并且可以改变CPL的话,必须通过调用门这种方式,或者自陷门,这里只说一下调用门。

 

调用门也是一种描述符,但其中并不像普通代码段那样存储段基址和段界限,而是存储的选择子和段偏移。当低权限CPL代码调用高权限代码段DPL的时候,调用门作为中间层进行间接的调用。

首先低权限代码段调用指定调用门,调用要求是CPL小于等于调用门的DPL,如果ring3调用的话,调用门的DPL要设置为3才可以。通过调用门的权限验证之后,然后通过选择子目标代码段的描述符,从中取出目标代码段的DPL,权限要求是CPL大于等于DPL,这样的话就实现了RING3到ring0的权限转移。

实现调用门的权限转移,目标如果是一致代码段的话CALL和JMP都可以,如果是非一致代码段的话必须用CALL。

进入ring0后通过retf实现ring0到ring3的转移。由于不同特权级所对应的堆栈是不同的,因此需要初始化并加载TSS描述符来说明不同特权级所对应的堆栈,在低权限到高权限的跳转时是需要TSS的。堆栈具体操作如下:

根据目标代码段的DPL选择TSS中对应的SS和ESP进行加载。

临时保存当前的ESP和SS。

加载新的ESP和SS。

将旧的ESP和SS压栈到新堆栈当中。

根据调用门中的PARAM COUNT复制参数从旧堆栈到新堆栈。

压入CS,EIP。

 

当执行RETF的时候恢复CS,EIP,SS,ESP,并从高权限跳转到低权限。

 

调用门和windows使用int 0x2e的权限跳转方式原理上是差不多的。

你可能感兴趣的:(代码)