调用门实际上还是一个描述符的格式,储存于GDTor
LDT表中,以下是他的结构
以下是跳转时候,使用门的汇编代码
1 | char door[] = {0,0,0,0,0x48,0}; |
这里使用的call 通过一个远指针(door)跳转,jmp也可以跳转但是不能提权。此时,描述符就不会被识别为段描述符
而是门描述符
其中的TYPE位置为c(h) = 1100(c)
决定了这个描述符的的类型是 调用门
首尾组合成的段中偏移值就是我们要跳转到的地方,即汇编指令中跳转的地址是没有作用的,(上代码中为0)
使用调用门之后会自动压入当前代码段的CS和返回地址,所以我们不能使用ret
而使用retf
此外用调用门的时候还可以携带参数,并且是先push参数,再push CS,再push返回地址,而门描述符中有5bit存放参数个数,意思是最多可以有2^5-1=31
个参数,调用代码如下 (此时需要对应修改门描述符中参数个数为2)
1 | char door[] = {0,0,0,0,0x48,0}; |
目标函数中只需要使用retf
即可把参数也pop出去,这就是retf
的特殊之处了
使用调用门的时候需要满足以下的权限检查:
[数值上] ① CPL<=调用门描述符DPL,②调用门RPL<=调用门描述符DPL,③当前CPL>=目标代码段描述符DPL
因为检查③的存在 我们可以由当前的R3(CPL=3)跳转到目标的R0(目标代码段描述符DPL=0)去
以下是实验代码
1 | /* |