一.如何识别门描述符:
门描述符是什么? 从一个房间进入到另一个房间时,我们就需要经过一扇门,从用户的2G空间,进入到内核的2G空间,我们也需要经过一扇门.
当S位=1 Type位为1100的时候
这个描述符,是一个门描述符:
二.门描述符有什么特点是区别于其他描述符的:
1.普通代码中,CPU要执行的代码地址为EIP所存储的地址,而在门中,将要被执行的代码地址是由Base(新地址的段选择子)+offset31:16+offset:15:0组成的.
CALL CS:EIP(此时的EIP并没什么卵用,凑个数...)
2.调用门在使用的时候,往往会用于提权,因此改动的寄存器有四个:SS CS EIP ESP, 一般的CALL只会改动ESP和EIP.
三.大概的实现模型:
void main()
{
char address;
*(DWORD*)&address[0]=0x12345678;//EIP赋值,因为没用...所以随便喽...
*(WORD*)&address[4]=0x48;//这个是CS寄存器的值,目的是为了,找到自己改写的GDT表里的相应位置,没改的时候是0000 0000.
_asm
{
CALL fword prt[address]
}
}
当代码执行后,CPU会按照CS的段选择子0x0048,取查找GDT表,找到我们改写好的段描述符,之所以选择这个位置,是因为在GDT表中,此位置一直为空,方便我们改写.
0000(offset1) ec00`0008 0000(offset2)
两个offset组成的地址,就是中断门要跳去的真实EIP
P位要为1,DPL要为3(因为代码运行时你还处于R3层),因此1110组成了e
TYPE 1100 是调用门的标志,所以组成了c
后面跟的是0000
最后的ParamCount是要传的参数,没有的时候就些了0
到此ec00 组合完毕
Segment Selector是新的段选择子,根据需要填写,如果想提权的话RPL就需要置0
随便写了一个 0008
(由于Windows系统本身并没有使用调用门,而其本身我也不是很喜欢用,所以测试代码也懒得写了...因此只是写了一个模型,offset和Index写的都是0)
0000ec00`00080000就是这么来的.
上边一个调用门,使用的是CALL FAR来进行的,当然JMP FAR也可以使用,但有一个比较重要的问题就是,在使用CALL FAR的时候,同时会修改CPL,而JMP FAR并不会.
因此在调用门实际使用过程中CALL FAR可以用来进行提权操作,当然也可以不提权,JMP FAR就显得有些多余了,毕竟不提权,我还调个毛的门啊...
比较要注意的一点是,调用门使用的时候 CS和EIP的值,是自己指定的,而SS和ESP的值来源于TSS中.