From 8fcaaf5cbffe7903ea9bd4641216404e192a3d42 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 27 Mar 2022 10:48:24 +0200 Subject: [PATCH] More cleanup and hypervisor progress --- src/driver/CMakeLists.txt | 2 +- src/driver/driver_main.cpp | 4 +- src/driver/exception.hpp | 5 +- src/driver/finally.hpp | 2 +- src/driver/functional.hpp | 10 ++-- src/driver/hypervisor.cpp | 41 +++++++++++++- src/driver/hypervisor.hpp | 10 +++- src/driver/new.cpp | 20 +++---- src/driver/new.hpp | 16 +++--- src/driver/nt_ext.hpp | 2 +- src/driver/std_include.hpp | 2 + src/driver/stdint.hpp | 31 +++++++++++ src/driver/thread.hpp | 17 ++++-- src/driver/type_traits.hpp | 94 +++++++++++++++++++++++++++---- src/driver/unique_ptr.hpp | 15 ++++- src/driver/vmx.hpp | 101 ++++++++++++++++++++++++++++++++++ src/runner/driver.hpp | 2 +- src/runner/driver_device.hpp | 2 +- src/runner/finally.hpp | 2 +- src/runner/native_handle.hpp | 2 +- src/runner/service_handle.hpp | 2 +- src/runner/std_include.hpp | 2 +- 22 files changed, 324 insertions(+), 60 deletions(-) create mode 100644 src/driver/stdint.hpp create mode 100644 src/driver/vmx.hpp diff --git a/src/driver/CMakeLists.txt b/src/driver/CMakeLists.txt index feba51c..3129d27 100644 --- a/src/driver/CMakeLists.txt +++ b/src/driver/CMakeLists.txt @@ -5,7 +5,7 @@ file(GLOB driver_headers ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp) wdk_add_driver(driver ${driver_sources} - ${driver_header} + ${driver_headers} ) target_precompile_headers(driver PRIVATE std_include.hpp diff --git a/src/driver/driver_main.cpp b/src/driver/driver_main.cpp index 8ff38b0..06b7e30 100644 --- a/src/driver/driver_main.cpp +++ b/src/driver/driver_main.cpp @@ -46,13 +46,13 @@ private: if (type == sleep_callback::type::sleep) { debug_log("Going to sleep!"); - this->hypervisor_.on_sleep(); + this->hypervisor_.disable(); } if (type == sleep_callback::type::wakeup) { debug_log("Waking up!"); - this->hypervisor_.on_wakeup(); + this->hypervisor_.enable(); } } }; diff --git a/src/driver/exception.hpp b/src/driver/exception.hpp index 585bb53..7fedb29 100644 --- a/src/driver/exception.hpp +++ b/src/driver/exception.hpp @@ -1,5 +1,4 @@ #pragma once -#include "type_traits.hpp" namespace std { @@ -19,7 +18,6 @@ namespace std runtime_error(const char* message) : message_(message) { - } runtime_error(const runtime_error& obj) noexcept = default; @@ -27,11 +25,12 @@ namespace std runtime_error(runtime_error&& obj) noexcept = default; runtime_error& operator=(runtime_error&& obj) noexcept = default; - + const char* what() const noexcept override { return message_; } + private: const char* message_{}; }; diff --git a/src/driver/finally.hpp b/src/driver/finally.hpp index 9c3cfda..458aba8 100644 --- a/src/driver/finally.hpp +++ b/src/driver/finally.hpp @@ -52,4 +52,4 @@ namespace utils return final_action::type>::type>( std::forward(f)); } -} \ No newline at end of file +} diff --git a/src/driver/functional.hpp b/src/driver/functional.hpp index 6bb8587..2023e8f 100644 --- a/src/driver/functional.hpp +++ b/src/driver/functional.hpp @@ -25,20 +25,20 @@ namespace std Result operator()(Args ... a) const override { - f_(std::forward(a)...); + return f_(std::forward(a)...); } F f_; }; - std::unique_ptr fn{}; + std::unique_ptr fn_{}; public: function() = default; template function(T&& t) - : fn(new fn_implementation(std::forward(t))) + : fn_(new fn_implementation(std::forward(t))) { } @@ -51,12 +51,12 @@ namespace std Result operator()(Args ... args) const { - return (*this->fn)(std::forward(args)...); + return (*this->fn_)(std::forward(args)...); } operator bool() const { - return this->fn; + return this->fn_; } }; } diff --git a/src/driver/hypervisor.cpp b/src/driver/hypervisor.cpp index b82c560..44c49b2 100644 --- a/src/driver/hypervisor.cpp +++ b/src/driver/hypervisor.cpp @@ -2,6 +2,8 @@ #include "hypervisor.hpp" #include "exception.hpp" #include "logging.hpp" +#include "finally.hpp" +#include "thread.hpp" #define IA32_FEATURE_CONTROL_MSR 0x3A #define IA32_FEATURE_CONTROL_MSR_LOCK 0x0001 @@ -9,6 +11,8 @@ namespace { + hypervisor* instance{nullptr}; + bool is_vmx_supported() { int cpuid_data[4] = {0}; @@ -33,22 +37,53 @@ namespace hypervisor::hypervisor() { - if(!is_virtualization_supported()) + if (instance != nullptr) + { + throw std::runtime_error("Hypervisor already instantiated"); + } + + auto destructor = utils::finally([]() + { + instance = nullptr; + }); + instance = this; + + if (!is_virtualization_supported()) { throw std::runtime_error("VMX not supported on this machine"); } debug_log("VMX supported!\n"); + this->enable(); + destructor.cancel(); } hypervisor::~hypervisor() { + this->disable(); + instance = nullptr; } -void hypervisor::on_sleep() +void hypervisor::disable() +{ + thread::dispatch_on_all_cores([this]() + { + this->disable_core(); + }); +} + +void hypervisor::enable() +{ + thread::dispatch_on_all_cores([this]() + { + this->enable_core(); + }); +} + +void hypervisor::enable_core() { } -void hypervisor::on_wakeup() +void hypervisor::disable_core() { } diff --git a/src/driver/hypervisor.hpp b/src/driver/hypervisor.hpp index 7e0219b..3c684ea 100644 --- a/src/driver/hypervisor.hpp +++ b/src/driver/hypervisor.hpp @@ -1,5 +1,7 @@ #pragma once +#include "vmx.hpp" + class hypervisor { public: @@ -12,8 +14,10 @@ public: hypervisor(const hypervisor& obj) = delete; hypervisor& operator=(const hypervisor& obj) = delete; - void on_sleep(); - void on_wakeup(); + void enable(); + void disable(); private: -}; \ No newline at end of file + void enable_core(); + void disable_core(); +}; diff --git a/src/driver/new.cpp b/src/driver/new.cpp index f5cefaa..0623bdb 100644 --- a/src/driver/new.cpp +++ b/src/driver/new.cpp @@ -16,53 +16,53 @@ namespace } } -void* __cdecl operator new(const size_t size, const POOL_TYPE pool, const unsigned long tag) +void* operator new(const size_t size, const POOL_TYPE pool, const unsigned long tag) { return perform_allocation(size, pool, tag); } -void* __cdecl operator new[](const size_t size, const POOL_TYPE pool, const unsigned long tag) +void* operator new[](const size_t size, const POOL_TYPE pool, const unsigned long tag) { return perform_allocation(size, pool, tag); } -void* __cdecl operator new(const size_t size) +void* operator new(const size_t size) { return operator new(size, NonPagedPool); } -void* __cdecl operator new[](const size_t size) +void* operator new[](const size_t size) { return operator new[](size, NonPagedPool); } // Placement new -inline void* operator new(size_t, void* where) +void* operator new(size_t, void* where) { return where; } -void __cdecl operator delete(void* ptr, size_t) +void operator delete(void* ptr, size_t) { ExFreePool(ptr); } -void __cdecl operator delete(void* ptr) +void operator delete(void* ptr) { ExFreePool(ptr); } -void __cdecl operator delete[](void* ptr, size_t) +void operator delete[](void* ptr, size_t) { ExFreePool(ptr); } -void __cdecl operator delete[](void* ptr) +void operator delete[](void* ptr) { ExFreePool(ptr); } -extern "C" void __cdecl __std_terminate() +extern "C" void __std_terminate() { KeBugCheckEx(DRIVER_VIOLATION, 14, 0, 0, 0); } diff --git a/src/driver/new.hpp b/src/driver/new.hpp index f09a4bf..860dfa3 100644 --- a/src/driver/new.hpp +++ b/src/driver/new.hpp @@ -1,13 +1,13 @@ #pragma once -void* __cdecl operator new(size_t size, POOL_TYPE pool, unsigned long tag = 'momo'); -void* __cdecl operator new[](size_t size, POOL_TYPE pool, unsigned long tag = 'momo'); -void* __cdecl operator new(size_t size); -void* __cdecl operator new[](size_t size); +void* operator new(size_t size, POOL_TYPE pool, unsigned long tag = 'momo'); +void* operator new[](size_t size, POOL_TYPE pool, unsigned long tag = 'momo'); +void* operator new(size_t size); +void* operator new[](size_t size); inline void* operator new(size_t, void* where); -void __cdecl operator delete(void *ptr, size_t); -void __cdecl operator delete(void *ptr); -void __cdecl operator delete[](void *ptr, size_t); -void __cdecl operator delete[](void *ptr); +void operator delete(void* ptr, size_t); +void operator delete(void* ptr); +void operator delete[](void* ptr, size_t); +void operator delete[](void* ptr); diff --git a/src/driver/nt_ext.hpp b/src/driver/nt_ext.hpp index efab5e4..355eac5 100644 --- a/src/driver/nt_ext.hpp +++ b/src/driver/nt_ext.hpp @@ -33,4 +33,4 @@ KeSignalCallDpcSynchronize( #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/src/driver/std_include.hpp b/src/driver/std_include.hpp index 37b833c..ae02641 100644 --- a/src/driver/std_include.hpp +++ b/src/driver/std_include.hpp @@ -2,5 +2,7 @@ #include #include + +#include "stdint.hpp" #include "nt_ext.hpp" #include "new.hpp" \ No newline at end of file diff --git a/src/driver/stdint.hpp b/src/driver/stdint.hpp new file mode 100644 index 0000000..d8e8b99 --- /dev/null +++ b/src/driver/stdint.hpp @@ -0,0 +1,31 @@ +#pragma once + +typedef signed char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef long long int64_t; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +typedef signed char int_least8_t; +typedef short int_least16_t; +typedef int int_least32_t; +typedef long long int_least64_t; +typedef unsigned char uint_least8_t; +typedef unsigned short uint_least16_t; +typedef unsigned int uint_least32_t; +typedef unsigned long long uint_least64_t; + +typedef signed char int_fast8_t; +typedef int int_fast16_t; +typedef int int_fast32_t; +typedef long long int_fast64_t; +typedef unsigned char uint_fast8_t; +typedef unsigned int uint_fast16_t; +typedef unsigned int uint_fast32_t; +typedef unsigned long long uint_fast64_t; + +typedef long long intmax_t; +typedef unsigned long long uintmax_t; diff --git a/src/driver/thread.hpp b/src/driver/thread.hpp index b4acb74..1f30d61 100644 --- a/src/driver/thread.hpp +++ b/src/driver/thread.hpp @@ -1,22 +1,29 @@ #pragma once -using uint32_t = int; - namespace thread { uint32_t get_processor_count(); uint32_t get_processor_index(); + _IRQL_requires_min_(PASSIVE_LEVEL) + _IRQL_requires_max_(APC_LEVEL) bool sleep(uint32_t milliseconds); - void dispatch_on_all_cores(void(*callback)(void*), void* data); + _IRQL_requires_max_(APC_LEVEL) + _IRQL_requires_min_(PASSIVE_LEVEL) + _IRQL_requires_same_ + void dispatch_on_all_cores(void (*callback)(void*), void* data); - template + _IRQL_requires_max_(APC_LEVEL) + _IRQL_requires_min_(PASSIVE_LEVEL) + _IRQL_requires_same_ + + template void dispatch_on_all_cores(F&& callback) { dispatch_on_all_cores([](void* data) { - (*reinterpret_cast(data))(); + (*static_cast(data))(); }, &callback); } } diff --git a/src/driver/type_traits.hpp b/src/driver/type_traits.hpp index 5b3062e..b644bf4 100644 --- a/src/driver/type_traits.hpp +++ b/src/driver/type_traits.hpp @@ -2,6 +2,8 @@ namespace std { + using size_t = ::size_t; + // TEMPLATE CLASS remove_reference template struct remove_reference @@ -51,15 +53,85 @@ namespace std // forward an rvalue as an rvalue return (static_cast<_Ty&&>(_Arg)); } - - template< class T > struct remove_cv { typedef T type; }; - template< class T > struct remove_cv { typedef T type; }; - template< class T > struct remove_cv { typedef T type; }; - template< class T > struct remove_cv { typedef T type; }; - - template< class T > struct remove_const { typedef T type; }; - template< class T > struct remove_const { typedef T type; }; - - template< class T > struct remove_volatile { typedef T type; }; - template< class T > struct remove_volatile { typedef T type; }; + + template + struct remove_cv + { + typedef T type; + }; + + template + struct remove_cv + { + typedef T type; + }; + + template + struct remove_cv + { + typedef T type; + }; + + template + struct remove_cv + { + typedef T type; + }; + + template + struct remove_const + { + typedef T type; + }; + + template + struct remove_const + { + typedef T type; + }; + + template + struct remove_volatile + { + typedef T type; + }; + + template + struct remove_volatile + { + typedef T type; + }; + + + template + struct integral_constant + { + static constexpr T value = v; + using value_type = T; + using type = integral_constant; + constexpr operator value_type() const noexcept { return value; } + constexpr value_type operator()() const noexcept { return value; } + }; + + // ALIAS TEMPLATE bool_constant + template + using bool_constant = integral_constant; + + using true_type = bool_constant; + using false_type = bool_constant; + + template + struct is_array : std::false_type + { + }; + + template + struct is_array : std::true_type + { + }; + + template + struct is_array : std::true_type + { + }; } diff --git a/src/driver/unique_ptr.hpp b/src/driver/unique_ptr.hpp index 9a6b04a..7e98e81 100644 --- a/src/driver/unique_ptr.hpp +++ b/src/driver/unique_ptr.hpp @@ -18,7 +18,7 @@ namespace std { if (this->pointer_) { - delete this->pointer_; + delete_pointer(); this->pointer_ = nullptr; } } @@ -70,6 +70,19 @@ namespace std } private: + static constexpr auto is_array_type = is_array::value; T* pointer_{nullptr}; + + void delete_pointer() + { + if(is_array_type) + { + delete[] this->pointer_; + } + else + { + delete this->pointer_; + } + } }; } diff --git a/src/driver/vmx.hpp b/src/driver/vmx.hpp new file mode 100644 index 0000000..ca66a3e --- /dev/null +++ b/src/driver/vmx.hpp @@ -0,0 +1,101 @@ +#pragma once + +#define PML4E_ENTRY_COUNT 512 +#define PDPTE_ENTRY_COUNT 512 +#define PDE_ENTRY_COUNT 512 + +namespace vmx +{ + struct vmcs + { + uint32_t revision_id; + uint32_t abort_indicator; + uint8_t data[PAGE_SIZE - 8]; + }; + + struct epml4e + { + union + { + struct + { + uint64_t read : 1; + uint64_t write : 1; + uint64_t execute : 1; + uint64_t reserved : 5; + uint64_t accessed : 1; + uint64_t software_use : 1; + uint64_t user_mode_execute : 1; + uint64_t software_use2 : 1; + uint64_t page_frame_number : 36; + uint64_t reserved_high : 4; + uint64_t software_use_high : 12; + }; + + uint64_t full; + }; + }; + + struct pdpte + { + union + { + struct + { + uint64_t read : 1; + uint64_t write : 1; + uint64_t execute : 1; + uint64_t reserved : 5; + uint64_t accessed : 1; + uint64_t software_use : 1; + uint64_t user_mode_execute : 1; + uint64_t software_use2 : 1; + uint64_t page_frame_number : 36; + uint64_t reserved_high : 4; + uint64_t software_use_high : 12; + }; + + uint64_t full; + }; + }; + + struct large_pde + { + union + { + struct + { + uint64_t read : 1; + uint64_t write : 1; + uint64_t execute : 1; + uint64_t type : 3; + uint64_t ignore_pat : 1; + uint64_t large : 1; + uint64_t accessed : 1; + uint64_t dirty : 1; + uint64_t user_mode_execute : 1; + uint64_t software_use : 1; + uint64_t reserved : 9; + uint64_t page_frame_number : 27; + uint64_t reserved_high : 4; + uint64_t software_use_high : 11; + uint64_t suppress_vme : 1; + }; + + uint64_t full; + }; + }; + + struct vm_state + { + DECLSPEC_ALIGN(PAGE_SIZE) uint8_t stack_buffer[KERNEL_STACK_SIZE]{}; + + DECLSPEC_ALIGN(PAGE_SIZE) uint8_t msr_bitmap[PAGE_SIZE]{}; + DECLSPEC_ALIGN(PAGE_SIZE) epml4e epml4[PML4E_ENTRY_COUNT]{}; + DECLSPEC_ALIGN(PAGE_SIZE) pdpte epdpt[PDPTE_ENTRY_COUNT]{}; + DECLSPEC_ALIGN(PAGE_SIZE) large_pde epde[PDPTE_ENTRY_COUNT][PDE_ENTRY_COUNT]{}; + + DECLSPEC_ALIGN(PAGE_SIZE) vmcs vmx_on{}; + DECLSPEC_ALIGN(PAGE_SIZE) vmcs vmcs{}; + }; +} diff --git a/src/runner/driver.hpp b/src/runner/driver.hpp index 20f2e7b..b60cd88 100644 --- a/src/runner/driver.hpp +++ b/src/runner/driver.hpp @@ -6,7 +6,7 @@ class driver public: driver(const std::filesystem::path& driver_file, const std::string& service_name); ~driver(); - + driver(const driver&) = delete; driver& operator=(const driver&) = delete; diff --git a/src/runner/driver_device.hpp b/src/runner/driver_device.hpp index eaab3ea..5a3c5da 100644 --- a/src/runner/driver_device.hpp +++ b/src/runner/driver_device.hpp @@ -6,7 +6,7 @@ class driver_device public: driver_device(const std::string& driver_device); ~driver_device() = default; - + driver_device(const driver_device&) = delete; driver_device& operator=(const driver_device&) = delete; diff --git a/src/runner/finally.hpp b/src/runner/finally.hpp index 69e448f..db9599e 100644 --- a/src/runner/finally.hpp +++ b/src/runner/finally.hpp @@ -52,4 +52,4 @@ namespace utils return final_action::type>::type>( std::forward(f)); } -} \ No newline at end of file +} diff --git a/src/runner/native_handle.hpp b/src/runner/native_handle.hpp index 3c7c045..c6d98a1 100644 --- a/src/runner/native_handle.hpp +++ b/src/runner/native_handle.hpp @@ -6,7 +6,7 @@ public: native_handle(); native_handle(HANDLE handle); ~native_handle(); - + native_handle(const native_handle&) = delete; native_handle& operator=(const native_handle&) = delete; diff --git a/src/runner/service_handle.hpp b/src/runner/service_handle.hpp index 8d761e6..601197d 100644 --- a/src/runner/service_handle.hpp +++ b/src/runner/service_handle.hpp @@ -6,7 +6,7 @@ public: service_handle(); service_handle(SC_HANDLE handle); ~service_handle(); - + service_handle(const service_handle&) = delete; service_handle& operator=(const service_handle&) = delete; diff --git a/src/runner/std_include.hpp b/src/runner/std_include.hpp index 78f947c..8a2f48d 100644 --- a/src/runner/std_include.hpp +++ b/src/runner/std_include.hpp @@ -7,4 +7,4 @@ #include #include -#pragma comment(lib, "Shlwapi.lib") \ No newline at end of file +#pragma comment(lib, "Shlwapi.lib")