aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToni Uhlig <matzeton@googlemail.com>2024-05-29 00:26:09 +0200
committerToni Uhlig <matzeton@googlemail.com>2024-05-29 10:49:32 +0200
commit8bdef10098cbdb9f010afb68f24ca715bc4afcec (patch)
tree317fc135e6be93ae09a0d9d4289e1e209203a57a
parent0ab8e3189dd1b63a76d15562b00a0c31d40260f7 (diff)
Added some "Experimental" functionality.
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r--Makefile11
-rw-r--r--memory.cpp316
-rw-r--r--memory.hpp173
-rw-r--r--native.h10
4 files changed, 399 insertions, 111 deletions
diff --git a/Makefile b/Makefile
index 13d191f..01fcaec 100644
--- a/Makefile
+++ b/Makefile
@@ -5,10 +5,12 @@ endif
include $(DPP_ROOT)/Makefile.inc
COMMON_HEADERS = native.h memory.hpp
+CFLAGS_memory-experimental.o = -DENABLE_EXPERIMENTAL=1
DRIVER_NAME = driver-kmem
-DRIVER_OBJECTS = $(DRIVER_NAME).o memory.o
+DRIVER_OBJECTS = $(DRIVER_NAME).o memory-experimental.o
DRIVER_TARGET = $(DRIVER_NAME).sys
+CFLAGS_driver-kmem.o = -DENABLE_EXPERIMENTAL=1
TARKOV_NAME = tfk
TARKOV_OBJECTS = tarkov.o memory.o
@@ -40,6 +42,9 @@ clean:
rm -f $(HUNT_OBJECTS) $(HUNT_TARGET)
rm -f $(BF4_OBJECTS) $(BF4_TARGET)
+memory-experimental.o: memory.cpp
+ $(call BUILD_CPP_OBJECT,$<,$@)
+
%.o: %.cpp $(COMMON_HEADERS)
$(call BUILD_CPP_OBJECT,$<,$@)
@@ -54,3 +59,7 @@ $(HUNT_TARGET): $(HUNT_OBJECTS)
$(BF4_TARGET): $(BF4_OBJECTS)
$(call LINK_CPP_KERNEL_TARGET,$(BF4_OBJECTS),$@)
+
+.NOTPARALLEL: all install clean
+.PHONY: all install clean
+.DEFAULT_GOAL := all
diff --git a/memory.cpp b/memory.cpp
index b7fb27a..eb13135 100644
--- a/memory.cpp
+++ b/memory.cpp
@@ -5,6 +5,17 @@
#include "memory.hpp"
#include "native.h"
+#define WINDOWS_1803 17134
+#define WINDOWS_1809 17763
+#define WINDOWS_1903 18362
+#define WINDOWS_1909 18363
+#define WINDOWS_2004 19041
+#define WINDOWS_20H2 19569
+#define WINDOWS_21H1 20180
+#define WINDOWS_22H2 19045
+
+#define MIN(a, b) (a < b ? a : b)
+
extern "C" {
NTSTATUS NTAPI WrapperObOpenObjectByPointer(
_In_ PVOID obj, _In_ ULONG HandleAttributes,
@@ -18,12 +29,20 @@ NTSTATUS NTAPI WrapperZwProtectVirtualMemory(
_Out_ PULONG OldAccessProtection);
NTSTATUS NTAPI WrapperMmCopyVirtualMemory(_In_ PEPROCESS SourceProcess,
- _In_ PVOID SourceAddress,
- _In_ PEPROCESS TargetProcess,
- _In_ PVOID TargetAddress,
- _In_ SIZE_T BufferSize,
- _In_ KPROCESSOR_MODE PreviousMode,
- _Out_ PSIZE_T ReturnSize);
+ _In_ PVOID SourceAddress,
+ _In_ PEPROCESS TargetProcess,
+ _In_ PVOID TargetAddress,
+ _In_ SIZE_T BufferSize,
+ _In_ KPROCESSOR_MODE PreviousMode,
+ _Out_ PSIZE_T ReturnSize);
+
+PVOID NTAPI MmMapIoSpaceEx(_In_ PHYSICAL_ADDRESS PhysicalAddress,
+ _In_ SIZE_T NumberOfBytes, _In_ ULONG Protect);
+
+NTSTATUS NTAPI MmCopyMemory(_In_ PVOID TargetAddress,
+ _In_ MM_COPY_ADDRESS SourceAddress,
+ _In_ SIZE_T NumberOfBytes, _In_ ULONG Flags,
+ _Out_ PSIZE_T NumberOfBytesTransferred);
NTKERNELAPI
PPEB NTAPI PsGetProcessPeb(_In_ PEPROCESS Process);
@@ -46,34 +65,255 @@ NTKERNELAPI PVOID NTAPI PsGetProcessWow64Process(_In_ PEPROCESS Process);
static int g_waitCount = 100;
static LONGLONG g_waitTimeout = (-1LL) * 10LL * 1000LL * 250LL; // 250ms
-auto get_process_cr3(PEPROCESS pe_process) -> uint64_t
-{
- auto process_dirbase = *(uint64_t*)((uint8_t*)pe_process + 0x28);
+#ifdef ENABLE_EXPERIMENTAL
+uint64_t Experimental::GetProcessCr3(_In_ const PEPROCESS pe_process) {
+ PUCHAR process = (PUCHAR)pe_process;
+ ULONG_PTR process_dirbase =
+ *(PULONG_PTR)(process + 0x28); // dirbase x64, 32bit is 0x18
+ if (process_dirbase == 0) {
+ uint64_t UserDirOffset = Experimental::GetUserDirectoryTableBaseOffset();
+
+ ULONG_PTR process_userdirbase = *(PULONG_PTR)(process + UserDirOffset);
+ return process_userdirbase;
+ }
+ return process_dirbase;
+}
+
+PEPROCESS Experimental::SwapProcess(_In_ PEPROCESS new_process) {
+ auto current_thread = KeGetCurrentThread();
+
+ auto apc_state = *(uint64_t *)((uint64_t)current_thread + 0x98);
+ auto old_process = *(uint64_t *)(apc_state + 0x20);
+
+ *(uint64_t *)(apc_state + 0x20) = reinterpret_cast<uint64_t>(new_process);
- if (!process_dirbase)
- return *(uint64_t*)((uint8_t*)pe_process + 0x388);
+ auto dir_table_base = GetProcessCr3(new_process);
+ __writecr3(dir_table_base);
- return process_dirbase;
+ return reinterpret_cast<PEPROCESS>(old_process);
}
-auto swap_process(PEPROCESS new_process) -> PEPROCESS
-{
- auto current_thread = KeGetCurrentThread();
+uint64_t Experimental::GetUserDirectoryTableBaseOffset() {
+ RTL_OSVERSIONINFOW ver = {};
+ RtlGetVersion(&ver);
+ switch (ver.dwBuildNumber) {
+ case WINDOWS_1803:
+ return 0x0278;
+ break;
+ case WINDOWS_1809:
+ return 0x0278;
+ break;
+ case WINDOWS_1903:
+ return 0x0280;
+ break;
+ case WINDOWS_1909:
+ return 0x0280;
+ break;
+ case WINDOWS_2004:
+ return 0x0388;
+ break;
+ case WINDOWS_20H2:
+ return 0x0388;
+ break;
+ case WINDOWS_21H1:
+ return 0x0388;
+ break;
+ case WINDOWS_22H2:
+ return 0x0388;
+ break;
+ default:
+ return 0x0388;
+ }
+}
+
+NTSTATUS Experimental::ReadPhysicalAddress(_In_ PVOID TargetAddress,
+ _In_ PVOID lpBuffer,
+ _In_ SIZE_T Size,
+ _Out_ SIZE_T *BytesRead) {
+ MM_COPY_ADDRESS AddrToRead = {};
+ AddrToRead.PhysicalAddress.QuadPart = (LONGLONG)TargetAddress;
+ return MmCopyMemory(lpBuffer, AddrToRead, Size, MM_COPY_MEMORY_PHYSICAL,
+ BytesRead);
+}
+
+NTSTATUS Experimental::WritePhysicalAddress(_In_ PVOID TargetAddress,
+ _In_ PVOID lpBuffer,
+ _In_ SIZE_T Size,
+ _Out_ SIZE_T *BytesWritten) {
+ if (!TargetAddress)
+ return STATUS_UNSUCCESSFUL;
- auto apc_state = *(uint64_t*)((uint64_t)current_thread + 0x98);
- auto old_process = *(uint64_t*)(apc_state + 0x20);
+ PHYSICAL_ADDRESS AddrToWrite = {};
+ AddrToWrite.QuadPart = LONGLONG(TargetAddress);
- *(uint64_t*)(apc_state + 0x20) = reinterpret_cast<uint64_t>(new_process);
+ PVOID pmapped_mem = MmMapIoSpaceEx(AddrToWrite, Size, PAGE_READWRITE);
- auto dir_table_base = get_process_cr3(new_process);
- __writecr3(dir_table_base);
+ if (!pmapped_mem)
+ return STATUS_UNSUCCESSFUL;
- return reinterpret_cast<PEPROCESS>(old_process);
+ memcpy(pmapped_mem, lpBuffer, Size);
+
+ *BytesWritten = Size;
+ MmUnmapIoSpace(pmapped_mem, Size);
+ return STATUS_SUCCESS;
+}
+
+uint64_t Experimental::GetKernelDirBase() {
+ PUCHAR process = (PUCHAR)PsGetCurrentProcess();
+ ULONG_PTR cr3 = *(PULONG_PTR)(process + 0x28); // dirbase x64, 32bit is 0x18
+ return cr3;
}
+uint64_t Experimental::TranslateLinearAddress(_In_ uint64_t directoryTableBase,
+ _In_ uint64_t virtualAddress) {
+ directoryTableBase &= ~0xf;
+
+ UINT64 pageOffset =
+ virtualAddress & ~(~0ul << Experimental::page_offset_size);
+ UINT64 pte = ((virtualAddress >> 12) & (0x1ffll));
+ UINT64 pt = ((virtualAddress >> 21) & (0x1ffll));
+ UINT64 pd = ((virtualAddress >> 30) & (0x1ffll));
+ UINT64 pdp = ((virtualAddress >> 39) & (0x1ffll));
+
+ SIZE_T readsize = 0;
+ UINT64 pdpe = 0;
+ ReadPhysicalAddress(PVOID(directoryTableBase + 8 * pdp), &pdpe, sizeof(pdpe),
+ &readsize);
+ if (~pdpe & 1)
+ return 0;
+
+ UINT64 pde = 0;
+ ReadPhysicalAddress(PVOID((pdpe & Experimental::page_mask) + 8 * pd), &pde,
+ sizeof(pde), &readsize);
+ if (~pde & 1)
+ return 0;
+
+ /* 1GB large page, use pde's 12-34 bits */
+ if (pde & 0x80)
+ return (pde & (~0ull << 42 >> 12)) + (virtualAddress & ~(~0ull << 30));
+
+ UINT64 pteAddr = 0;
+ ReadPhysicalAddress(PVOID((pde & Experimental::page_mask) + 8 * pt), &pteAddr,
+ sizeof(pteAddr), &readsize);
+ if (~pteAddr & 1)
+ return 0;
+
+ /* 2MB large page */
+ if (pteAddr & 0x80)
+ return (pteAddr & Experimental::page_mask) +
+ (virtualAddress & ~(~0ull << 21));
+
+ virtualAddress = 0;
+ ReadPhysicalAddress(PVOID((pteAddr & Experimental::page_mask) + 8 * pte),
+ &virtualAddress, sizeof(virtualAddress), &readsize);
+ virtualAddress &= Experimental::page_mask;
+
+ if (!virtualAddress)
+ return 0;
+
+ return virtualAddress + pageOffset;
+}
+
+NTSTATUS Experimental::WriteProcessMemory(_In_ HANDLE pid,
+ _In_ uint64_t Address,
+ _In_ uint64_t AllocatedBuffer,
+ _In_ SIZE_T size,
+ _Out_ SIZE_T *written) {
+ DbgPrintEx(0, 0, "\n[Write] Address is: %llx", Address);
+ PEPROCESS pProcess = NULL;
+ if (pid == NULL)
+ return STATUS_UNSUCCESSFUL;
+
+ NTSTATUS NtRet = PsLookupProcessByProcessId(pid, &pProcess);
+ if (NtRet != STATUS_SUCCESS)
+ return NtRet;
+
+ ULONG_PTR process_dirbase = GetProcessCr3(pProcess);
+ ObDereferenceObject(pProcess);
+ DbgPrintEx(0, 0, "\n[Write] DirBase is: %llx", process_dirbase);
+ SIZE_T CurOffset = 0;
+ SIZE_T TotalSize = size;
+ while (TotalSize) {
+ uint64_t CurPhysAddr =
+ TranslateLinearAddress(process_dirbase, (ULONG64)Address + CurOffset);
+ if (!CurPhysAddr)
+ return STATUS_UNSUCCESSFUL;
+
+ ULONG64 WriteSize = MIN(PAGE_SIZE - (CurPhysAddr & 0xFFF), TotalSize);
+ SIZE_T BytesWritten = 0;
+ NtRet = WritePhysicalAddress((PVOID)CurPhysAddr,
+ (PVOID)((ULONG64)AllocatedBuffer + CurOffset),
+ WriteSize, &BytesWritten);
+ TotalSize -= BytesWritten;
+ CurOffset += BytesWritten;
+ if (NtRet != STATUS_SUCCESS)
+ break;
+ if (BytesWritten == 0)
+ break;
+ }
+
+ *written = CurOffset;
+ return NtRet;
+}
+
+NTSTATUS Experimental::ReadProcessMemory(_In_ HANDLE pid, _In_ uint64_t Address,
+ _In_ uint64_t AllocatedBuffer,
+ _In_ SIZE_T size, _Out_ SIZE_T *read) {
+ DbgPrintEx(0, 0, "\n[Read] Address is: %llx", Address);
+ PEPROCESS pProcess = NULL;
+ if (pid == NULL)
+ return STATUS_UNSUCCESSFUL;
+
+ NTSTATUS NtRet = PsLookupProcessByProcessId(pid, &pProcess);
+ if (NtRet != STATUS_SUCCESS)
+ return NtRet;
+
+ ULONG_PTR process_dirbase = GetProcessCr3(pProcess);
+ DbgPrintEx(0, 0, "\n[Read] DirBase is: %llx", process_dirbase);
+ ObDereferenceObject(pProcess);
+
+ SIZE_T CurOffset = 0;
+ SIZE_T TotalSize = size;
+ while (TotalSize) {
+ uint64_t CurPhysAddr =
+ TranslateLinearAddress(process_dirbase, (ULONG64)Address + CurOffset);
+ if (!CurPhysAddr)
+ return STATUS_UNSUCCESSFUL;
+
+ ULONG64 ReadSize = MIN(PAGE_SIZE - (CurPhysAddr & 0xFFF), TotalSize);
+ SIZE_T BytesRead = 0;
+ NtRet = ReadPhysicalAddress((PVOID)CurPhysAddr,
+ (PVOID)((ULONG64)AllocatedBuffer + CurOffset),
+ ReadSize, &BytesRead);
+ TotalSize -= BytesRead;
+ CurOffset += BytesRead;
+ if (NtRet != STATUS_SUCCESS)
+ break;
+ if (BytesRead == 0)
+ break;
+ }
+
+ *read = CurOffset;
+ return NtRet;
+}
+
+uint64_t
+Experimental::VirtualAddressToPhysicalAddress(_In_ PVOID VirtualAddress) {
+ return MmGetPhysicalAddress(VirtualAddress).QuadPart;
+}
+
+uint64_t
+Experimental::PhysicalAddressToVirtualAddress(_In_ uint64_t PhysicalAddress) {
+ PHYSICAL_ADDRESS PhysicalAddr = {};
+ PhysicalAddr.QuadPart = PhysicalAddress;
+
+ return reinterpret_cast<uint64_t>(MmGetVirtualForPhysical(PhysicalAddr));
+}
+#endif
+
void SetLdrInitWaitPrefs(int waitCount, LONGLONG waitTimeout) {
- g_waitCount = waitCount;
- g_waitTimeout = waitTimeout;
+ g_waitCount = waitCount;
+ g_waitTimeout = waitTimeout;
}
eastl::vector<Process> GetProcesses() {
@@ -116,13 +356,14 @@ eastl::vector<Process> GetProcesses() {
return result;
}
-NTSTATUS OpenProcess(_In_ HANDLE pid, _Out_ PEPROCESS *pep, _Out_ HANDLE *process) {
+NTSTATUS OpenProcess(_In_ HANDLE pid, _Out_ PEPROCESS *pep,
+ _Out_ HANDLE *process) {
NTSTATUS status = PsLookupProcessByProcessId(pid, pep);
if (NT_SUCCESS(status)) {
status = WrapperObOpenObjectByPointer(
- *pep, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, GENERIC_ALL | PROCESS_ALL_ACCESS,
- *PsProcessType, KernelMode, process);
+ *pep, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL,
+ GENERIC_ALL | PROCESS_ALL_ACCESS, *PsProcessType, KernelMode, process);
}
return status;
@@ -278,8 +519,7 @@ extern "C" int ehandler(_In_ EXCEPTION_POINTERS *ep) {
return EXCEPTION_EXECUTE_HANDLER;
}
-NTSTATUS ProtectVirtualMemory(_In_ PEPROCESS pep,
- _In_ uint64_t addr,
+NTSTATUS ProtectVirtualMemory(_In_ PEPROCESS pep, _In_ uint64_t addr,
_In_ SIZE_T size, _In_ ULONG newProt,
_Out_ ULONG *oldProt) {
KAPC_STATE apcState;
@@ -291,8 +531,8 @@ NTSTATUS ProtectVirtualMemory(_In_ PEPROCESS pep,
KeStackAttachProcess((PKPROCESS)pep, &apcState);
__dpptry(ehandler, pvm) {
- status =
- WrapperZwProtectVirtualMemory(ZwCurrentProcess(), &paddr, &psize, newProt, &prot);
+ status = WrapperZwProtectVirtualMemory(ZwCurrentProcess(), &paddr, &psize,
+ newProt, &prot);
*oldProt = prot;
}
__dppexcept(pvm) { status = STATUS_ACCESS_VIOLATION; }
@@ -314,8 +554,8 @@ NTSTATUS RestoreProtectVirtualMemory(_In_ PEPROCESS pep, _In_ uint64_t addr,
KeStackAttachProcess((PKPROCESS)pep, &apcState);
__dpptry(ehandler, rpvm) {
- status =
- WrapperZwProtectVirtualMemory(ZwCurrentProcess(), &paddr, &psize, old_prot, &prot);
+ status = WrapperZwProtectVirtualMemory(ZwCurrentProcess(), &paddr, &psize,
+ old_prot, &prot);
}
__dppexcept(rpvm) { status = STATUS_ACCESS_VIOLATION; }
__dpptryend(rpvm);
@@ -331,9 +571,9 @@ NTSTATUS ReadVirtualMemory(_In_ PEPROCESS pep, _In_ uint64_t sourceAddress,
SIZE_T bytes = 0;
__dpptry(ehandler, rvm) {
- status =
- WrapperMmCopyVirtualMemory(pep, (PVOID)sourceAddress, PsGetCurrentProcess(),
- (PVOID)targetAddress, *size, KernelMode, &bytes);
+ status = WrapperMmCopyVirtualMemory(
+ pep, (PVOID)sourceAddress, PsGetCurrentProcess(), (PVOID)targetAddress,
+ *size, KernelMode, &bytes);
}
__dppexcept(rvm) { status = STATUS_UNSUCCESSFUL; }
__dpptryend(rvm);
@@ -350,9 +590,9 @@ NTSTATUS WriteVirtualMemory(_In_ PEPROCESS pep, _In_ const UCHAR *sourceAddress,
SIZE_T bytes = 0;
__dpptry(ehandler, wvm) {
- status =
- WrapperMmCopyVirtualMemory(PsGetCurrentProcess(), (PVOID)sourceAddress, pep,
- (PVOID)targetAddress, *size, KernelMode, &bytes);
+ status = WrapperMmCopyVirtualMemory(
+ PsGetCurrentProcess(), (PVOID)sourceAddress, pep, (PVOID)targetAddress,
+ *size, KernelMode, &bytes);
}
__dppexcept(wvm) { status = STATUS_UNSUCCESSFUL; }
__dpptryend(wvm);
diff --git a/memory.hpp b/memory.hpp
index ff40d54..c8db72c 100644
--- a/memory.hpp
+++ b/memory.hpp
@@ -44,13 +44,13 @@ struct Page {
void SetLdrInitWaitPrefs(int waitCount, LONGLONG waitTimeout);
eastl::vector<Process> GetProcesses();
-NTSTATUS OpenProcess(_In_ HANDLE pid, _Out_ PEPROCESS *pep, _Out_ HANDLE *process);
+NTSTATUS OpenProcess(_In_ HANDLE pid, _Out_ PEPROCESS *pep,
+ _Out_ HANDLE *process);
NTSTATUS CloseProcess(_In_ _Out_ PEPROCESS *pep, _In_ _Out_ HANDLE *process);
eastl::vector<Page> GetPages(_In_ HANDLE obj, SIZE_T maxPages = 1024,
ULONG_PTR startAddress = 0);
eastl::vector<Module> GetModules(_In_ PEPROCESS Process, _In_ BOOLEAN isWow64);
-NTSTATUS ProtectVirtualMemory(_In_ PEPROCESS pep,
- _In_ uint64_t addr,
+NTSTATUS ProtectVirtualMemory(_In_ PEPROCESS pep, _In_ uint64_t addr,
_In_ SIZE_T size, _In_ ULONG newProt,
_Out_ ULONG *oldProt);
NTSTATUS RestoreProtectVirtualMemory(_In_ PEPROCESS pep, _In_ uint64_t addr,
@@ -61,89 +61,118 @@ NTSTATUS WriteVirtualMemory(_In_ PEPROCESS pep, _In_ const UCHAR *sourceAddress,
_Out_ uint64_t targetAddress,
_In_ _Out_ SIZE_T *size);
-auto get_process_cr3(PEPROCESS pe_process) -> uint64_t;
-auto swap_process(PEPROCESS new_process) -> PEPROCESS;
+#ifdef ENABLE_EXPERIMENTAL
+namespace Experimental {
+/*
+ * Copy Pasta from:
+ * https://www.unknowncheats.me/forum/anti-cheat-bypass/594858-updated-physical-mem-attach-paste-ready.html
+ */
+static constexpr uint8_t page_offset_size = 12;
+static constexpr uint64_t page_mask = (~0xfull << 8) & 0xfffffffffull;
+
+uint64_t GetProcessCr3(_In_ const PEPROCESS pe_process);
+PEPROCESS SwapProcess(_In_ PEPROCESS new_process);
+
+uint64_t GetUserDirectoryTableBaseOffset();
+NTSTATUS ReadPhysicalAddress(_In_ PVOID TargetAddress, _In_ PVOID lpBuffer,
+ _In_ SIZE_T Size, _Out_ SIZE_T *BytesRead);
+NTSTATUS WritePhysicalAddress(_In_ PVOID TargetAddress, _In_ PVOID lpBuffer,
+ _In_ SIZE_T Size, _Out_ SIZE_T *BytesWritten);
+uint64_t GetKernelDirBase();
+uint64_t TranslateLinearAddress(_In_ uint64_t directoryTableBase,
+ _In_ uint64_t virtualAddress);
+NTSTATUS WriteProcessMemory(_In_ HANDLE pid, _In_ uint64_t Address,
+ _In_ uint64_t AllocatedBuffer, _In_ SIZE_T size,
+ _Out_ SIZE_T *written);
+NTSTATUS ReadProcessMemory(_In_ HANDLE pid, _In_ uint64_t Address,
+ _In_ uint64_t AllocatedBuffer, _In_ SIZE_T size,
+ _Out_ SIZE_T *read);
+uint64_t VirtualAddressToPhysicalAddress(_In_ PVOID VirtualAddress);
+uint64_t PhysicalAddressToVirtualAddress(_In_ uint64_t PhysicalAddress);
+}; // namespace Experimental
+#endif
class Memory {
public:
- Memory(_In_ PEPROCESS& pep) : m_pep(pep) {
- ClearLastErrorAndSize();
- }
- Memory(const Memory&) = delete;
+ Memory(_In_ PEPROCESS &pep) : m_pep(pep) { ClearLastErrorAndSize(); }
+ Memory(const Memory &) = delete;
- void ClearLastErrorAndSize() {
- m_last_error = STATUS_SUCCESS;
- m_last_size = 0;
- }
+ void ClearLastErrorAndSize() {
+ m_last_error = STATUS_SUCCESS;
+ m_last_size = 0;
+ }
- static bool IsValidAddress(uint64_t address) {
- return address >= 0x10000 && address < 0x000F000000000000;
- }
+ static bool IsValidAddress(uint64_t address) {
+ return address >= 0x10000 && address < 0x000F000000000000;
+ }
- template<typename T>
- T Read(uint64_t sourceAddress) {
- if (!IsValidAddress(sourceAddress))
- return T();
- T value;
- SIZE_T size = sizeof(value);
- m_last_error = ReadVirtualMemory(m_pep, sourceAddress, reinterpret_cast<UCHAR*>(&value), &size);
- m_last_size = size;
- if (m_last_error == STATUS_SUCCESS && m_last_size == sizeof(T))
- return value;
- return T();
- }
+ template <typename T> T Read(uint64_t sourceAddress) {
+ if (!IsValidAddress(sourceAddress))
+ return T();
+ T value;
+ SIZE_T size = sizeof(value);
+ m_last_error = ReadVirtualMemory(m_pep, sourceAddress,
+ reinterpret_cast<UCHAR *>(&value), &size);
+ m_last_size = size;
+ if (m_last_error == STATUS_SUCCESS && m_last_size == sizeof(T))
+ return value;
+ return T();
+ }
- template<typename T>
- T ReadChain(uint64_t sourceAddress, const eastl::vector<uint64_t>& chainedOffsets) {
- for (const auto& offset : chainedOffsets) {
- if (offset == chainedOffsets.back())
- break;
- sourceAddress = Read<uint64_t>(sourceAddress + offset);
- if (!sourceAddress)
- break;
- }
- if (chainedOffsets.size() == 0)
- return Read<T>(sourceAddress);
- else
- return Read<T>(sourceAddress + chainedOffsets.back());
+ template <typename T>
+ T ReadChain(uint64_t sourceAddress,
+ const eastl::vector<uint64_t> &chainedOffsets) {
+ for (const auto &offset : chainedOffsets) {
+ if (offset == chainedOffsets.back())
+ break;
+ sourceAddress = Read<uint64_t>(sourceAddress + offset);
+ if (!sourceAddress)
+ break;
}
+ if (chainedOffsets.size() == 0)
+ return Read<T>(sourceAddress);
+ else
+ return Read<T>(sourceAddress + chainedOffsets.back());
+ }
- template<typename T, size_t N>
- bool ReadBuffer(uint64_t sourceAddress, T out[N]) {
- if (!IsValidAddress(sourceAddress))
- return false;
- SIZE_T size = sizeof(T) * N;
- m_last_error = ReadVirtualMemory(m_pep, sourceAddress, reinterpret_cast<UCHAR*>(out), &size);
- m_last_size = size;
- return Succeeded<T, N>();
- }
+ template <typename T, size_t N>
+ bool ReadBuffer(uint64_t sourceAddress, T out[N]) {
+ if (!IsValidAddress(sourceAddress))
+ return false;
+ SIZE_T size = sizeof(T) * N;
+ m_last_error = ReadVirtualMemory(m_pep, sourceAddress,
+ reinterpret_cast<UCHAR *>(out), &size);
+ m_last_size = size;
+ return Succeeded<T, N>();
+ }
- template<size_t N>
- bool ReadString(uint64_t sourceAddress, char out[N]) {
- const auto retval = ReadBuffer<char, N-1>(sourceAddress, out);
- out[m_last_size] = '\0';
- return retval;
- }
+ template <size_t N> bool ReadString(uint64_t sourceAddress, char out[N]) {
+ const auto retval = ReadBuffer<char, N - 1>(sourceAddress, out);
+ out[m_last_size] = '\0';
+ return retval;
+ }
- template<typename T>
- bool Write(uint64_t targetAddress, const T& writeData) {
- if (!IsValidAddress(targetAddress))
- return false;
- SIZE_T size = sizeof(T);
- m_last_error = WriteVirtualMemory(m_pep, reinterpret_cast<const UCHAR*>(&writeData), targetAddress, &size);
- m_last_size = size;
- return Succeeded<T, 1>();
- }
+ template <typename T> bool Write(uint64_t targetAddress, const T &writeData) {
+ if (!IsValidAddress(targetAddress))
+ return false;
+ SIZE_T size = sizeof(T);
+ m_last_error =
+ WriteVirtualMemory(m_pep, reinterpret_cast<const UCHAR *>(&writeData),
+ targetAddress, &size);
+ m_last_size = size;
+ return Succeeded<T, 1>();
+ }
- template<typename T, size_t N>
- bool Succeeded() { return m_last_error == STATUS_SUCCESS && m_last_size == sizeof(T) * N; }
+ template <typename T, size_t N> bool Succeeded() {
+ return m_last_error == STATUS_SUCCESS && m_last_size == sizeof(T) * N;
+ }
- NTSTATUS LastError() { return m_last_error; }
- SIZE_T LastSize() { return m_last_size; }
+ NTSTATUS LastError() { return m_last_error; }
+ SIZE_T LastSize() { return m_last_size; }
private:
- PEPROCESS& m_pep;
- NTSTATUS m_last_error;
- SIZE_T m_last_size;
+ PEPROCESS &m_pep;
+ NTSTATUS m_last_error;
+ SIZE_T m_last_size;
};
#endif
diff --git a/native.h b/native.h
index 84e1ad4..5e293e8 100644
--- a/native.h
+++ b/native.h
@@ -1,6 +1,9 @@
#ifndef NATIVE_H
#define NATIVE_H 1
+#define MM_COPY_MEMORY_PHYSICAL 0x1
+#define MM_COPY_MEMORY_VIRTUAL 0x2
+
// QuerySystemInformation
typedef enum _SYSTEM_INFORMATION_CLASS {
@@ -168,4 +171,11 @@ typedef struct _PEB {
PVOID ApiSetMap;
} PEB, *PPEB;
+typedef struct _MM_COPY_ADDRESS {
+ union {
+ PVOID VirtualAddress;
+ PHYSICAL_ADDRESS PhysicalAddress;
+ };
+} MM_COPY_ADDRESS, *PMMCOPY_ADDRESS;
+
#endif