diff --git a/PSKDM/PSKDM.vcxproj b/PSKDM/PSKDM.vcxproj index 3e5dc91..84e6de3 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 818bb07..44dc5b9 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 8d4388a..2685c00 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.hpp" +#include "vdm_ctx/vdm_ctx.h" #include "vdm/vdm.hpp" #include "set_mgr/set_mgr.hpp" @@ -22,30 +22,13 @@ namespace mapper if (!runtime_broker_pid) return { mapper_error::failed_to_create_proc, nullptr }; - 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 }; + 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); + // 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 5563f91..3291a01 100644 --- a/PSKDM/map_driver.hpp +++ b/PSKDM/map_driver.hpp @@ -7,14 +7,13 @@ namespace mapper { enum class mapper_error { - 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... + 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) }; /// @@ -24,5 +23,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... - auto map_driver(std::uint8_t* drv_image, std::size_t image_size, void** entry_data)->std::pair; + std::pair map_driver(std::uint8_t* drv_image, std::size_t image_size, void** entry_data); } \ No newline at end of file diff --git a/PSKDM/mapper_ctx/mapper_ctx.cpp b/PSKDM/mapper_ctx/mapper_ctx.cpp index d9c12bc..829c204 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->dirbase)); + map_into.set_page(map_into.get_dirbase())); // look for an empty pml4e... for (auto idx = 0u; idx < 256; ++idx) @@ -30,20 +30,18 @@ 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); - while (!map_from->set_pml4e(drv_ppml4e, pml4e{ NULL })) - continue; + map_from.set_pml4e(drv_ppml4e, pml4e{ NULL }); + while (!SwitchToThread()); drv_pml4e.nx = false; drv_pml4e.user_supervisor = false; - // ensure we insert the pml4e... - while (!map_into->write_phys( - reinterpret_cast( - map_into->dirbase) + this->pml4_idx, drv_pml4e)) - continue; + map_into.write_phys(reinterpret_cast( + map_into.get_dirbase()) + this->pml4_idx, drv_pml4e); virt_addr_t new_addr = { reinterpret_cast(drv_alloc) }; new_addr.pml4_index = this->pml4_idx; @@ -52,7 +50,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 @@ -62,11 +60,11 @@ namespace nasa OpenProcess( PROCESS_ALL_ACCESS, FALSE, - map_from->pid + map_from.get_pid() ); if (!process_handle) - return { {}, {} }; + return {}; drv_image.fix_imports([&](const char* module_name, const char* export_name) { @@ -89,7 +87,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; @@ -112,23 +110,15 @@ 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) @@ -139,7 +129,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... @@ -151,7 +141,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... @@ -166,14 +156,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 4f7f2ec..9ed4800 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 1e487f7..12ebd48 100644 --- a/PSKDM/mem_ctx/mem_ctx.cpp +++ b/PSKDM/mem_ctx/mem_ctx.cpp @@ -2,25 +2,20 @@ namespace nasa { - mem_ctx::mem_ctx(vdm::vdm_ctx* v_ctx, std::uint32_t pid) + mem_ctx::mem_ctx(vdm::vdm_ctx& v_ctx, DWORD 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)).present) - { + if (!v_ctx.rkm(current_pml4 + (idx * sizeof pml4e)).value) this->pml4e_index = idx; - break; - } - } // allocate a pdpt this->new_pdpt.second = @@ -36,17 +31,13 @@ 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>(this->dirbase) + - this->pml4e_index, new_pdpt_entries.pml4.second, true); + set_pml4e(reinterpret_cast<::ppml4e>(get_dirbase()) + this->pml4e_index, new_pdpt_entries.pml4.second, true); // make a new pd this->new_pd.second = @@ -63,10 +54,7 @@ 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 = @@ -83,42 +71,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() { - const auto pml4 = - reinterpret_cast( - set_page(dirbase))[pml4e_index] = pml4e{ NULL }; + set_pml4e(reinterpret_cast<::ppml4e>(get_dirbase()) + this->pml4e_index, pml4e{NULL}); + while (!SwitchToThread()); } void* mem_ctx::set_page(void* addr) { - ++pte_index; - if (pte_index > 511) + // table entry change. { - ++pde_index; - pte_index = 0; - } + ++pte_index; + if (pte_index >= 511) + { + ++pde_index; + pte_index = 0; + } - if (pde_index > 511) - { - ++pdpte_index; - pde_index = 0; - } + if (pde_index >= 511) + { + ++pdpte_index; + pde_index = 0; + } - if (pdpte_index > 511) - pdpte_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; @@ -128,6 +116,7 @@ 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; @@ -137,6 +126,7 @@ 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; @@ -155,39 +145,18 @@ 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)); - return reinterpret_cast( - v_ctx.rkm(peproc + 0x28).pfn << 12); + const auto dirbase = + v_ctx.rkm(peproc + 0x28); + + return reinterpret_cast(dirbase.pfn << 12); } bool mem_ctx::hyperspace_entries(pt_entries& entries, void* addr) @@ -232,106 +201,95 @@ namespace nasa return true; } - auto mem_ctx::get_pte(void* addr, bool use_hyperspace) -> std::pair + std::pair mem_ctx::get_pte(void* addr, bool use_hyperspace) { 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 {}; } - bool mem_ctx::set_pte(void* addr, const ::pte& pte, bool use_hyperspace) + void mem_ctx::set_pte(void* addr, const ::pte& pte, bool use_hyperspace) { if (!dirbase || !addr) - return false; + return; if (use_hyperspace) - return v_ctx->wkm( - v_ctx->get_virtual( - reinterpret_cast(addr)), pte); - - return write_phys(addr, pte); + v_ctx->wkm(v_ctx->get_virtual(reinterpret_cast(addr)), pte); + else + write_phys(addr, pte); } - auto mem_ctx::get_pde(void* addr, bool use_hyperspace) -> std::pair + std::pair mem_ctx::get_pde(void* addr, bool use_hyperspace) { 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 {}; } - bool mem_ctx::set_pde(void* addr, const ::pde& pde, bool use_hyperspace) + void mem_ctx::set_pde(void* addr, const ::pde& pde, bool use_hyperspace) { - if (!dirbase || !addr) - return false; + if (!this->dirbase || !addr) + return; if (use_hyperspace) - return v_ctx->wkm( - v_ctx->get_virtual( - reinterpret_cast(addr)), pde); - - return write_phys(addr, pde); + v_ctx->wkm(v_ctx->get_virtual(reinterpret_cast(addr)), pde); + else + write_phys(addr, pde); } - auto mem_ctx::get_pdpte(void* addr, bool use_hyperspace) -> std::pair + std::pair mem_ctx::get_pdpte(void* addr, bool use_hyperspace) { 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 {}; } - bool mem_ctx::set_pdpte(void* addr, const ::pdpte& pdpte, bool use_hyperspace) + void mem_ctx::set_pdpte(void* addr, const ::pdpte& pdpte, bool use_hyperspace) { - if (!dirbase || !addr) - return false; + if (!this->dirbase || !addr) + return; if (use_hyperspace) - return v_ctx->wkm( - v_ctx->get_virtual( - reinterpret_cast(addr)), pdpte); - - return write_phys(addr, pdpte); + v_ctx->wkm(v_ctx->get_virtual(reinterpret_cast(addr)), pdpte); + else + write_phys(addr, pdpte); } - auto mem_ctx::get_pml4e(void* addr, bool use_hyperspace) -> std::pair + std::pair mem_ctx::get_pml4e(void* addr, bool use_hyperspace) { - if (!dirbase || !addr) - return { {}, {} }; + if (!this->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 {}; } - bool mem_ctx::set_pml4e(void* addr, const ::pml4e& pml4e, bool use_hyperspace) + void mem_ctx::set_pml4e(void* addr, const ::pml4e& pml4e, bool use_hyperspace) { - if (!dirbase || !addr) - return false; + if (!this->dirbase || !addr) + return; if (use_hyperspace) - return v_ctx->wkm( - v_ctx->get_virtual( - reinterpret_cast(addr)), pml4e); - - return write_phys(addr, pml4e); + v_ctx->wkm(v_ctx->get_virtual(reinterpret_cast(addr)), pml4e); + else + write_phys(addr, pml4e); } - auto mem_ctx::read_virtual(void* buffer, void* addr, std::size_t size) -> std::pair + std::pair mem_ctx::read_virtual(void* buffer, void* addr, std::size_t size) { if (!buffer || !addr || !size || !dirbase) return {}; @@ -373,7 +331,7 @@ namespace nasa } } - auto mem_ctx::write_virtual(void* buffer, void* addr, std::size_t size) -> std::pair + std::pair mem_ctx::write_virtual(void* buffer, void* addr, std::size_t size) { if (!buffer || !addr || !size || !dirbase) return {}; @@ -415,10 +373,10 @@ namespace nasa } } - bool mem_ctx::read_phys(void* buffer, void* addr, std::size_t size) + void mem_ctx::read_phys(void* buffer, void* addr, std::size_t size) { if (!buffer || !addr || !size) - return false; + return; const auto temp_page = set_page(addr); __try @@ -426,16 +384,13 @@ namespace nasa memcpy(buffer, temp_page, size); } __except (EXCEPTION_EXECUTE_HANDLER) - { - return false; - } - return true; + {} } - bool mem_ctx::write_phys(void* buffer, void* addr, std::size_t size) + void mem_ctx::write_phys(void* buffer, void* addr, std::size_t size) { if (!buffer || !addr || !size) - return false; + return; const auto temp_page = set_page(addr); __try @@ -443,15 +398,12 @@ 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 || !dirbase) + if (!addr || !this->dirbase) return {}; const virt_addr_t virt_addr{ addr }; @@ -495,4 +447,37 @@ 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 d0f555f..da40df2 100644 --- a/PSKDM/mem_ctx/mem_ctx.hpp +++ b/PSKDM/mem_ctx/mem_ctx.hpp @@ -1,33 +1,36 @@ #pragma once #include "../util/nt.hpp" -#include "../vdm_ctx/vdm_ctx.hpp" +#include "../vdm_ctx/vdm_ctx.h" namespace nasa { class mem_ctx { + friend class mapper_ctx; public: - explicit mem_ctx(vdm::vdm_ctx* v_ctx, std::uint32_t pid = GetCurrentProcessId()); + explicit mem_ctx(vdm::vdm_ctx& v_ctx, DWORD pid = GetCurrentProcessId()); ~mem_ctx(); - 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_pte(void* addr, bool use_hyperspace = false); + void set_pte(void* addr, const ::pte& pte, 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_pde(void* addr, bool use_hyperspace = false); + void set_pde(void* addr, const ::pde& pde, 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_pdpte(void* addr, bool use_hyperspace = false); + void set_pdpte(void* addr, const ::pdpte& pdpte, bool use_hyperspace = false); - auto get_pml4e(void* addr, bool use_hyperspace = false) -> std::pair; - bool set_pml4e(void* addr, const ::pml4e& pml4e, 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; static void* get_dirbase(vdm::vdm_ctx& v_ctx, DWORD pid); - bool read_phys(void* buffer, void* addr, std::size_t size); - bool write_phys(void* buffer, void* addr, std::size_t size); + void read_phys(void* buffer, void* addr, std::size_t size); + void write_phys(void* buffer, void* addr, std::size_t size); template - __forceinline T read_phys(void* addr) + T read_phys(void* addr) { T buffer; read_phys((void*)&buffer, addr, sizeof(T)); @@ -35,13 +38,13 @@ namespace nasa } template - __forceinline bool write_phys(void* addr, const T& data) + void write_phys(void* addr, const T& data) { - return write_phys((void*)&data, addr, sizeof(T)); + write_phys((void*)&data, addr, sizeof(T)); } - 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; + std::pair read_virtual(void* buffer, void* addr, std::size_t size); + std::pair write_virtual(void* buffer, void* addr, std::size_t size); template __forceinline T read_virtual(void* addr) @@ -58,15 +61,19 @@ 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; - unsigned pid; + 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); void* dirbase; vdm::vdm_ctx* v_ctx; - private: std::uint16_t pml4e_index, pdpte_index, pde_index, @@ -76,5 +83,6 @@ 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 5b99746..beea970 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.hpp" +#include "../vdm_ctx/vdm_ctx.h" 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 9061160..52581c6 100644 --- a/PSKDM/vdm_ctx/vdm_ctx.cpp +++ b/PSKDM/vdm_ctx/vdm_ctx.cpp @@ -1,13 +1,10 @@ -#include "vdm_ctx.hpp" +#include "vdm_ctx.h" namespace vdm { - vdm_ctx::vdm_ctx(read_phys_t& read_func, write_phys_t& write_func) - : - read_phys(read_func), - write_phys(write_func) + vdm_ctx::vdm_ctx() { - // already found the syscall's physical page... + // if we already found the syscall's physical page... if (vdm::syscall_address.load()) return; @@ -37,37 +34,9 @@ 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, @@ -80,7 +49,7 @@ namespace vdm if (vdm::syscall_address.load()) break; - if (!read_phys(reinterpret_cast(address + page), page_data, PAGE_4KB)) + if (!vdm::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 @@ -91,6 +60,7 @@ namespace vdm reinterpret_cast( address + page + nt_page_offset)); } + VirtualFree(page_data, PAGE_4KB, MEM_DECOMMIT); } @@ -111,11 +81,11 @@ namespace vdm std::uint8_t orig_bytes[sizeof shellcode]; // save original bytes and install shellcode... - read_phys(syscall_addr, orig_bytes, sizeof orig_bytes); - write_phys(syscall_addr, shellcode, sizeof shellcode); + vdm::read_phys(syscall_addr, orig_bytes, sizeof orig_bytes); + vdm::write_phys(syscall_addr, shellcode, sizeof shellcode); auto result = reinterpret_cast(proc)(); - write_phys(syscall_addr, orig_bytes, sizeof orig_bytes); + vdm::write_phys(syscall_addr, orig_bytes, sizeof orig_bytes); syscall_mutex.unlock(); return result == STATUS_SUCCESS; } diff --git a/PSKDM/vdm_ctx/vdm_ctx.hpp b/PSKDM/vdm_ctx/vdm_ctx.h similarity index 70% rename from PSKDM/vdm_ctx/vdm_ctx.hpp rename to PSKDM/vdm_ctx/vdm_ctx.h index 84282c7..7396687 100644 --- a/PSKDM/vdm_ctx/vdm_ctx.hpp +++ b/PSKDM/vdm_ctx/vdm_ctx.h @@ -5,35 +5,28 @@ #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: - 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); - + vdm_ctx(); 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 @@ -53,12 +46,12 @@ namespace vdm std::uint8_t orig_bytes[sizeof jmp_code]; *reinterpret_cast(jmp_code + 6) = addr; - read_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes); + vdm::read_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes); // execute hook... - write_phys(vdm::syscall_address.load(), jmp_code, sizeof jmp_code); + vdm::write_phys(vdm::syscall_address.load(), jmp_code, sizeof jmp_code); auto result = reinterpret_cast(proc)(args ...); - write_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes); + vdm::write_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes); syscall_mutex.unlock(); return result; @@ -67,15 +60,35 @@ 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; - rkm((void*)&buffer, (void*)addr, sizeof T); + this->syscall( + ntoskrnl_memcpy, &buffer, (void*)addr, sizeof T); + return buffer; } template - __forceinline auto wkm(std::uintptr_t addr, const T& value) -> bool + __forceinline void wkm(std::uintptr_t addr, const T& value) { - return wkm((void*)addr, (void*)&value, sizeof T); + 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); } __forceinline auto get_peprocess(std::uint32_t pid) -> PEPROCESS @@ -93,23 +106,8 @@ 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 4d0e6a1..bf5f52e 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 0cbbebb..601130b 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 // you can pass your structure here... + nullptr ); - std::printf("[+] driver mapping result -> 0x%x (0 == STATUS_SUCCESS)\n", result); + std::printf("[+] driver mapping result -> 0x%x\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 7e2fcf1..3291a01 100644 --- a/um-example/map_driver.hpp +++ b/um-example/map_driver.hpp @@ -7,14 +7,13 @@ namespace mapper { enum class mapper_error { - 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... + 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) }; /// @@ -24,5 +23,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... - auto map_driver(std::uint8_t* drv_image, std::size_t image_size, void** entry_data) -> std::pair; + std::pair map_driver(std::uint8_t* drv_image, std::size_t image_size, void** entry_data); } \ No newline at end of file