#include "mapper_ctx.hpp" namespace physmeme { mapper_ctx::mapper_ctx ( physmeme::mem_ctx& map_into, physmeme::mem_ctx& map_from ) : map_into(map_into), map_from(map_from) {} std::pair mapper_ctx::map(std::vector& raw_image) { const auto [drv_alloc, drv_entry_addr] = allocate_driver(raw_image); auto [drv_ppml4e, drv_pml4e] = map_from.get_pml4e(drv_alloc); // // make the pde & pte's containing the driver user supervisor = false... // make_kernel_access(drv_alloc); // // removes the kernel memory from runtimebroker.exe // map_from.set_pml4e(drv_ppml4e, pml4e{ NULL }); // // set new pml4e into specific process. // drv_pml4e.nx = false; drv_pml4e.user_supervisor = false; map_into.write_phys ( reinterpret_cast(map_into.get_dirbase()) + PML4_MAP_INDEX, drv_pml4e ); virt_addr_t new_addr = { reinterpret_cast(drv_alloc) }; new_addr.pml4_index = PML4_MAP_INDEX; return { new_addr.value, drv_entry_addr }; } bool mapper_ctx::call_entry(void* drv_entry, void** hook_handler) const { const auto result = map_into.k_ctx->syscall(drv_entry, hook_handler); return !result; } std::pair mapper_ctx::allocate_driver(std::vector& raw_image) { const auto _get_module = [&](std::string_view name) { return util::get_module_base(name.data()); }; const auto _get_export_name = [&](const char* base, const char* name) { return reinterpret_cast(util::get_module_export(base, name)); }; physmeme::pe_image drv_image(raw_image); const auto process_handle = OpenProcess( PROCESS_ALL_ACCESS, FALSE, map_from.get_pid() ); if (!process_handle) return {}; drv_image.fix_imports(_get_module, _get_export_name); drv_image.map(); const auto drv_alloc_base = reinterpret_cast( direct::alloc_virtual_memory( process_handle, drv_image.size(), PAGE_READWRITE )); if (!drv_alloc_base) return {}; virt_addr_t new_addr = { reinterpret_cast(drv_alloc_base) }; new_addr.pml4_index = PML4_MAP_INDEX; drv_image.relocate(reinterpret_cast(new_addr.value)); // // dont write nt headers... // const bool result = direct::write_virtual_memory ( process_handle, reinterpret_cast((std::uint64_t)drv_alloc_base + drv_image.header_size()), reinterpret_cast((std::uint64_t)drv_image.data() + drv_image.header_size()), drv_image.size() - drv_image.header_size() ); if (!CloseHandle(process_handle)) return { {}, {} }; return { reinterpret_cast(drv_alloc_base), 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)); // set pdptes to CPL0 access only and executable... for (auto pdpt_idx = 0u; pdpt_idx < 512; ++pdpt_idx) { if (pdpt_mapping[pdpt_idx].present) { pdpt_mapping[pdpt_idx].user_supervisor = false; pdpt_mapping[pdpt_idx].nx = false; auto pd_mapping = reinterpret_cast( map_from.set_page(reinterpret_cast( pdpt_mapping[pdpt_idx].pfn << 12))); // set pdes to CPL0 access only and executable... for (auto pd_idx = 0u; pd_idx < 512; ++pd_idx) { if (pd_mapping[pd_idx].present) { pd_mapping[pd_idx].user_supervisor = false; pd_mapping[pd_idx].nx = false; auto pt_mapping = reinterpret_cast( map_from.set_page(reinterpret_cast( pd_mapping[pd_idx].pfn << 12))); // set ptes to CPL0 access only and executable... for (auto pt_idx = 0u; pt_idx < 512; ++pt_idx) { if (pt_mapping[pt_idx].present) { pt_mapping[pt_idx].user_supervisor = false; pt_mapping[pt_idx].nx = false; } } // set page back to pd... pd_mapping = 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)); } } } }