Physmeme - Windows Unsigned Kernel Driver Mapper
Download link: physmeme
Introduction
Physmeme is a driver mapper that works with any form of read and write to physical memory. It is highly modular code that allows a reverse engineer to easily integrate their own vulnerable driver. If you are able to read and write to physical memory you can now map an unsigned driver into your kernel just by coding four functions.
How it works
Physmeme works similarly to kdmapper at a higher level. Inline hooking a syscall and then calling the syscall we are able to call any function in the kernel. The only issue is finding the physical page of the desired syscall. This can be done by doing a simple calculation. Given the relative virtual address of an exported function in ntoskrnl.exe you can modulo the virtual address by the size of a page. Usually pages are 0x1000 (4096) bytes, but they can be 2mb or 1gb on some systems.
On the left you can see the relative virtual address from the base address of ntoskrnl.exe to the function we are interested in. On the image you can see the simple calculation done to get the page offset. This page offset is used later in the mapper to compare bytes with physical memory. Now that we know the page offset, we can start mapping every single physical page. Instead of doing this one page at a time, mapping 2mb at a time can increase the speed dramatically, this is because IOCTL is pretty slow. Ontop of mapping 2mb at a time, creating a thread for each physical memory range will lower the time to find the correct physical page to under a second.
//--- for each physical memory range, make a thread to search it
std::vector<std::thread> search_threads;
for (const auto& ranges : util::pmem_ranges)
search_threads.emplace_back(std::thread(
&kernel_ctx::map_syscall,
this,
ranges.first,
ranges.second
));
for (std::thread& search_thread : search_threads)
search_thread.join();
Once the physical page of the syscall is found and mapped into our process, we can install inline hooks into it and then call into the function. This introduces a few risks ranging from patch guard to race conditions. Nonetheless the probability of such things happening are not high enough to be problematic since bytes are restored within a few microseconds/nanoseconds.
template <class T, class... Ts>
std::invoke_result_t<T, Ts...> syscall(void* addr, Ts ... args) const
{
static const auto proc =
GetProcAddress(
syscall_hook.second.data(),
syscall_hook.first.data()
);
hook::make_hook(psyscall_func, addr);
auto result = reinterpret_cast<T>(proc)(args ...);
hook::remove(psyscall_func);
return result;
}
With this function you can syscall into any function in the kernel.
Usage
Why use physmeme over kdmapper or drvmapper you may be asking. Physmeme is highly modular code that is easy to work with and allows the user to integrate their own vulnerable driver in a matter of minutes. There are only four functions that are required to be programmed to use physmeme.
Two functions for loading and unloading the driver.
*
load_drv, loads the driver and returns a handle to the driver.*
unload_drv, closes the handle to the driver and then unloads it.
Two functions for handling physical memory.
*
map_phys, maps physical memory into the address space of the current process.*
unmap_phys, unmaps physical memory that has been mapped into the current process.
Conclusion
Physmeme is a highly modular, well rounded mapper that can be used to systematically exploit thousands of drivers both known and unknown. The ability to read/write arbitrary physical memory is very wide spread. Anything from a cpu fan speed reader to a bios flashing utility can now be easily used to map a driver.
Credits
- can1357 - Ch40zz