- fixed blue screen issues with NtShutdownSystem

- kernel_ctx is now singleton, thus allowing many kernel_ctx's.
merge-requests/1/head
xerox 5 years ago
parent f06dfdb370
commit fbce69c77e

@ -28,22 +28,14 @@ For more information, please refer to <http://unlicense.org>
!!!!!!!!!!!!!!!!!!!!!!!!!!! This code was created by not-wlan (wlan). all credit for this header and source file goes to him !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
#include "drv_image.h"
#include <cassert>
#include <fstream>
#include "../drv_image/drv_image.h"
namespace physmeme
{
drv_image::drv_image(std::vector<std::uint8_t>& 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<uint8_t> image) : m_image(std::move(image))
{
m_image = std::vector<std::uint8_t>(image, image + size);
m_dos_header = reinterpret_cast<PIMAGE_DOS_HEADER>(m_image.data());
assert(m_dos_header->e_magic == IMAGE_DOS_SIGNATURE);
m_nt_headers = reinterpret_cast<PIMAGE_NT_HEADERS64>((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", &section.Name[0], (void*)source, (void*)target, section.SizeOfRawData);
#endif
if constexpr(physmeme_debugging)
printf("[+] copying [%s] 0x%p -> 0x%p [0x%04X]\n", &section.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<uintptr_t>(static_cast<uintptr_t>(base) - (nt_headers->OptionalHeader.ImageBase));
auto image_base_delta = static_cast<uintptr_t>(reinterpret_cast<uintptr_t>(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<char>(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<IMAGE_THUNK_DATA>(import_descriptors->OriginalFirstThunk);
else
@ -222,9 +212,9 @@ namespace physmeme
const auto image_import_by_name = get_rva<IMAGE_IMPORT_BY_NAME>(*(DWORD*)image_thunk_data);
const auto name_of_import = static_cast<char*>(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;
}

@ -40,9 +40,7 @@ For more information, please refer to <http://unlicense.org>
#include <functional>
#include <DbgHelp.h>
#include <variant>
#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<std::uint8_t>& image);
explicit drv_image(std::vector<uint8_t> 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<typename T>
__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<uintptr_t(std::string_view)> get_module, const std::function<uintptr_t(const char*, const char*)> get_function);
void fix_imports(
const std::function<uintptr_t(std::string_view)> get_module,
const std::function<uintptr_t(const char*, const char*)> get_function
);
void* data();
size_t header_size();
};

@ -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<std::uint32_t>(
util::get_module_export(
"ntoskrnl.exe",
@ -16,16 +14,27 @@ namespace physmeme
true
));
nt_page_offset = nt_rva % 0x1000;
ntoskrnl_buffer = reinterpret_cast<std::uint8_t*>(LoadLibraryA("C:\\Windows\\System32\\ntoskrnl.exe"));
nt_page_offset = nt_rva % page_size;
ntoskrnl_buffer = reinterpret_cast<std::uint8_t*>(
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<std::thread> 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<void*>(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<ExAllocatePool>(ex_alloc_pool, pool_type, size);
return NULL;
}
/*
Author: xerox
Date: 4/19/2020
return syscall<ExAllocatePool>(
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<ExAllocatePoolWithTag>(ex_alloc_pool_with_tag, pool_type, size, pool_tag);
}
/*
Author: xerox
Date: 4/19/2020
return syscall<ExAllocatePoolWithTag>(
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<MmCopyMemory>(
syscall<decltype(&memcpy)>(
mm_copy_memory,
reinterpret_cast<void*>(buffer),
MM_COPY_ADDRESS{ (void*)addr },
size,
MM_COPY_MEMORY_VIRTUAL,
&amount_copied
buffer,
addr,
size
);
}
/*
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)
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<MmCopyMemory>(
syscall<decltype(&memcpy)>(
mm_copy_memory,
reinterpret_cast<void*>(addr),
MM_COPY_ADDRESS{ buffer },
size,
MM_COPY_MEMORY_VIRTUAL,
&amount_copied
addr,
buffer,
size
);
}
/*
Author: xerox
Date: 4/19/2020
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<decltype(&RtlSecureZeroMemory)>(
rtl_zero_memory,
reinterpret_cast<void*>(addr),
addr,
size
);
}

@ -1,5 +1,6 @@
#pragma once
#include <windows.h>
#include <iostream>
#include <string_view>
#include <vector>
#include <thread>
@ -9,32 +10,69 @@
#include "../physmeme/physmeme.hpp"
#include "../util/hook.hpp"
#if PHYSMEME_DEBUGGING
#include <iostream>
#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<void*> psyscall_func{};
//
// you can edit this how you choose, im hooking NtShutdownSystem.
//
inline const std::pair<std::string_view, std::string_view> 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 <class T>
T read_kernel(std::uintptr_t addr)
T read_kernel(void* addr)
{
if (!addr)
return {};
@ -44,7 +82,7 @@ namespace physmeme
}
template <class T>
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 <class T, class ... Ts>
PVOID syscall(void* addr, Ts ... args)
std::invoke_result_t<T, Ts...> 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<PVOID>(STATUS_INVALID_PARAMETER);
return {};
hook::make_hook(psyscall_func, addr);
PVOID result = reinterpret_cast<PVOID>(reinterpret_cast<T>(proc)(args ...));
auto result = reinterpret_cast<T>(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<void*> psyscall_func;
//
// you can edit this how you choose, im hooking NtShutdownSystem.
//
const std::pair<std::string_view, std::string_view> 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;
};
}

@ -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<std::uintptr_t>(util::get_module_export(base, name));
};
//
// allocate memory in the kernel for the driver
//
std::uintptr_t pool_base = reinterpret_cast<std::uintptr_t>(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<std::uintptr_t>(pool_base) + image.entry_point();
//
// call driver entry
//
auto result = ctx.syscall<DRIVER_INITIALIZE>(reinterpret_cast<void*>(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<DRIVER_INITIALIZE>(
reinterpret_cast<void*>(entry_point),
reinterpret_cast<std::uintptr_t>(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
}

@ -90,7 +90,7 @@
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
@ -105,7 +105,7 @@
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
@ -120,7 +120,7 @@
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
@ -140,7 +140,7 @@
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>

@ -4,53 +4,20 @@
#include <cstdint>
#include <map>
#include "../util/util.hpp"
namespace physmeme
{
//--- ranges of physical memory
static std::map<std::uintptr_t, std::size_t> 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();
}

@ -3,17 +3,18 @@
#include <winternl.h>
#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;

@ -1,17 +1,54 @@
#pragma once
#include <Windows.h>
#include <cstdint>
#include <string_view>
#include <iterator>
#include <fstream>
#include <string>
#include <map>
#include <vector>
#include <ntstatus.h>
#include <winternl.h>
#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<std::uintptr_t, std::size_t> 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<uint8_t>& data)

@ -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

@ -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

@ -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\|

@ -28,10 +28,9 @@ For more information, please refer to <http://unlicense.org>
!!!!!!!!!!!!!!!!!!!!!!!!!!! This code was created by not-wlan (wlan). all credit for this header and source file goes to him !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
#include "drv_image.h"
#include <cassert>
#include <fstream>
#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", &section.Name[0], (void*)source, (void*)target, section.SizeOfRawData);
if constexpr(physmeme_debugging)
printf("[+] copying [%s] 0x%p -> 0x%p [0x%04X]\n", &section.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<uintptr_t>(static_cast<uintptr_t>(base) - (nt_headers->OptionalHeader.ImageBase));
auto image_base_delta = static_cast<uintptr_t>(reinterpret_cast<uintptr_t>(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<IMAGE_THUNK_DATA>(import_descriptors->OriginalFirstThunk);
@ -208,7 +212,9 @@ namespace physmeme
const auto image_import_by_name = get_rva<IMAGE_IMPORT_BY_NAME>(*(DWORD*)image_thunk_data);
const auto name_of_import = static_cast<char*>(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;
}

@ -40,6 +40,7 @@ For more information, please refer to <http://unlicense.org>
#include <functional>
#include <DbgHelp.h>
#include <variant>
#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<typename T>
__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<uintptr_t(std::string_view)> get_module, const std::function<uintptr_t(const char*, const char*)> get_function);
void fix_imports(
const std::function<uintptr_t(std::string_view)> get_module,
const std::function<uintptr_t(const char*, const char*)> get_function
);
void* data();
size_t header_size();
};

@ -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<std::uint32_t>(
util::get_module_export(
"ntoskrnl.exe",
@ -16,16 +14,27 @@ namespace physmeme
true
));
nt_page_offset = nt_rva % 0x1000;
ntoskrnl_buffer = reinterpret_cast<std::uint8_t*>(LoadLibraryA("C:\\Windows\\System32\\ntoskrnl.exe"));
nt_page_offset = nt_rva % page_size;
ntoskrnl_buffer = reinterpret_cast<std::uint8_t*>(
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<std::thread> 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<void*>(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<ExAllocatePool>(ex_alloc_pool, pool_type, size);
return NULL;
}
/*
Author: xerox
Date: 4/19/2020
return syscall<ExAllocatePool>(
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<ExAllocatePoolWithTag>(ex_alloc_pool_with_tag, pool_type, size, pool_tag);
}
/*
Author: xerox
Date: 4/19/2020
return syscall<ExAllocatePoolWithTag>(
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<MmCopyMemory>(
syscall<decltype(&memcpy)>(
mm_copy_memory,
reinterpret_cast<void*>(buffer),
MM_COPY_ADDRESS{ (void*)addr },
size,
MM_COPY_MEMORY_VIRTUAL,
&amount_copied
buffer,
addr,
size
);
}
/*
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)
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<MmCopyMemory>(
syscall<decltype(&memcpy)>(
mm_copy_memory,
reinterpret_cast<void*>(addr),
MM_COPY_ADDRESS{ buffer },
size,
MM_COPY_MEMORY_VIRTUAL,
&amount_copied
addr,
buffer,
size
);
}
/*
Author: xerox
Date: 4/19/2020
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<decltype(&RtlSecureZeroMemory)>(
rtl_zero_memory,
reinterpret_cast<void*>(addr),
addr,
size
);
}

@ -1,5 +1,6 @@
#pragma once
#include <windows.h>
#include <iostream>
#include <string_view>
#include <vector>
#include <thread>
@ -9,34 +10,69 @@
#include "../physmeme/physmeme.hpp"
#include "../util/hook.hpp"
#define PHYSMEME_DEBUGGING 1
namespace physmeme
{
//
// offset of function into a physical page
// used for comparing bytes when searching
//
inline std::uint16_t nt_page_offset{};
#if PHYSMEME_DEBUGGING
#include <iostream>
#endif
//
// rva of nt function we are going to hook
//
inline std::uint32_t nt_rva{};
/*
Author: xerox
Date: 4/19/2020
//
// 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<void*> psyscall_func{};
//
// you can edit this how you choose, im hooking NtShutdownSystem.
//
inline const std::pair<std::string_view, std::string_view> syscall_hook = { "NtShutdownSystem", "ntdll.dll" };
this namespace contains everything needed to interface with the kernel
*/
namespace physmeme
{
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 <class T>
T read_kernel(std::uintptr_t addr)
T read_kernel(void* addr)
{
if (!addr)
return {};
@ -46,7 +82,7 @@ namespace physmeme
}
template <class T>
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 <class T, class ... Ts>
PVOID syscall(void* addr, Ts ... args)
std::invoke_result_t<T, Ts...> 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<PVOID>(STATUS_INVALID_PARAMETER);
return {};
hook::make_hook(psyscall_func, addr);
PVOID result = reinterpret_cast<PVOID>(reinterpret_cast<T>(proc)(args ...));
auto result = reinterpret_cast<T>(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<void*> psyscall_func;
//
// you can edit this how you choose, im hooking NtTraceControl.
//
const std::pair<std::string_view, std::string_view> 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;
};
}

@ -1,28 +1,43 @@
#include <windows.h>
#include <iostream>
#include <fstream>
#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<std::uint8_t> 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<std::uintptr_t>(util::get_module_export(base, name));
};
//
// allocate memory in the kernel for the driver
//
std::uintptr_t pool_base = reinterpret_cast<std::uintptr_t>(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<std::uintptr_t>(pool_base) + image.entry_point();
//
// call driver entry
//
auto result = ctx.syscall<DRIVER_INITIALIZE>(reinterpret_cast<void*>(entry_point), pool_base, image.size());
std::cout << "[+] driver entry returned: " << std::hex << result << std::endl;
auto result = ctx.syscall<DRIVER_INITIALIZE>(
reinterpret_cast<void*>(entry_point),
reinterpret_cast<std::uintptr_t>(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();
}

@ -90,7 +90,7 @@
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
@ -105,7 +105,7 @@
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
@ -120,7 +120,7 @@
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
@ -140,7 +140,7 @@
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>

@ -4,53 +4,20 @@
#include <cstdint>
#include <map>
#include "../util/util.hpp"
namespace physmeme
{
//--- ranges of physical memory
static std::map<std::uintptr_t, std::size_t> 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();
}

@ -3,16 +3,18 @@
#include <winternl.h>
#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;

@ -1,17 +1,54 @@
#pragma once
#include <Windows.h>
#include <cstdint>
#include <string_view>
#include <iterator>
#include <fstream>
#include <string>
#include <map>
#include <vector>
#include <ntstatus.h>
#include <winternl.h>
#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<std::uintptr_t, std::size_t> 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<uint8_t>& data)

Binary file not shown.

@ -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

@ -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

@ -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\|

Binary file not shown.
Loading…
Cancel
Save