(x64)Linux下的中断门测试
code
测试代码如下:
#include <stdio.h>
// 裸函数声明,好像没什么用。。。
__attribute__((naked)) void int3_handler()
{
//printf("___ kernel mode ___\n");
//printf("return to UserMode!\n");
asm("movq $0xffffffff12345678, %rax; \
popq %rbp; \
iretq");
}
int main()
{
long res = 0;
char buff[] = "haha,walker!";
printf("buff:%s addr: %p\n", buff, buff);
printf("int3_handler addr: %p\n", int3_handler);
getchar();
asm("int $0x3");
asm("leaq %0, %%rdx; movq %%rax, (%%rdx);" : "=m"(res));
printf("___ user mode ___\n");
printf("Good Done! res: %p\n", res);
return 0;
}
执行流程
测试程序的 int3_handler()
地址为 0x40105e
测试当前CPU.cr3指向当前测试程序:
可以看到,当前CPU.Cr3指向测试程序。
int3_handler()
测试函数的反汇编代码如下,
当修改IDT表中的int3中断描述符后,将异常处理例程指向测试函数 int3_handler()。
当执行测试函数时,cs处于内核态下,通过汇编指令 iretq
返回用户态。
push %rbp # 函数包装,此处未实现裸函数
mov %rsp,%rbp
movabs $0xffffffff12345678,%rax
pop %rbp # 恢复rbp,实现栈平衡
iretq # 返回用户态
# pop %rbp # --------------------- 以下指令不会执行
# retq
构造中断门
在 int3_handler() 函数处下断点,并修改idt中断门描述符
(gdb) b *0x40105e # 在int3_handle()函数处下断点
Breakpoint 1 at 0x40105e
(gdb) p idt_table # 内核全局变量, 指向idt表
$1 = 0xffffffff8082b000
构造中断门描述符:0x0010105e, 0x0040ee04 0x00000000, 0x00000000
中断在内核态
继续执行程序,程序执行int3
指令中断在int3_handler()函数处:
此时,cs/ds/ss均处于内核态。
此时 rsp 栈顶的5个元素依次为:rip、cs、eflags、rsp、ss。
cs和ss的DPL均为3,即中断来自用户态,rip为0x4010e0,rsp=0x00007fffef3de120。
返回用户态
当指向汇编指令 iretq
时,将返回用户态。
成功获取返回值!