Physmeme, Driver Mapper
To begin I would like to credit those who helped me complete this project.
- Buck, for helping me learn everything about paging tables.
- Can1357, for helping me find the correct physical page.
- Ch40zz, for helping me fix issues that I couldn't have ever fixed.
Without the help of these three people this project wouldn't have gone anywhere.
What is Physmeme?
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 a vulnerable driver into the project. 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 does Physmeme work?
Physmeme works similarly to kdmapper at a higher level. Changing the bytes of 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 syscall. This can be done by doing a simple calculation. Given the relative virtual address of an exported function in ntoskrnl.exe you can modulus 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.
#define PAGE_SIZE 0x1000;
auto page_offset = page_rva % PAGE_SIZE;
This gives us the offset into the page in which the syscall is located. Now it's just a matter of mapping and comparing each physical page of memory. To speed things up I create a thread for each physical memory range and map 2mb at a time, this reduces the heavy overhead of making an ioctl request to the driver for every single physical page.
How can I use Physmeme?
Find a driver that exposes MmMapIoSpace/ZwMapViewOfSection to user mode and then code four functions located inside of “physmeme.hpp”.
- load_drv, to load the driver, this function mustn't take any parameters and return only a handle to the driver.
- unload_drv, to unload the driver, this function takes no parameters.
- map_phys, to map physical memory into the process, this function must take exactly two parameters and return the virtual base address of the mapping. You can treat this function like MmMapIoSpace without the cache type since that will be handled by your driver.
- unmap_phys, this function must take two parameters, the virtual base address of the mapping and the size of the mapping
That is all you need to make physmeme work for your driver. Physmeme should support all versions of windows down to windows vista. This is because I am hooking a function exported by ntoskrnl (“NtTraceControl”). You can change this however you want.
The risk of crashing your system is only slightly greater than kdmapper since I am hooking a function protected by patch guard. This shouldn't matter since I only hook the function for fractions of a second at a time. Another thing to note is, other threads can and may call into the same syscall you are currently hooking thus causing unknown behavior.
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.