V1.0 baby! :)

merge-requests/1/head
xerox 5 years ago
parent 3d3a2ebd82
commit 5d8fb3f10d

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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

@ -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 <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>
namespace physmeme
{
drv_image::drv_image(std::vector<uint8_t> image) : m_image(std::move(image))
{
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);
assert(m_nt_headers->Signature == IMAGE_NT_SIGNATURE);
assert(m_nt_headers->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC);
m_section_header = reinterpret_cast<IMAGE_SECTION_HEADER*>((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", &section.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<int16_t*>(relocation_base + IMR_RELOFFSET(data));
*raw_address += static_cast<unsigned long>(HIWORD(image_base_delta));
break;
}
case IMAGE_REL_BASED_LOW:
{
const auto raw_address = reinterpret_cast<int16_t*>(relocation_base + IMR_RELOFFSET(data));
*raw_address += static_cast<unsigned long>(LOWORD(image_base_delta));
break;
}
case IMAGE_REL_BASED_HIGHLOW:
{
const auto raw_address = reinterpret_cast<size_t*>(relocation_base + IMR_RELOFFSET(data));
*raw_address += static_cast<size_t>(image_base_delta);
break;
}
case IMAGE_REL_BASED_DIR64:
{
auto UNALIGNED raw_address = reinterpret_cast<DWORD_PTR UNALIGNED*>(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<uintptr_t>(static_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
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<uint8_t*>(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<PWORD>(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<PIMAGE_BASE_RELOCATION>(relocation_data);
}
}
template<typename T>
__forceinline T* ptr_add(void* base, uintptr_t offset)
{
return (T*)(uintptr_t)base + offset;
}
void drv_image::fix_imports(const std::function<uintptr_t(std::string_view)> get_module, const std::function<uintptr_t(const char*, const char*)> get_function)
{
ULONG size;
auto import_descriptors = static_cast<PIMAGE_IMPORT_DESCRIPTOR>(::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<char>(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<IMAGE_THUNK_DATA>(import_descriptors->OriginalFirstThunk);
else
image_thunk_data = get_rva<IMAGE_THUNK_DATA>(import_descriptors->FirstThunk);
auto image_func_data = get_rva<IMAGE_THUNK_DATA64>(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<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);
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;
}
}

@ -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 <http://unlicense.org>
!!!!!!!!!!!!!!!!!!!!!!!!!!! This code was created by not-wlan (wlan). all credit for this header and source file goes to him !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
#pragma once
#include <vector>
#define WIN32_NO_STATUS
#include <Windows.h>
#include <Winternl.h>
#undef WIN32_NO_STATUS
#include <ntstatus.h>
#include <functional>
#include <DbgHelp.h>
#include <variant>
#pragma comment(lib, "Dbghelp.lib")
namespace physmeme
{
class drv_image
{
std::vector<uint8_t> m_image;
std::vector<uint8_t> 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<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;
template<typename T>
__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<uintptr_t(std::string_view)> get_module, const std::function<uintptr_t(const char*, const char*)> get_function);
void* data();
size_t header_size();
};
}

@ -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<std::uint32_t>(
util::get_module_export(
"ntoskrnl.exe",
syscall_hook.first.data(),
true
));
nt_page_offset = nt_rva % 0x1000;
ntoskrnl_buffer = reinterpret_cast<std::uint8_t*>(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<std::thread> 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<void*>(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<void*>(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<void*>(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<ExAllocatePool>(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<ExAllocatePoolWithTag>(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<MmCopyMemory>(
mm_copy_memory,
reinterpret_cast<void*>(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<MmCopyMemory>(
mm_copy_memory,
reinterpret_cast<void*>(addr),
MM_COPY_ADDRESS{ buffer },
size,
MM_COPY_MEMORY_VIRTUAL,
&amount_copied
);
}
}

@ -0,0 +1,103 @@
#pragma once
#include <windows.h>
#include <string_view>
#include <vector>
#include <thread>
#include <atomic>
#include "../util/util.hpp"
#include "../physmeme/physmeme.hpp"
#include "../util/hook.hpp"
#define PHYSMEME_DEBUGGING 1
#if PHYSMEME_DEBUGGING
#include <iostream>
#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 <class T>
T read_kernel(std::uintptr_t addr)
{
if (!addr)
return {};
T buffer;
read_kernel(addr, &buffer, sizeof(T));
return buffer;
}
template <class T>
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 <class T, class ... Ts>
PVOID syscall(void* addr, Ts ... args)
{
auto proc = GetProcAddress(GetModuleHandleA("ntdll.dll"), syscall_hook.first.data());
if (!proc || !psyscall_func || !addr)
return reinterpret_cast<PVOID>(STATUS_INVALID_PARAMETER);
hook::make_hook(psyscall_func, addr);
PVOID result = reinterpret_cast<PVOID>(reinterpret_cast<T>(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<void*> psyscall_func;
//
// you can edit this how you choose, im hooking NtTraceControl.
//
const std::pair<std::string_view, std::string_view> 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;
};
}

@ -0,0 +1,73 @@
#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 < 1)
{
std::cout << "[-] invalid use, please provide a path to a driver" << std::endl;
return -1;
}
std::vector<std::uint8_t> 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<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;
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<DRIVER_INITIALIZE>(reinterpret_cast<void*>(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();
}

@ -0,0 +1,175 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{6578B958-DD53-4BE0-8011-009563919E73}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>physmeme</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<SpectreMitigation>false</SpectreMitigation>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="drv_image\drv_image.cpp" />
<ClCompile Include="kernel_ctx\kernel_ctx.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="drv_image\drv_image.h" />
<ClInclude Include="kernel_ctx\kernel_ctx.h" />
<ClInclude Include="physmeme\physmeme.hpp" />
<ClInclude Include="util\hook.hpp" />
<ClInclude Include="util\nt.hpp" />
<ClInclude Include="util\util.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Header Files\kernel_ctx">
<UniqueIdentifier>{040c8387-476c-4aa5-aa2a-ca30465b41bd}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\kernel_ctx">
<UniqueIdentifier>{642c89a0-7989-4f5c-ae5a-f71e697abe16}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\physmeme">
<UniqueIdentifier>{c4aa2f98-70d4-418e-894d-4e1975e2bad2}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\util">
<UniqueIdentifier>{4fd2f117-66bb-4f75-af5b-b7e041a4dc48}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\drv_image">
<UniqueIdentifier>{161b3714-a6cd-4b7b-a1f1-9b90b1f84aca}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\drv_image">
<UniqueIdentifier>{ed9d2db3-acef-42c0-880f-7f95dcca819d}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="kernel_ctx\kernel_ctx.cpp">
<Filter>Source Files\kernel_ctx</Filter>
</ClCompile>
<ClCompile Include="drv_image\drv_image.cpp">
<Filter>Source Files\drv_image</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="kernel_ctx\kernel_ctx.h">
<Filter>Header Files\kernel_ctx</Filter>
</ClInclude>
<ClInclude Include="util\hook.hpp">
<Filter>Header Files\util</Filter>
</ClInclude>
<ClInclude Include="util\util.hpp">
<Filter>Header Files\util</Filter>
</ClInclude>
<ClInclude Include="util\nt.hpp">
<Filter>Header Files\util</Filter>
</ClInclude>
<ClInclude Include="drv_image\drv_image.h">
<Filter>Header Files\drv_image</Filter>
</ClInclude>
<ClInclude Include="physmeme\physmeme.hpp">
<Filter>Header Files\physmeme</Filter>
</ClInclude>
</ItemGroup>
</Project>

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LocalDebuggerCommandArguments>C:\Users\interesting\Desktop\hello-world.sys</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LocalDebuggerCommandArguments>C:\Users\interesting\Desktop\hello-world.sys</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LocalDebuggerCommandArguments>C:\Users\interesting\Desktop\hello-world.sys</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LocalDebuggerCommandArguments>C:\Users\interesting\Desktop\hello-world.sys</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>

@ -0,0 +1,104 @@
#pragma once
#include <windows.h>
#include <mutex>
#include <cstdint>
#include <map>
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.
*/
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();
}

@ -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 <Windows.h>
#include <map>
#include <atomic>
#include <memory>
#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<bool> 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<void*, std::unique_ptr<detour>> 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<detour>(
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);
}
}

@ -0,0 +1,93 @@
#pragma once
#include <Windows.h>
#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 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);

@ -0,0 +1,155 @@
#include <Windows.h>
#include <cstdint>
#include <string_view>
#include <iterator>
#include <fstream>
#include <string>
#include <vector>
#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<uint8_t>& 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<uint32_t>(file_size));
data.insert(data.begin(), std::istream_iterator<uint8_t>(fstr), std::istream_iterator<uint8_t>());
}
// 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<SYSTEM_INFORMATION_CLASS>(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<SYSTEM_INFORMATION_CLASS>(SystemModuleInformation), buffer, buffer_size, &buffer_size);
}
if (!NT_SUCCESS(status))
{
VirtualFree(buffer, NULL, MEM_RELEASE);
return NULL;
}
const auto modules = static_cast<PRTL_PROCESS_MODULES>(buffer);
for (auto idx = 0u; idx < modules->NumberOfModules; ++idx)
{
const std::string current_module_name = std::string(reinterpret_cast<char*>(modules->Modules[idx].FullPathName) + modules->Modules[idx].OffsetToFileName);
if (!_stricmp(current_module_name.c_str(), module_name))
{
const uint64_t result = reinterpret_cast<uint64_t>(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<SYSTEM_INFORMATION_CLASS>(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<SYSTEM_INFORMATION_CLASS>(SystemModuleInformation), buffer, buffer_size, &buffer_size);
}
if (!NT_SUCCESS(status))
{
VirtualFree(buffer, 0, MEM_RELEASE);
return 0;
}
const auto modules = static_cast<PRTL_PROCESS_MODULES>(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<char*>(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<char*>(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;
}
}
Loading…
Cancel
Save