1.中断门介绍
在三环程序开发中,编译器进行断点之后反汇编可以查看到,断点反汇编的形式就是 int 3。如下图,在OD中查看,这就是一个断点。
int 0x3; 其实就是查找的IDT表中,从0开始,索引为3的位置,继续看下图,通过windbg查看到int 3的段描述符。
INT段描述符对应的分解图如下:
构造中断门的高32位中的低16位的值是固定的,也就是ee00
而offset就是要跳转的函数地址(高32位中高16位和低32位中低16位)
低32位中,高16位是我们的段选择子偏移(index),查询的是GDT表
2.中断门的实现
接下来找一段空的位置,在把我们新构造的段描述符放进去。
1.构建段描述符
我们需要的两个条件,第一个是函数地址,第二个是段选择子 (index),这里我新建了一个__declspec的空函数,然后取地址即可
40100a。
第二个段选择子,我们用0008即可,就是GDT表中偏移为8的地方。
GDT表
kd> dq 80b99000
80b99000 00000000`00000000 00cf9b00`0000ffff
80b99010 00cf9300`0000ffff 00cffb00`0000ffff
80b99020 00cff300`0000ffff 80008b1e`400020ab
80b99030 834093f3`5c003748 0040f300`00000fff
80b99040 0000f200`0400ffff 00000000`00000000
80b99050 830089f3`30000068 830089f3`30680068
80b99060 00000000`00000000 00000000`00000000
80b99070 800092b9`900003ff 00000000`00000000
最终构造段描述符为:
40ee00~00081005
然后我们查找IDT表中的一段空位置放进去,如下方80b99500就是一段空位置,那么int 0x20,查的则是80b99500的位置。
kd> dq 80b99400 L 30
80b99400 83e48e00`00088fc0 83e48e00`00089150
80b99410 00008500`00580000 83e4ee00`000895c0
80b99420 83e4ee00`00089748 83e48e00`000898a8
80b99430 83e48e00`00089a1c 83e48e00`0008a018
80b99440 00008500`00500000 83e48e00`0008a478
80b99450 83e48e00`0008a59c 83e48e00`0008a6dc
80b99460 83e48e00`0008a93c 83e48e00`0008ac2c
80b99470 83e48e00`0008b2fc 83e48e00`0008b6b0
80b99480 83e48e00`0008b7d4 83e48e00`0008b914
80b99490 00008500`00a00000 83e48e00`0008ba80
80b994a0 83e48e00`0008b6b0 83e48e00`0008b6b0
80b994b0 83e48e00`0008b6b0 83e48e00`0008b6b0
80b994c0 83e48e00`0008b6b0 83e48e00`0008b6b0
80b994d0 83e48e00`0008b6b0 83e48e00`0008b6b0
80b994e0 83e48e00`0008b6b0 83e48e00`0008b6b0
80b994f0 83e48e00`0008b6b0 84238e00`00086af8
80b99500 00000000`00080000 00000000`00080000
80b99510 00000000`00080000 00000000`00080000
80b99520 00000000`00080000 00000000`00080000
80b99530 00000000`00080000 00000000`00080000
80b99540 00000000`00080000 00000000`00080000
80b99550 83e4ee00`0008863a 83e4ee00`000887c0
80b99560 83e4ee00`000888fc 83e4ee00`00089498
80b99570 83e4ee00`00087fee 83e48e00`0008b6b0
写入数据 eq 80b99500 40ee00~00081005
3.通过代码实现
当调用我们自己的中断门的时候,会进入到test函数并成功赋值我们的value。
int value = 0;
void __declspec(naked) test(){
__asm{
mov dword ptr ds:[value],100;
int 3;
iretd;
}
}
int main(int argc, char* argv[])
{
printf("%xn",&test);
__asm{
pushfd;
push fs;
int 0x20;
pop fs;
popfd;
}
printf("%dn",value);
return 0;
}
然后再来观察寄存器变化。来看一下我们是否成功提权?
在三环中,寄存器的值如下
EAX = 00000007 EBX = 7FFD5000 ECX = 00422A60 EDX = 00422A60
ESI = 00000000 EDI = 0012FF48 EIP = 0040105D ESP = 0012FEF4
EBP = 0012FF48 EFL = 00000206 CS = 001B DS = 0023 ES = 0023
SS = 0023 FS = 003B GS = 0000
当 int 0x20;后,在查看一下零环寄存器的值
97e3fc9c 0040105f 返回地址
97e3fca0 0000001b CS
97e3fca4 00000206 EFL
97e3fca8 0012fef4 ESP
97e3fcac 00000023 SS
97e3fcb0 00000000
97e3fcb4 00000000
97e3fcb8 00000000
97e3fcbc 00000000
发现成功提权。
微信搜索关注 "安全族" 长期更新安全资料,扫一扫即可关注安全族!
本文始发于微信公众号(安全族):Windows内核之中断门提权
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论