From 5d8fb3f10d1b2a9dca6ff3f6f9cb5862a803de41 Mon Sep 17 00:00:00 2001 From: xerox Date: Sun, 19 Apr 2020 04:56:53 -0700 Subject: [PATCH] V1.0 baby! :) --- demo/hello-world.sys | Bin 0 -> 6272 bytes demo/phymem64.sys | Bin 0 -> 19240 bytes demo/physmeme.exe | Bin 0 -> 100352 bytes demo/pmdll64.dll | Bin 0 -> 117760 bytes physmeme.sln | 31 ++++ physmeme/drv_image/drv_image.cpp | 227 +++++++++++++++++++++++++++++ physmeme/drv_image/drv_image.h | 73 ++++++++++ physmeme/kernel_ctx/kernel_ctx.cpp | 193 ++++++++++++++++++++++++ physmeme/kernel_ctx/kernel_ctx.h | 103 +++++++++++++ physmeme/main.cpp | 73 ++++++++++ physmeme/physmeme.vcxproj | 175 ++++++++++++++++++++++ physmeme/physmeme.vcxproj.filters | 62 ++++++++ physmeme/physmeme.vcxproj.user | 19 +++ physmeme/physmeme/physmeme.hpp | 104 +++++++++++++ physmeme/util/hook.hpp | 190 ++++++++++++++++++++++++ physmeme/util/nt.hpp | 93 ++++++++++++ physmeme/util/util.hpp | 155 ++++++++++++++++++++ 17 files changed, 1498 insertions(+) create mode 100644 demo/hello-world.sys create mode 100644 demo/phymem64.sys create mode 100644 demo/physmeme.exe create mode 100644 demo/pmdll64.dll create mode 100644 physmeme.sln create mode 100644 physmeme/drv_image/drv_image.cpp create mode 100644 physmeme/drv_image/drv_image.h create mode 100644 physmeme/kernel_ctx/kernel_ctx.cpp create mode 100644 physmeme/kernel_ctx/kernel_ctx.h create mode 100644 physmeme/main.cpp create mode 100644 physmeme/physmeme.vcxproj create mode 100644 physmeme/physmeme.vcxproj.filters create mode 100644 physmeme/physmeme.vcxproj.user create mode 100644 physmeme/physmeme/physmeme.hpp create mode 100644 physmeme/util/hook.hpp create mode 100644 physmeme/util/nt.hpp create mode 100644 physmeme/util/util.hpp diff --git a/demo/hello-world.sys b/demo/hello-world.sys new file mode 100644 index 0000000000000000000000000000000000000000..7f2301f7e9e730af66ed0935ce4edb0ce04850fe GIT binary patch literal 6272 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 literal 0 HcmV?d00001 diff --git a/demo/phymem64.sys b/demo/phymem64.sys new file mode 100644 index 0000000000000000000000000000000000000000..572668e3d97b213dc14d5f7c771279abffeb8f9f GIT binary patch literal 19240 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 literal 0 HcmV?d00001 diff --git a/demo/physmeme.exe b/demo/physmeme.exe new file mode 100644 index 0000000000000000000000000000000000000000..924a32b6c8b8f282b30e2cb105fc6129ca919f39 GIT binary patch literal 100352 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%0A>O;>>gq%DOiOr)_Q9_RR) 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 Zu_*^-fi-I}WBL90T>`&L;QuEH{6Fp~vpWC) literal 0 HcmV?d00001 diff --git a/physmeme.sln b/physmeme.sln new file mode 100644 index 0000000..87974c8 --- /dev/null +++ b/physmeme.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29613.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "physmeme", "physmeme\physmeme.vcxproj", "{6578B958-DD53-4BE0-8011-009563919E73}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6578B958-DD53-4BE0-8011-009563919E73}.Debug|x64.ActiveCfg = Debug|x64 + {6578B958-DD53-4BE0-8011-009563919E73}.Debug|x64.Build.0 = Debug|x64 + {6578B958-DD53-4BE0-8011-009563919E73}.Debug|x86.ActiveCfg = Debug|Win32 + {6578B958-DD53-4BE0-8011-009563919E73}.Debug|x86.Build.0 = Debug|Win32 + {6578B958-DD53-4BE0-8011-009563919E73}.Release|x64.ActiveCfg = Release|x64 + {6578B958-DD53-4BE0-8011-009563919E73}.Release|x64.Build.0 = Release|x64 + {6578B958-DD53-4BE0-8011-009563919E73}.Release|x86.ActiveCfg = Release|Win32 + {6578B958-DD53-4BE0-8011-009563919E73}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FFE13E08-F538-4509-A3A3-7B16A9EEA923} + EndGlobalSection +EndGlobal diff --git a/physmeme/drv_image/drv_image.cpp b/physmeme/drv_image/drv_image.cpp new file mode 100644 index 0000000..26aacdf --- /dev/null +++ b/physmeme/drv_image/drv_image.cpp @@ -0,0 +1,227 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +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 + +namespace physmeme +{ + drv_image::drv_image(std::vector image) : m_image(std::move(image)) + { + 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); + assert(m_nt_headers->Signature == IMAGE_NT_SIGNATURE); + assert(m_nt_headers->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC); + m_section_header = reinterpret_cast((uintptr_t)(&m_nt_headers->OptionalHeader) + m_nt_headers->FileHeader.SizeOfOptionalHeader); + } + + size_t drv_image::size() const + { + return m_nt_headers->OptionalHeader.SizeOfImage; + } + + uintptr_t drv_image::entry_point() const + { + return m_nt_headers->OptionalHeader.AddressOfEntryPoint; + } + + void drv_image::map() + { + m_image_mapped.clear(); + m_image_mapped.resize(m_nt_headers->OptionalHeader.SizeOfImage); + std::copy_n(m_image.begin(), m_nt_headers->OptionalHeader.SizeOfHeaders, m_image_mapped.begin()); + + for (size_t i = 0; i < m_nt_headers->FileHeader.NumberOfSections; ++i) + { + const auto& section = m_section_header[i]; + 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); + } + } + + bool drv_image::process_relocation(uintptr_t image_base_delta, uint16_t data, uint8_t* relocation_base) + { +#define IMR_RELOFFSET(x) (x & 0xFFF) + + switch (data >> 12 & 0xF) + { + case IMAGE_REL_BASED_HIGH: + { + const auto raw_address = reinterpret_cast(relocation_base + IMR_RELOFFSET(data)); + *raw_address += static_cast(HIWORD(image_base_delta)); + break; + } + case IMAGE_REL_BASED_LOW: + { + const auto raw_address = reinterpret_cast(relocation_base + IMR_RELOFFSET(data)); + *raw_address += static_cast(LOWORD(image_base_delta)); + break; + } + case IMAGE_REL_BASED_HIGHLOW: + { + const auto raw_address = reinterpret_cast(relocation_base + IMR_RELOFFSET(data)); + *raw_address += static_cast(image_base_delta); + break; + } + case IMAGE_REL_BASED_DIR64: + { + auto UNALIGNED raw_address = reinterpret_cast(relocation_base + IMR_RELOFFSET(data)); + *raw_address += image_base_delta; + break; + } + case IMAGE_REL_BASED_ABSOLUTE: // No action required + case IMAGE_REL_BASED_HIGHADJ: // no action required + { + break; + } + default: + { + throw std::runtime_error("gay relocation!"); + return false; + } + + } +#undef IMR_RELOFFSET + + return true; + } + + + void drv_image::relocate(uintptr_t base) const + { + if (m_nt_headers->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) + return; + + 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 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 + const bool doRelocations = image_base_delta != 0 && relocation_size > 0; + + if (!doRelocations) + { + printf("no relocations needed\n"); + return; + } + + assert(relocation_directory != nullptr); + + void* relocation_end = reinterpret_cast(relocation_directory) + relocation_size; + + while (relocation_directory < relocation_end) + { + auto relocation_base = ::ImageRvaToVa(nt_headers, (void*)m_image_mapped.data(), relocation_directory->VirtualAddress, nullptr); + + auto num_relocs = (relocation_directory->SizeOfBlock - 8) >> 1; + + auto relocation_data = reinterpret_cast(relocation_directory + 1); + + for (unsigned long i = 0; i < num_relocs; ++i, ++relocation_data) + { + if (process_relocation(image_base_delta, *relocation_data, (uint8_t*)relocation_base) == FALSE) + { + printf("failed to relocate!"); + return; + } + } + + relocation_directory = reinterpret_cast(relocation_data); + } + + } + + template + __forceinline T* ptr_add(void* base, uintptr_t offset) + { + return (T*)(uintptr_t)base + offset; + } + + void drv_image::fix_imports(const std::function get_module, const std::function get_function) + { + ULONG size; + auto import_descriptors = static_cast(::ImageDirectoryEntryToData(m_image.data(), FALSE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size)); + + if (import_descriptors == nullptr) + { + printf("no imports!\n"); + return; + } + + for (; import_descriptors->Name; import_descriptors++) + { + IMAGE_THUNK_DATA* image_thunk_data; + + const auto module_name = get_rva(import_descriptors->Name); + const auto module_base = get_module(module_name); + assert(module_base != 0); + + printf("processing module: %s [0x%I64X]\n", module_name, module_base); + + if (import_descriptors->OriginalFirstThunk) + image_thunk_data = get_rva(import_descriptors->OriginalFirstThunk); + else + image_thunk_data = get_rva(import_descriptors->FirstThunk); + auto image_func_data = get_rva(import_descriptors->FirstThunk); + + assert(image_thunk_data != nullptr); + assert(image_func_data != nullptr); + + for (; image_thunk_data->u1.AddressOfData; image_thunk_data++, image_func_data++) + { + uintptr_t function_address; + const auto ordinal = (image_thunk_data->u1.Ordinal & IMAGE_ORDINAL_FLAG64) != 0; + 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); + assert(function_address != 0); + image_func_data->u1.Function = function_address; + } + } + } + + void* drv_image::data() + { + return m_image_mapped.data(); + } + + size_t drv_image::header_size() + { + return m_nt_headers->OptionalHeader.SizeOfHeaders; + } +} \ No newline at end of file diff --git a/physmeme/drv_image/drv_image.h b/physmeme/drv_image/drv_image.h new file mode 100644 index 0000000..45199fe --- /dev/null +++ b/physmeme/drv_image/drv_image.h @@ -0,0 +1,73 @@ +/* +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +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 !!!!!!!!!!!!!!!!!!!!!!!!!!!!! +*/ + + +#pragma once +#include +#define WIN32_NO_STATUS +#include +#include +#undef WIN32_NO_STATUS +#include + +#include +#include +#include + +#pragma comment(lib, "Dbghelp.lib") +namespace physmeme +{ + class drv_image + { + std::vector m_image; + std::vector m_image_mapped; + PIMAGE_DOS_HEADER m_dos_header = nullptr; + PIMAGE_NT_HEADERS64 m_nt_headers = nullptr; + PIMAGE_SECTION_HEADER m_section_header = nullptr; + + public: + 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; + + template + __forceinline T* get_rva(const unsigned long offset) + { + 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* data(); + size_t header_size(); + }; +} \ No newline at end of file diff --git a/physmeme/kernel_ctx/kernel_ctx.cpp b/physmeme/kernel_ctx/kernel_ctx.cpp new file mode 100644 index 0000000..008d375 --- /dev/null +++ b/physmeme/kernel_ctx/kernel_ctx.cpp @@ -0,0 +1,193 @@ +#include "kernel_ctx.h" + +namespace physmeme +{ + /* + Author: xerox + Date: 4/19/2020 + */ + kernel_ctx::kernel_ctx() + : psyscall_func(NULL), ntoskrnl_buffer(NULL) + { + nt_rva = reinterpret_cast( + util::get_module_export( + "ntoskrnl.exe", + syscall_hook.first.data(), + true + )); + + nt_page_offset = nt_rva % 0x1000; + ntoskrnl_buffer = reinterpret_cast(LoadLibraryA("C:\\Windows\\System32\\ntoskrnl.exe")); + +#if PHYSMEME_DEBUGGING + std::cout << "[+] page offset of " << syscall_hook.first << " is: " << std::hex << nt_page_offset << std::endl; +#endif + + std::vector search_threads; + //--- for each physical memory range, make a thread to search it + for (auto ranges : 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(); + +#if PHYSMEME_DEBUGGING + std::cout << "[+] psyscall_func: " << std::hex << std::showbase << psyscall_func.load() << std::endl; +#endif + } + + /* + 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 + if (begin + end <= 0x1000 * 512) + { + auto page_va = physmeme::map_phys(begin + nt_page_offset, end); + if (page_va) + { + // 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 (!memcmp(reinterpret_cast(page), ntoskrnl_buffer + nt_rva, 32)) + { + psyscall_func.store((void*)page); + return; + } + physmeme::unmap_phys(page_va, end); + } + } + else // else the range is bigger then 2mb + { + auto remainder = (begin + end) % (0x1000 * 512); + + // loop over 2m chunks + for (auto range = begin; range < begin + end; range += 0x1000 * 512) + { + auto page_va = physmeme::map_phys(range + nt_page_offset, 0x1000 * 512); + if (page_va) + { + // loop every page of 2mbs (512) + for (auto page = page_va; page < page_va + 0x1000 * 512; page += 0x1000) + { + if (!memcmp(reinterpret_cast(page), ntoskrnl_buffer + nt_rva, 32)) + { + psyscall_func.store((void*)page); + return; + } + } + physmeme::unmap_phys(page_va, 0x1000 * 512); + } + } + + // map the remainder and check each page of it + auto page_va = physmeme::map_phys(begin + end - remainder + nt_page_offset, remainder); + if (page_va) + { + for (auto page = page_va; page < page_va + remainder; page += 0x1000) + { + if (!memcmp(reinterpret_cast(page), ntoskrnl_buffer + nt_rva, 32)) + { + psyscall_func.store((void*)page); + return; + } + } + physmeme::unmap_phys(page_va, remainder); + } + } + } + + /* + 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 = + util::get_module_export( + "ntoskrnl.exe", + "ExAllocatePool" + ); + if (ex_alloc_pool) + return syscall(ex_alloc_pool, pool_type, size); + return NULL; + } + + /* + Author: xerox + Date: 4/19/2020 + + 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 = + util::get_module_export( + "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 + + read kernel memory + */ + void kernel_ctx::read_kernel(std::uintptr_t addr, void* buffer, std::size_t size) + { + size_t amount_copied; + static const auto mm_copy_memory = + util::get_module_export( + "ntoskrnl.exe", + "MmCopyMemory" + ); + 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 + + 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) + { + size_t amount_copied; + static const auto mm_copy_memory = + util::get_module_export( + "ntoskrnl.exe", + "MmCopyMemory" + ); + if (mm_copy_memory) + syscall( + mm_copy_memory, + reinterpret_cast(addr), + MM_COPY_ADDRESS{ buffer }, + size, + MM_COPY_MEMORY_VIRTUAL, + &amount_copied + ); + } +} \ No newline at end of file diff --git a/physmeme/kernel_ctx/kernel_ctx.h b/physmeme/kernel_ctx/kernel_ctx.h new file mode 100644 index 0000000..16ee891 --- /dev/null +++ b/physmeme/kernel_ctx/kernel_ctx.h @@ -0,0 +1,103 @@ +#pragma once +#include +#include +#include +#include +#include + +#include "../util/util.hpp" +#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 +{ + class kernel_ctx + { + public: + kernel_ctx(); + void* allocate_pool(std::size_t size, POOL_TYPE pool_type = NonPagedPool); + 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); + + template + T read_kernel(std::uintptr_t addr) + { + if (!addr) + return {}; + T buffer; + read_kernel(addr, &buffer, sizeof(T)); + return buffer; + } + + template + void write_kernel(std::uintptr_t addr, const T& data) + { + if (!addr) + return {}; + write_kernel(addr, &data, sizeof(T)); + } + + // + // use this to call any function in the kernel + // + template + PVOID syscall(void* addr, Ts ... args) + { + auto proc = GetProcAddress(GetModuleHandleA("ntdll.dll"), syscall_hook.first.data()); + if (!proc || !psyscall_func || !addr) + return reinterpret_cast(STATUS_INVALID_PARAMETER); + + hook::make_hook(psyscall_func, addr); + PVOID result = reinterpret_cast(reinterpret_cast(proc)(args ...)); + hook::remove(psyscall_func); + return result; + } + + private: + + // + // 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 = { "NtTraceControl", "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 new file mode 100644 index 0000000..fa1dde4 --- /dev/null +++ b/physmeme/main.cpp @@ -0,0 +1,73 @@ +#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 < 1) + { + std::cout << "[-] invalid use, please provide a path to a driver" << std::endl; + return -1; + } + + std::vector drv_buffer; + util::open_binary_file(argv[1], drv_buffer); + + physmeme::drv_image image(drv_buffer); + physmeme::kernel_ctx ctx; + + // + // lambdas used for fixing driver 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)); + }; + + // + // 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; + image.map(); + std::cout << "[+] sections mapped in memory" << std::endl; + image.relocate(pool_base); + std::cout << "[+] relocations fixed" << std::endl; + + // + // 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()); + + // + // call driver entry and pass in base address and size of the driver. + // + auto entry_point = pool_base + image.entry_point(); + auto size = image.size(); + + auto result = ctx.syscall(reinterpret_cast(entry_point), pool_base, image.size()); + std::cout << "[+] driver entry returned: " << std::hex << result << std::endl; + physmeme::unload_drv(); + + std::cout << "[=] press enter to close" << std::endl; + std::cin.get(); +} \ No newline at end of file diff --git a/physmeme/physmeme.vcxproj b/physmeme/physmeme.vcxproj new file mode 100644 index 0000000..430b100 --- /dev/null +++ b/physmeme/physmeme.vcxproj @@ -0,0 +1,175 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {6578B958-DD53-4BE0-8011-009563919E73} + Win32Proj + physmeme + 10.0 + + + + Application + true + v142 + MultiByte + false + + + Application + false + v142 + true + MultiByte + false + + + Application + true + v142 + MultiByte + false + + + Application + false + v142 + true + MultiByte + false + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + true + _CRT_SECURE_NO_WARNINGS + true + stdcpp17 + + + Console + true + + + + + + + Level3 + true + _CRT_SECURE_NO_WARNINGS + true + stdcpp17 + + + Console + true + + + + + + + Level3 + true + true + true + _CRT_SECURE_NO_WARNINGS + true + stdcpp17 + Disabled + + + Console + true + true + true + + + + + + + Level3 + true + true + true + _CRT_SECURE_NO_WARNINGS + true + stdcpp17 + Disabled + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/physmeme/physmeme.vcxproj.filters b/physmeme/physmeme.vcxproj.filters new file mode 100644 index 0000000..abf7894 --- /dev/null +++ b/physmeme/physmeme.vcxproj.filters @@ -0,0 +1,62 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {040c8387-476c-4aa5-aa2a-ca30465b41bd} + + + {642c89a0-7989-4f5c-ae5a-f71e697abe16} + + + {c4aa2f98-70d4-418e-894d-4e1975e2bad2} + + + {4fd2f117-66bb-4f75-af5b-b7e041a4dc48} + + + {161b3714-a6cd-4b7b-a1f1-9b90b1f84aca} + + + {ed9d2db3-acef-42c0-880f-7f95dcca819d} + + + + + Source Files + + + Source Files\kernel_ctx + + + Source Files\drv_image + + + + + Header Files\kernel_ctx + + + Header Files\util + + + Header Files\util + + + Header Files\util + + + Header Files\drv_image + + + Header Files\physmeme + + + \ No newline at end of file diff --git a/physmeme/physmeme.vcxproj.user b/physmeme/physmeme.vcxproj.user new file mode 100644 index 0000000..78bd717 --- /dev/null +++ b/physmeme/physmeme.vcxproj.user @@ -0,0 +1,19 @@ + + + + C:\Users\interesting\Desktop\hello-world.sys + WindowsLocalDebugger + + + C:\Users\interesting\Desktop\hello-world.sys + WindowsLocalDebugger + + + C:\Users\interesting\Desktop\hello-world.sys + WindowsLocalDebugger + + + C:\Users\interesting\Desktop\hello-world.sys + WindowsLocalDebugger + + \ No newline at end of file diff --git a/physmeme/physmeme/physmeme.hpp b/physmeme/physmeme/physmeme.hpp new file mode 100644 index 0000000..9b80ce4 --- /dev/null +++ b/physmeme/physmeme/physmeme.hpp @@ -0,0 +1,104 @@ +#pragma once +#include +#include +#include +#include + +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. + */ + 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)) + 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. + */ + static 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. + */ + static 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. + */ + static 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/physmeme/util/hook.hpp b/physmeme/util/hook.hpp new file mode 100644 index 0000000..1004d9f --- /dev/null +++ b/physmeme/util/hook.hpp @@ -0,0 +1,190 @@ +/* + MIT License + + Copyright (c) 2020 xerox + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#pragma once +#include +#include +#include +#include + +#if _M_IX86 + #define OFFSET_TO_ADDRESS 0x1 +#elif _M_X64 + #define OFFSET_TO_ADDRESS 0x2 +#endif + +namespace hook +{ + static void write_to_readonly(void* addr, void* data, int size) + { + DWORD old_flags; + VirtualProtect((LPVOID)addr, size, PAGE_EXECUTE_READWRITE, &old_flags); + memcpy((void*)addr, data, size); + VirtualProtect((LPVOID)addr, size, old_flags, &old_flags); + } + + class detour + { + public: + detour(void* addr_to_hook, void* jmp_to, bool enable = true) + : hook_addr(addr_to_hook), detour_addr(jmp_to), hook_installed(false) + { + //setup hook + memcpy( + jmp_code + OFFSET_TO_ADDRESS, + &jmp_to, + sizeof(jmp_to) + ); + + //save bytes + memcpy( + org_bytes, + hook_addr, + sizeof(org_bytes) + ); + if(enable) + install(); + } + + void install() + { + if (hook_installed.load()) + return; + + // mapped page is already read/write + memcpy(hook_addr, jmp_code, sizeof(jmp_code)); + hook_installed.exchange(true); + } + void uninstall() + { + if (!hook_installed.load()) + return; + + // mapped page is already read/write + memcpy(hook_addr, org_bytes, sizeof(org_bytes)); + hook_installed.exchange(false); + } + + ~detour() { uninstall(); } + bool installed() { return hook_installed; } + void* hook_address() { return hook_addr; } + void* detour_address() { return detour_addr; } + private: + std::atomic hook_installed; + void *hook_addr, *detour_addr; + +#if _M_IX86 + /* + 0: b8 ff ff ff ff mov eax, 0xffffffff + 5: ff e0 jmp eax + */ + unsigned char jmp_code[7] = { + 0xb8, 0x0, 0x0, 0x0, 0x0, + 0xFF, 0xE0 + }; +#elif _M_X64 + /* + 0: 48 b8 ff ff ff ff ff ff ff ff movabs rax,0xffffffffffffffff + 7: ff e0 jmp rax + */ + unsigned char jmp_code[12] = { + 0x48, 0xb8, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0xff, 0xe0 + }; +#endif + 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) + { + if (!addr_to_hook) + return; + + hooks.insert({ + addr_to_hook, + std::make_unique( + addr_to_hook, + jmp_to_addr, + enable + )} + ); + } + + /* + Author: xerox + Date: 12/19/2019 + + Enable hook given the address to hook + */ + static 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) + { + if (!addr) + return; + hooks.at(addr)->uninstall(); + } + + + /* + Author: xerox + Date: 12/19/2019 + + Remove hook completely from vector + */ + static void remove(void* addr) + { + if (!addr) + return; + hooks.at(addr)->~detour(); + hooks.erase(addr); + } +} \ No newline at end of file diff --git a/physmeme/util/nt.hpp b/physmeme/util/nt.hpp new file mode 100644 index 0000000..f671e6a --- /dev/null +++ b/physmeme/util/nt.hpp @@ -0,0 +1,93 @@ +#pragma once +#include +#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 auto SystemModuleInformation = 11; +constexpr auto SystemHandleInformation = 16; +constexpr auto SystemExtendedHandleInformation = 64; + +typedef struct _SYSTEM_HANDLE +{ + PVOID Object; + HANDLE UniqueProcessId; + HANDLE HandleValue; + ULONG GrantedAccess; + USHORT CreatorBackTraceIndex; + USHORT ObjectTypeIndex; + ULONG HandleAttributes; + ULONG Reserved; +} SYSTEM_HANDLE, * PSYSTEM_HANDLE; + +typedef struct _SYSTEM_HANDLE_INFORMATION_EX +{ + ULONG_PTR HandleCount; + ULONG_PTR Reserved; + SYSTEM_HANDLE Handles[1]; +} SYSTEM_HANDLE_INFORMATION_EX, * PSYSTEM_HANDLE_INFORMATION_EX; + +typedef enum _POOL_TYPE { + NonPagedPool, + NonPagedPoolExecute, + PagedPool, + NonPagedPoolMustSucceed, + DontUseThisType, + NonPagedPoolCacheAligned, + PagedPoolCacheAligned, + NonPagedPoolCacheAlignedMustS, + MaxPoolType, + NonPagedPoolBase, + NonPagedPoolBaseMustSucceed, + NonPagedPoolBaseCacheAligned, + NonPagedPoolBaseCacheAlignedMustS, + NonPagedPoolSession, + PagedPoolSession, + NonPagedPoolMustSucceedSession, + DontUseThisTypeSession, + NonPagedPoolCacheAlignedSession, + PagedPoolCacheAlignedSession, + NonPagedPoolCacheAlignedMustSSession, + NonPagedPoolNx, + NonPagedPoolNxCacheAligned, + NonPagedPoolSessionNx +} POOL_TYPE; + +typedef struct _RTL_PROCESS_MODULE_INFORMATION +{ + HANDLE Section; + PVOID MappedBase; + PVOID ImageBase; + ULONG ImageSize; + ULONG Flags; + USHORT LoadOrderIndex; + USHORT InitOrderIndex; + USHORT LoadCount; + USHORT OffsetToFileName; + UCHAR FullPathName[256]; +} RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION; + +typedef struct _RTL_PROCESS_MODULES +{ + ULONG NumberOfModules; + RTL_PROCESS_MODULE_INFORMATION Modules[1]; +} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES; + +typedef LARGE_INTEGER PHYSICAL_ADDRESS, * PPHYSICAL_ADDRESS; + +typedef struct _MM_COPY_ADDRESS { + union { + PVOID VirtualAddress; + PHYSICAL_ADDRESS PhysicalAddress; + }; +} MM_COPY_ADDRESS, * PMMCOPY_ADDRESS; + +using ExAllocatePool = PVOID(__stdcall*) (POOL_TYPE, SIZE_T); +using ExAllocatePoolWithTag = PVOID(__stdcall*)(POOL_TYPE, SIZE_T, ULONG); +using MmCopyMemory = NTSTATUS (__fastcall*)(PVOID, MM_COPY_ADDRESS,SIZE_T,ULONG,PSIZE_T); +using DRIVER_INITIALIZE = NTSTATUS(__stdcall*)(std::uintptr_t, std::size_t); \ No newline at end of file diff --git a/physmeme/util/util.hpp b/physmeme/util/util.hpp new file mode 100644 index 0000000..5af7b34 --- /dev/null +++ b/physmeme/util/util.hpp @@ -0,0 +1,155 @@ +#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 +{ + // 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) + { + std::ifstream fstr(file, std::ios::binary); + fstr.unsetf(std::ios::skipws); + fstr.seekg(0, std::ios::end); + + const auto file_size = fstr.tellg(); + + fstr.seekg(NULL, std::ios::beg); + data.reserve(static_cast(file_size)); + 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) + { + void* buffer = nullptr; + DWORD buffer_size = NULL; + + NTSTATUS status = NtQuerySystemInformation(static_cast(SystemModuleInformation), buffer, buffer_size, &buffer_size); + + while (status == STATUS_INFO_LENGTH_MISMATCH) + { + VirtualFree(buffer, NULL, MEM_RELEASE); + buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + status = NtQuerySystemInformation(static_cast(SystemModuleInformation), buffer, buffer_size, &buffer_size); + } + + if (!NT_SUCCESS(status)) + { + VirtualFree(buffer, NULL, MEM_RELEASE); + return NULL; + } + + const auto modules = static_cast(buffer); + for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) + { + const std::string current_module_name = std::string(reinterpret_cast(modules->Modules[idx].FullPathName) + modules->Modules[idx].OffsetToFileName); + if (!_stricmp(current_module_name.c_str(), module_name)) + { + const uint64_t result = reinterpret_cast(modules->Modules[idx].ImageBase); + VirtualFree(buffer, NULL, MEM_RELEASE); + return result; + } + } + + VirtualFree(buffer, NULL, MEM_RELEASE); + return NULL; + } + + // get base address of kernel module + // + // taken from: https://github.com/z175/kdmapper/blob/master/kdmapper/utils.cpp#L30 + static void* get_module_export(const char* module_name, const char* export_name, bool rva = false) + { + void* buffer = nullptr; + DWORD buffer_size = 0; + + NTSTATUS status = NtQuerySystemInformation(static_cast(SystemModuleInformation), buffer, buffer_size, &buffer_size); + + while (status == STATUS_INFO_LENGTH_MISMATCH) + { + VirtualFree(buffer, 0, MEM_RELEASE); + buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + status = NtQuerySystemInformation(static_cast(SystemModuleInformation), buffer, buffer_size, &buffer_size); + } + + if (!NT_SUCCESS(status)) + { + VirtualFree(buffer, 0, MEM_RELEASE); + return 0; + } + + const auto modules = static_cast(buffer); + for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) + { + // find module and then load library it + const std::string current_module_name = std::string(reinterpret_cast(modules->Modules[idx].FullPathName) + modules->Modules[idx].OffsetToFileName); + if (!_stricmp(current_module_name.c_str(), module_name)) + { + // had to shoot the tires off of "\\SystemRoot\\" + std::string full_path = reinterpret_cast(modules->Modules[idx].FullPathName); + full_path.replace( + full_path.find("\\SystemRoot\\"), + sizeof("\\SystemRoot\\") - 1, + std::string(getenv("SYSTEMROOT")).append("\\") + ); + + auto module_base = LoadLibraryA(full_path.c_str()); + PIMAGE_DOS_HEADER p_idh; + PIMAGE_NT_HEADERS p_inh; + PIMAGE_EXPORT_DIRECTORY p_ied; + + PDWORD addr, name; + PWORD ordinal; + + p_idh = (PIMAGE_DOS_HEADER)module_base; + if (p_idh->e_magic != IMAGE_DOS_SIGNATURE) + return NULL; + + p_inh = (PIMAGE_NT_HEADERS)((LPBYTE)module_base + p_idh->e_lfanew); + if (p_inh->Signature != IMAGE_NT_SIGNATURE) + return NULL; + + if (p_inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0) + return NULL; + + p_ied = (PIMAGE_EXPORT_DIRECTORY)((LPBYTE)module_base + + p_inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); + + addr = (PDWORD)((LPBYTE)module_base + p_ied->AddressOfFunctions); + name = (PDWORD)((LPBYTE)module_base + p_ied->AddressOfNames); + ordinal = (PWORD)((LPBYTE)module_base + p_ied->AddressOfNameOrdinals); + + // find exported function + for (auto i = 0; i < p_ied->AddressOfFunctions; i++) + if (!strcmp(export_name, (char*)module_base + name[i])) + { + if (!rva) + { + auto result = (void*)((std::uintptr_t)modules->Modules[idx].ImageBase + addr[ordinal[i]]); + VirtualFree(buffer, NULL, MEM_RELEASE); + return result; + } + else + { + auto result = (void*)addr[ordinal[i]]; + VirtualFree(buffer, NULL, MEM_RELEASE); + return result; + } + } + } + } + VirtualFree(buffer, NULL, MEM_RELEASE); + return NULL; + } +} \ No newline at end of file