如有错误,还请大佬指正
除了 调用门 可以进行提权操作之外,中断门也是可以的
中断描述符
那么中断门又是何方神圣?
其实中断门和调用门是同一派系的神,何出此言?
我们先来看看中断门长啥样吧
intel3卷 Vol. 3A 6-11
如果对描述符不熟悉的,可以先看看 调用门
这里可以看到与调用门的区别就是在于type域和中断门是无参数的
- 先认识一下D位:
D == 1,表示32位的中断门
D == 0,表示16位的中断门
复习一下调用门的type域:1100
这里中断门的type域为:D110 (默认为1110啦)
堆栈变化
intel 3卷 Vol. 3A 6-13
相比于调用门,这里多出来一个EFLAGS
所以调用门使用的RETF
返回值指令已经不再适用,需要使用IRET
或IRETF
进行返回
但如果对指令足够了解,也能重新构造堆栈,使用RETF
甚至RET
进行返回
挖一个坑,了解RET RETF IRET IRETF的区别
构造中断门
在构造中断门前,首先了解一下如何调用中断门
_asm {
INT 21 //INT index 的形式
}
INT 21
就是调用index == 21 的中断门。这个21已经不再包含RPL和TI位了,只是index本身
中断描述符在IDT表中,调用这一条指令CPU会去查IDT表中索引为21的中断门,根据中断描述符中的数据进行操作
同样可以写出 INT 3
INT 0
之类的指令,前提是能够 正确地使用 IDT 表中index对应的描述符
#include <windows.h>
void __declspec(naked) func(){
_asm{
int 3
iretd
}
}
int main(){
printf("function addrs: %x", func);
_asm{
int 0x22
}
return 0;
}
想来大家都喜欢直接能用代码,所以我就直接将0x22写上了
正常来说,写int 0
是没有确认好GDT表哪里有空位
先编写好大概的程序,获取函数地址
找一个空白的位置写入我们的描述符,之前查到的函数地址写到相应的位置
eq 8003f510 0040EE00`0008100A
停止调试后,将之前写的 INT 0x0
改成 INT 0x22
,重新编译执行即可
( (0x08003f510 - 0x8003f400) / 0x8 = 0x22 )转换成十进制为34,可写成INT 34
执行之后又重新跳回去了 (p指令 是执行下一条汇编指令)