diff --git a/PSKDM/PSKDM.vcxproj b/PSKDM/PSKDM.vcxproj index 84e6de3..3e5dc91 100644 --- a/PSKDM/PSKDM.vcxproj +++ b/PSKDM/PSKDM.vcxproj @@ -217,7 +217,7 @@ - + diff --git a/PSKDM/PSKDM.vcxproj.filters b/PSKDM/PSKDM.vcxproj.filters index 44dc5b9..818bb07 100644 --- a/PSKDM/PSKDM.vcxproj.filters +++ b/PSKDM/PSKDM.vcxproj.filters @@ -67,10 +67,10 @@ Header Files - + Header Files - + Header Files diff --git a/PSKDM/map_driver.cpp b/PSKDM/map_driver.cpp index 2685c00..8d4388a 100644 --- a/PSKDM/map_driver.cpp +++ b/PSKDM/map_driver.cpp @@ -1,6 +1,6 @@ #include "map_driver.hpp" #include "mapper_ctx/mapper_ctx.hpp" -#include "vdm_ctx/vdm_ctx.h" +#include "vdm_ctx/vdm_ctx.hpp" #include "vdm/vdm.hpp" #include "set_mgr/set_mgr.hpp" @@ -22,13 +22,30 @@ namespace mapper if (!runtime_broker_pid) return { mapper_error::failed_to_create_proc, nullptr }; - vdm::vdm_ctx v_ctx; - nasa::mem_ctx my_proc(v_ctx, GetCurrentProcessId()); - nasa::mem_ctx runtime_broker(v_ctx, runtime_broker_pid); - nasa::mapper_ctx mapper(my_proc, runtime_broker); + vdm::read_phys_t _read_phys = + [&](void* addr, void* buffer, std::size_t size) -> bool + { + return vdm::read_phys(addr, buffer, size); + }; + + vdm::write_phys_t _write_phys = + [&](void* addr, void* buffer, std::size_t size) -> bool + { + return vdm::write_phys(addr, buffer, size); + }; + + vdm::vdm_ctx v_ctx(_read_phys, _write_phys); + nasa::mem_ctx my_proc(&v_ctx, GetCurrentProcessId()); + nasa::mem_ctx runtime_broker(&v_ctx, runtime_broker_pid); + nasa::mapper_ctx mapper(&my_proc, &runtime_broker); + + const auto result = + set_mgr::stop_setmgr(v_ctx, + set_mgr::get_setmgr_pethread(v_ctx)); + + if (result != STATUS_SUCCESS) + return { mapper_error::set_mgr_failure, nullptr }; - // shoot the tires off the set manager thread..... - set_mgr::stop_setmgr(v_ctx, set_mgr::get_setmgr_pethread(v_ctx)); const auto [drv_base, drv_entry] = mapper.map(drv_buffer); if (!drv_base || !drv_entry) return { mapper_error::init_failed, nullptr }; diff --git a/PSKDM/map_driver.hpp b/PSKDM/map_driver.hpp index 3291a01..5563f91 100644 --- a/PSKDM/map_driver.hpp +++ b/PSKDM/map_driver.hpp @@ -7,13 +7,14 @@ namespace mapper { enum class mapper_error { - error_success = 0x000, // everything is good! - image_invalid = 0x111, // the driver your trying to map is invalid (are you importing things that arent in ntoskrnl?) - load_error = 0x222, // unable to load signed driver into the kernel (are you running as admin?) - unload_error = 0x333, // unable to unload signed driver from kernel (are all handles to this driver closes?) - piddb_fail = 0x444, // piddb cache clearing failed... (are you using this code below windows 10?) - init_failed = 0x555, // setting up library dependancies failed! - failed_to_create_proc = 0x777 // was unable to create a new process to inject driver into! (RuntimeBroker.exe) + error_success, // everything is good! + image_invalid, // the driver your trying to map is invalid (are you importing things that arent in ntoskrnl?) + load_error, // unable to load signed driver into the kernel (are you running as admin?) + unload_error, // unable to unload signed driver from kernel (are all handles to this driver closes?) + piddb_fail, // piddb cache clearing failed... (are you using this code below windows 10?) + init_failed, // setting up library dependancies failed! + failed_to_create_proc, // was unable to create a new process to inject driver into! (RuntimeBroker.exe) + set_mgr_failure // unable to stop working set manager thread... this thread can cause issues with PTM... }; /// @@ -23,5 +24,5 @@ namespace mapper /// size of the driver buffer /// data to be sent to the entry point of the driver... /// status of the driver being mapped, and base address of the driver... - std::pair map_driver(std::uint8_t* drv_image, std::size_t image_size, void** entry_data); + auto map_driver(std::uint8_t* drv_image, std::size_t image_size, void** entry_data)->std::pair; } \ No newline at end of file diff --git a/PSKDM/mapper_ctx/mapper_ctx.cpp b/PSKDM/mapper_ctx/mapper_ctx.cpp index 829c204..d9c12bc 100644 --- a/PSKDM/mapper_ctx/mapper_ctx.cpp +++ b/PSKDM/mapper_ctx/mapper_ctx.cpp @@ -4,8 +4,8 @@ namespace nasa { mapper_ctx::mapper_ctx ( - nasa::mem_ctx& map_into, - nasa::mem_ctx& map_from + nasa::mem_ctx* map_into, + nasa::mem_ctx* map_from ) : map_into(map_into), @@ -14,7 +14,7 @@ namespace nasa { const auto map_into_pml4 = reinterpret_cast( - map_into.set_page(map_into.get_dirbase())); + map_into->set_page(map_into->dirbase)); // look for an empty pml4e... for (auto idx = 0u; idx < 256; ++idx) @@ -30,18 +30,20 @@ namespace nasa auto mapper_ctx::map(std::vector& raw_image) -> std::pair { const auto [drv_alloc, drv_entry_addr] = allocate_driver(raw_image); - auto [drv_ppml4e, drv_pml4e] = map_from.get_pml4e(drv_alloc); + auto [drv_ppml4e, drv_pml4e] = map_from->get_pml4e(drv_alloc); - while (!SwitchToThread()); make_kernel_access(drv_alloc); - map_from.set_pml4e(drv_ppml4e, pml4e{ NULL }); - while (!SwitchToThread()); + while (!map_from->set_pml4e(drv_ppml4e, pml4e{ NULL })) + continue; drv_pml4e.nx = false; drv_pml4e.user_supervisor = false; - map_into.write_phys(reinterpret_cast( - map_into.get_dirbase()) + this->pml4_idx, drv_pml4e); + // ensure we insert the pml4e... + while (!map_into->write_phys( + reinterpret_cast( + map_into->dirbase) + this->pml4_idx, drv_pml4e)) + continue; virt_addr_t new_addr = { reinterpret_cast(drv_alloc) }; new_addr.pml4_index = this->pml4_idx; @@ -50,7 +52,7 @@ namespace nasa void mapper_ctx::call_entry(void* drv_entry, void** hook_handler) const { - map_into.v_ctx->syscall(drv_entry, hook_handler); + map_into->v_ctx->syscall(drv_entry, hook_handler); } auto mapper_ctx::allocate_driver(std::vector& raw_image) -> std::pair @@ -60,11 +62,11 @@ namespace nasa OpenProcess( PROCESS_ALL_ACCESS, FALSE, - map_from.get_pid() + map_from->pid ); if (!process_handle) - return {}; + return { {}, {} }; drv_image.fix_imports([&](const char* module_name, const char* export_name) { @@ -87,7 +89,7 @@ namespace nasa )); if (!drv_alloc_base) - return {}; + return { {}, {} }; virt_addr_t new_addr = { reinterpret_cast(drv_alloc_base) }; new_addr.pml4_index = this->pml4_idx; @@ -110,15 +112,23 @@ namespace nasa return { reinterpret_cast(drv_alloc_base), - reinterpret_cast(drv_image.entry_point() + reinterpret_cast(new_addr.value)) + reinterpret_cast(drv_image.entry_point() + + reinterpret_cast(new_addr.value)) }; } void mapper_ctx::make_kernel_access(void* drv_base) { - const auto [ppdpte, pdpte] = map_from.get_pdpte(drv_base); - auto ppdpte_phys = reinterpret_cast((reinterpret_cast(ppdpte) >> 12) << 12); // 0 the last 12 bits... - auto pdpt_mapping = reinterpret_cast<::ppdpte>(map_from.set_page(ppdpte_phys)); + const auto [ppdpte, pdpte] = + map_from->get_pdpte(drv_base); + + auto ppdpte_phys = + reinterpret_cast(( + reinterpret_cast(ppdpte) >> 12) << 12); // 0 the last 12 bits... + + auto pdpt_mapping = + reinterpret_cast<::ppdpte>( + map_from->set_page(ppdpte_phys)); // set pdptes to CPL0 access only and executable... for (auto pdpt_idx = 0u; pdpt_idx < 512; ++pdpt_idx) @@ -129,7 +139,7 @@ namespace nasa pdpt_mapping[pdpt_idx].nx = false; auto pd_mapping = reinterpret_cast( - map_from.set_page(reinterpret_cast( + map_from->set_page(reinterpret_cast( pdpt_mapping[pdpt_idx].pfn << 12))); // set pdes to CPL0 access only and executable... @@ -141,7 +151,7 @@ namespace nasa pd_mapping[pd_idx].nx = false; auto pt_mapping = reinterpret_cast( - map_from.set_page(reinterpret_cast( + map_from->set_page(reinterpret_cast( pd_mapping[pd_idx].pfn << 12))); // set ptes to CPL0 access only and executable... @@ -156,14 +166,14 @@ namespace nasa // set page back to pd... pd_mapping = reinterpret_cast( - map_from.set_page(reinterpret_cast( + map_from->set_page(reinterpret_cast( pdpt_mapping[pdpt_idx].pfn << 12))); } } // set page back to pdpt... pdpt_mapping = reinterpret_cast<::ppdpte>( - map_from.set_page(ppdpte_phys)); + map_from->set_page(ppdpte_phys)); } } } diff --git a/PSKDM/mapper_ctx/mapper_ctx.hpp b/PSKDM/mapper_ctx/mapper_ctx.hpp index 9ed4800..4f7f2ec 100644 --- a/PSKDM/mapper_ctx/mapper_ctx.hpp +++ b/PSKDM/mapper_ctx/mapper_ctx.hpp @@ -6,14 +6,14 @@ namespace nasa class mapper_ctx { public: - explicit mapper_ctx(nasa::mem_ctx& map_into, nasa::mem_ctx& map_from); - auto map(std::vector& raw_image)->std::pair; + explicit mapper_ctx(nasa::mem_ctx* map_into, nasa::mem_ctx* map_from); + auto map(std::vector& raw_image) -> std::pair; void call_entry(void* drv_entry, void** hook_handler) const; private: std::uint16_t pml4_idx; - auto allocate_driver(std::vector& raw_image)->std::pair; + auto allocate_driver(std::vector& raw_image) -> std::pair; void make_kernel_access(void* drv_base); - nasa::mem_ctx map_into, map_from; + nasa::mem_ctx* map_into, *map_from; }; } \ No newline at end of file diff --git a/PSKDM/mem_ctx/mem_ctx.cpp b/PSKDM/mem_ctx/mem_ctx.cpp index 12ebd48..1e487f7 100644 --- a/PSKDM/mem_ctx/mem_ctx.cpp +++ b/PSKDM/mem_ctx/mem_ctx.cpp @@ -2,20 +2,25 @@ 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; + break; + } + } // allocate a pdpt this->new_pdpt.second = @@ -31,13 +36,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 +63,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,42 +83,42 @@ 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() { - set_pml4e(reinterpret_cast<::ppml4e>(get_dirbase()) + this->pml4e_index, pml4e{NULL}); - while (!SwitchToThread()); + const auto pml4 = + reinterpret_cast( + set_page(dirbase))[pml4e_index] = pml4e{ NULL }; } void* mem_ctx::set_page(void* addr) { - // table entry change. + ++pte_index; + if (pte_index > 511) { - ++pte_index; - if (pte_index >= 511) - { - ++pde_index; - pte_index = 0; - } - - if (pde_index >= 511) - { - ++pdpte_index; - pde_index = 0; - } + ++pde_index; + pte_index = 0; + } - if (pdpte_index >= 511) - pdpte_index = 0; + if (pde_index > 511) + { + ++pdpte_index; + pde_index = 0; } + if (pdpte_index > 511) + pdpte_index = 0; + pdpte new_pdpte = { NULL }; new_pdpte.present = true; new_pdpte.rw = true; new_pdpte.pfn = reinterpret_cast(new_pd.first) >> 12; new_pdpte.user_supervisor = true; - new_pdpte.accessed = true; // set pdpte entry *reinterpret_cast(new_pdpt.second + pdpte_index) = new_pdpte; @@ -116,7 +128,6 @@ namespace nasa new_pde.rw = true; new_pde.pfn = reinterpret_cast(new_pt.first) >> 12; new_pde.user_supervisor = true; - new_pde.accessed = true; // set pde entry *reinterpret_cast(new_pd.second + pde_index) = new_pde; @@ -126,7 +137,6 @@ namespace nasa new_pte.rw = true; new_pte.pfn = reinterpret_cast(addr) >> 12; new_pte.user_supervisor = true; - new_pte.accessed = true; // set pte entry *reinterpret_cast(new_pt.second + pte_index) = new_pte; @@ -145,18 +155,39 @@ namespace nasa new_addr.pd_index = this->pde_index; new_addr.pt_index = this->pte_index; new_addr.offset = this->page_offset; + + // 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) + { + // try again to access the page... + __try + { + *(std::uint8_t*)new_addr.value = *(std::uint8_t*)new_addr.value; + return new_addr.value; + } + // try one last time by yeilding execution... + __except (EXCEPTION_EXECUTE_HANDLER) + { + while (!SwitchToThread()) + continue; + } + } return new_addr.value; } void* mem_ctx::get_dirbase(vdm::vdm_ctx& v_ctx, DWORD pid) { const auto peproc = - reinterpret_cast(v_ctx.get_peprocess(pid)); + reinterpret_cast( + v_ctx.get_peprocess(pid)); - const auto dirbase = - v_ctx.rkm(peproc + 0x28); - - return reinterpret_cast(dirbase.pfn << 12); + return reinterpret_cast( + v_ctx.rkm(peproc + 0x28).pfn << 12); } bool mem_ctx::hyperspace_entries(pt_entries& entries, void* addr) @@ -201,95 +232,106 @@ namespace nasa return true; } - std::pair mem_ctx::get_pte(void* addr, bool use_hyperspace) + auto mem_ctx::get_pte(void* addr, bool use_hyperspace) -> std::pair { if (!dirbase || !addr) - return {}; + return { {}, {} }; pt_entries entries; if ((use_hyperspace ? hyperspace_entries(entries, addr) : (bool)virt_to_phys(entries, addr))) return { entries.pt.first, entries.pt.second }; - return {}; + + return { {}, {} }; } - void mem_ctx::set_pte(void* addr, const ::pte& pte, bool use_hyperspace) + bool mem_ctx::set_pte(void* addr, const ::pte& pte, bool use_hyperspace) { if (!dirbase || !addr) - return; + return false; if (use_hyperspace) - v_ctx->wkm(v_ctx->get_virtual(reinterpret_cast(addr)), pte); - else - write_phys(addr, pte); + return v_ctx->wkm( + v_ctx->get_virtual( + reinterpret_cast(addr)), pte); + + return write_phys(addr, pte); } - std::pair mem_ctx::get_pde(void* addr, bool use_hyperspace) + auto mem_ctx::get_pde(void* addr, bool use_hyperspace) -> std::pair { if (!dirbase || !addr) - return {}; + return { {}, {} }; pt_entries entries; if ((use_hyperspace ? hyperspace_entries(entries, addr) : (bool)virt_to_phys(entries, addr))) return { entries.pd.first, entries.pd.second }; - return {}; + return { {}, {} }; } - void mem_ctx::set_pde(void* addr, const ::pde& pde, bool use_hyperspace) + bool mem_ctx::set_pde(void* addr, const ::pde& pde, bool use_hyperspace) { - if (!this->dirbase || !addr) - return; + if (!dirbase || !addr) + return false; if (use_hyperspace) - v_ctx->wkm(v_ctx->get_virtual(reinterpret_cast(addr)), pde); - else - write_phys(addr, pde); + return v_ctx->wkm( + v_ctx->get_virtual( + reinterpret_cast(addr)), pde); + + return write_phys(addr, pde); } - std::pair mem_ctx::get_pdpte(void* addr, bool use_hyperspace) + auto mem_ctx::get_pdpte(void* addr, bool use_hyperspace) -> std::pair { if (!dirbase || !addr) - return {}; + return { {}, {} }; pt_entries entries; if ((use_hyperspace ? hyperspace_entries(entries, addr) : (bool)virt_to_phys(entries, addr))) return { entries.pdpt.first, entries.pdpt.second }; - return {}; + + return { {}, {} }; } - void mem_ctx::set_pdpte(void* addr, const ::pdpte& pdpte, bool use_hyperspace) + bool mem_ctx::set_pdpte(void* addr, const ::pdpte& pdpte, bool use_hyperspace) { - if (!this->dirbase || !addr) - return; + if (!dirbase || !addr) + return false; if (use_hyperspace) - v_ctx->wkm(v_ctx->get_virtual(reinterpret_cast(addr)), pdpte); - else - write_phys(addr, pdpte); + return v_ctx->wkm( + v_ctx->get_virtual( + reinterpret_cast(addr)), pdpte); + + return write_phys(addr, pdpte); } - std::pair mem_ctx::get_pml4e(void* addr, bool use_hyperspace) + auto mem_ctx::get_pml4e(void* addr, bool use_hyperspace) -> std::pair { - if (!this->dirbase || !addr) - return {}; + if (!dirbase || !addr) + return { {}, {} }; pt_entries entries; if ((use_hyperspace ? hyperspace_entries(entries, addr) : (bool)virt_to_phys(entries, addr))) return { entries.pml4.first, entries.pml4.second }; - return {}; + + return { {}, {} }; } - void mem_ctx::set_pml4e(void* addr, const ::pml4e& pml4e, bool use_hyperspace) + bool mem_ctx::set_pml4e(void* addr, const ::pml4e& pml4e, bool use_hyperspace) { - if (!this->dirbase || !addr) - return; + if (!dirbase || !addr) + return false; if (use_hyperspace) - v_ctx->wkm(v_ctx->get_virtual(reinterpret_cast(addr)), pml4e); - else - write_phys(addr, pml4e); + return v_ctx->wkm( + v_ctx->get_virtual( + reinterpret_cast(addr)), pml4e); + + return write_phys(addr, pml4e); } - std::pair mem_ctx::read_virtual(void* buffer, void* addr, std::size_t size) + auto mem_ctx::read_virtual(void* buffer, void* addr, std::size_t size) -> std::pair { if (!buffer || !addr || !size || !dirbase) return {}; @@ -331,7 +373,7 @@ namespace nasa } } - std::pair mem_ctx::write_virtual(void* buffer, void* addr, std::size_t size) + auto mem_ctx::write_virtual(void* buffer, void* addr, std::size_t size) -> std::pair { if (!buffer || !addr || !size || !dirbase) return {}; @@ -373,10 +415,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 @@ -384,13 +426,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 @@ -398,12 +443,15 @@ 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) { - if (!addr || !this->dirbase) + if (!addr || !dirbase) return {}; const virt_addr_t virt_addr{ addr }; @@ -447,37 +495,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/PSKDM/mem_ctx/mem_ctx.hpp b/PSKDM/mem_ctx/mem_ctx.hpp index da40df2..d0f555f 100644 --- a/PSKDM/mem_ctx/mem_ctx.hpp +++ b/PSKDM/mem_ctx/mem_ctx.hpp @@ -1,36 +1,33 @@ #pragma once #include "../util/nt.hpp" -#include "../vdm_ctx/vdm_ctx.h" +#include "../vdm_ctx/vdm_ctx.hpp" namespace nasa { class mem_ctx { - friend class mapper_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(); - std::pair get_pte(void* addr, bool use_hyperspace = false); - void set_pte(void* addr, const ::pte& pte, bool use_hyperspace = false); + auto get_pte(void* addr, bool use_hyperspace = false) -> std::pair; + bool set_pte(void* addr, const ::pte& pte, bool use_hyperspace = false); - std::pair get_pde(void* addr, bool use_hyperspace = false); - void set_pde(void* addr, const ::pde& pde, bool use_hyperspace = false); + auto get_pde(void* addr, bool use_hyperspace = false) -> std::pair; + bool set_pde(void* addr, const ::pde& pde, bool use_hyperspace = false); - std::pair get_pdpte(void* addr, bool use_hyperspace = false); - void set_pdpte(void* addr, const ::pdpte& pdpte, bool use_hyperspace = false); + auto get_pdpte(void* addr, bool use_hyperspace = false) -> std::pair; + bool set_pdpte(void* addr, const ::pdpte& pdpte, bool use_hyperspace = false); - std::pair get_pml4e(void* addr, bool use_hyperspace = false); - void set_pml4e(void* addr, const ::pml4e& pml4e, bool use_hyperspace = false); - - void* get_dirbase() const; + auto get_pml4e(void* addr, bool use_hyperspace = false) -> std::pair; + bool set_pml4e(void* addr, const ::pml4e& pml4e, bool use_hyperspace = false); 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 - T read_phys(void* addr) + __forceinline T read_phys(void* addr) { T buffer; read_phys((void*)&buffer, addr, sizeof(T)); @@ -38,13 +35,13 @@ namespace nasa } template - void write_phys(void* addr, const T& data) + __forceinline bool write_phys(void* addr, const T& data) { - write_phys((void*)&data, addr, sizeof(T)); + return write_phys((void*)&data, addr, sizeof(T)); } - std::pair read_virtual(void* buffer, void* addr, std::size_t size); - std::pair write_virtual(void* buffer, void* addr, std::size_t size); + auto read_virtual(void* buffer, void* addr, std::size_t size) -> std::pair; + auto write_virtual(void* buffer, void* addr, std::size_t size) -> std::pair; template __forceinline T read_virtual(void* addr) @@ -61,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, @@ -83,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/PSKDM/set_mgr/set_mgr.hpp b/PSKDM/set_mgr/set_mgr.hpp index beea970..5b99746 100644 --- a/PSKDM/set_mgr/set_mgr.hpp +++ b/PSKDM/set_mgr/set_mgr.hpp @@ -1,5 +1,5 @@ #pragma once -#include "../vdm_ctx/vdm_ctx.h" +#include "../vdm_ctx/vdm_ctx.hpp" using PETHREAD = PVOID; using PsSuspendThread = NTSTATUS(*)(PETHREAD, PULONG); diff --git a/PSKDM/vdm_ctx/vdm_ctx.cpp b/PSKDM/vdm_ctx/vdm_ctx.cpp index 52581c6..9061160 100644 --- a/PSKDM/vdm_ctx/vdm_ctx.cpp +++ b/PSKDM/vdm_ctx/vdm_ctx.cpp @@ -1,10 +1,13 @@ -#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) { - // if we already found the syscall's physical page... + // already found the syscall's physical page... if (vdm::syscall_address.load()) return; @@ -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; + } + + bool vdm_ctx::rkm(void* dst, void* src, std::size_t size) + { + static const auto ntoskrnl_memcpy = + util::get_kmodule_export("ntoskrnl.exe", "memcpy"); + + return this->syscall( + ntoskrnl_memcpy, dst, src, size); + } + + bool vdm_ctx::wkm(void* dst, void* src, std::size_t size) + { + static const auto ntoskrnl_memcpy = + util::get_kmodule_export("ntoskrnl.exe", "memcpy"); + + return 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/PSKDM/vdm_ctx/vdm_ctx.h b/PSKDM/vdm_ctx/vdm_ctx.hpp similarity index 70% rename from PSKDM/vdm_ctx/vdm_ctx.h rename to PSKDM/vdm_ctx/vdm_ctx.hpp index 7396687..84282c7 100644 --- a/PSKDM/vdm_ctx/vdm_ctx.h +++ b/PSKDM/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); + bool rkm(void* dst, void* src, std::size_t size); + bool 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) + __forceinline auto wkm(std::uintptr_t addr, const T& value) -> bool { - 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); + return wkm((void*)addr, (void*)&value, sizeof T); } __forceinline auto get_peprocess(std::uint32_t pid) -> PEPROCESS @@ -106,8 +93,23 @@ namespace vdm ); 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 diff --git a/um-example/PSKDM.lib b/um-example/PSKDM.lib index bf5f52e..4d0e6a1 100644 Binary files a/um-example/PSKDM.lib and b/um-example/PSKDM.lib differ diff --git a/um-example/main.cpp b/um-example/main.cpp index 601130b..0cbbebb 100644 --- a/um-example/main.cpp +++ b/um-example/main.cpp @@ -20,10 +20,10 @@ int __cdecl main(int argc, char** argv) ( driver_data.data(), driver_data.size(), - nullptr + nullptr // you can pass your structure here... ); - std::printf("[+] driver mapping result -> 0x%x\n", result); + std::printf("[+] driver mapping result -> 0x%x (0 == STATUS_SUCCESS)\n", result); std::printf("[+] driver base address (usermode) -> 0x%p\n", driver_base); std::getchar(); } \ No newline at end of file diff --git a/um-example/map_driver.hpp b/um-example/map_driver.hpp index 3291a01..7e2fcf1 100644 --- a/um-example/map_driver.hpp +++ b/um-example/map_driver.hpp @@ -7,13 +7,14 @@ namespace mapper { enum class mapper_error { - error_success = 0x000, // everything is good! - image_invalid = 0x111, // the driver your trying to map is invalid (are you importing things that arent in ntoskrnl?) - load_error = 0x222, // unable to load signed driver into the kernel (are you running as admin?) - unload_error = 0x333, // unable to unload signed driver from kernel (are all handles to this driver closes?) - piddb_fail = 0x444, // piddb cache clearing failed... (are you using this code below windows 10?) - init_failed = 0x555, // setting up library dependancies failed! - failed_to_create_proc = 0x777 // was unable to create a new process to inject driver into! (RuntimeBroker.exe) + error_success, // everything is good! + image_invalid, // the driver your trying to map is invalid (are you importing things that arent in ntoskrnl?) + load_error, // unable to load signed driver into the kernel (are you running as admin?) + unload_error, // unable to unload signed driver from kernel (are all handles to this driver closes?) + piddb_fail, // piddb cache clearing failed... (are you using this code below windows 10?) + init_failed, // setting up library dependancies failed! + failed_to_create_proc, // was unable to create a new process to inject driver into! (RuntimeBroker.exe) + set_mgr_failure // unable to stop working set manager thread... this thread can cause issues with PTM... }; /// @@ -23,5 +24,5 @@ namespace mapper /// size of the driver buffer /// data to be sent to the entry point of the driver... /// status of the driver being mapped, and base address of the driver... - std::pair map_driver(std::uint8_t* drv_image, std::size_t image_size, void** entry_data); + auto map_driver(std::uint8_t* drv_image, std::size_t image_size, void** entry_data) -> std::pair; } \ No newline at end of file