diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2024-05-29 00:26:09 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2024-05-29 10:49:32 +0200 |
commit | 8bdef10098cbdb9f010afb68f24ca715bc4afcec (patch) | |
tree | 317fc135e6be93ae09a0d9d4289e1e209203a57a | |
parent | 0ab8e3189dd1b63a76d15562b00a0c31d40260f7 (diff) |
Added some "Experimental" functionality.
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r-- | Makefile | 11 | ||||
-rw-r--r-- | memory.cpp | 316 | ||||
-rw-r--r-- | memory.hpp | 173 | ||||
-rw-r--r-- | native.h | 10 |
4 files changed, 399 insertions, 111 deletions
@@ -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 @@ -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); @@ -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 @@ -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 |