Intel的x64位芯片的sysret内部实现伪码如下——
if (Not in 64-Bit Mode or Syscall/Sysret not enabled) throw #UD exceptionif (CPL != 0) throw #GP exceptionif (RCX is not CANONICAL_ADDRESS) throw #GPexception...... CPL = 0x3; .... RIP = RCX;
AMD的x64位芯片的sysret内部实现伪码如下——
if (System Call Extension is disable) throw #UD exceptionif (Protected mode is disable or CPL != 0) throw #GP exception...... CPL = 0x3; ... RIP = RCX;很明显能看出Intel的芯片在何处过早地检查并抛出针对非规范地址的GP异常。而AMD没有明确给出其芯片何时抛出针对非规范地址的GP异常的伪码,(根据AMD手册)估计是在sysret指令后试图根据RIP从内存读取下一条指令时抛出GP异常。
攻击过程:
1、利用映射获得指定虚拟内存页,首地址为:(1 << 47) - 4096
2、在该空间放置shellcode,并使得syscall指令地址位于:(1 << 47) - 23、计算并设置rdx寄存器为包含kernel_code函数地址的IDT表项数值4、计算并设置rsp寄存器,使其指向IDT表中的适当位置(以用rdx的值覆盖IDT_GP表项)5、跳转到shellcode执行。 A、触发syscall调用,此时CPU将自动将syscall指令后面的地址保存到rcx(返回地址) B、执行完指定syscall调用后,sysret指令将触发GP异常(特权级为内核态,但rsp、gs等寄存器为用户态数值) C、内核根据IDT表的IDT_GP表项定位并调用GP异常处理,在异常处理过程中,将包括rdx在内的多个寄存器压入rsp所指向的地址空间 D、由于rsp为用户态数值,并被指向系统IDT表区域,经过精确构造,可使rdx入栈时正好覆盖IDT_GP表项内容 E、由于gs为用户态数值,系统异常处理函数执行到mov %gs:0x20, %rdi时将再次触发GP异常 F、内核再度根据IDT_GP表项内容定位异常处理函数入口,此时kernel_code函数将获得调用 G、kernel_code以ring0特权级完成IDT表修复、线程提权、修复sysret环境等工作 H、调用sysret从内核态返回到用户态继续运行,即exit_usermode函数