/
Fail.Memory.Local.hpp
135 lines (115 loc) · 3.51 KB
/
Fail.Memory.Local.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#pragma once
#pragma warning (push)
#pragma warning (disable : 4482)
#include <Windows.h>
#include <TlHelp32.h>
#include "Fail.Exception.hpp"
#include "Fail.Loops.hpp"
#include "Fail.Types.hpp"
namespace Fail
{
namespace Memory
{
// Memory Protection
enum Protection : unsigned int
{
NoAccess = 0x1,
Read = 0x2,
ReadWrite = 0x4,
WriteCopy = 0x8,
Execute = 0x10,
ExecuteRead = 0x20,
ExecuteReadWrite = 0x40,
ExecuteWriteCopy = 0x80
};
// Functions for local process memory editing
namespace Local
{
// Get an object and return by reference
template <typename Type>
inline Type& get (uint Address)
{
return *reinterpret_cast<Type*>(Address.AsPointer());
}
// Get a pointer to the main module
inline uint GetMainModule ()
{
return GetModuleHandle(nullptr);
}
// Get a pointer to a module
inline uint GetModule (const char* Module)
{
return GetModuleHandle(Module);
}
// Get a handle to the main thread
inline void* GetMainThread ()
{
THREADENTRY32 Thread;
ZeroMemory(&Thread, sizeof(Thread));
Thread.dwSize = sizeof(Thread);
void* Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, GetCurrentProcessId());
Thread32Next(Snapshot, &Thread);
if(Thread.th32OwnerProcessID != GetCurrentProcessId())
{
throw exception("Unable to get main thread.");
}
CloseHandle(Snapshot);
return OpenThread(THREAD_ALL_ACCESS, false, Thread.th32ThreadID);
}
// Protect memory and return the old protection
inline Protection Protect (uint Address, uint Size, Protection NewProtection)
{
unsigned long OldProtection = 0;
if(VirtualProtect(Address.AsPointer(), Size, NewProtection, &OldProtection) == 0)
{
throw exception("Unable to change memory protection: VirtualProtect failed.");
}
return Protection(OldProtection);
}
// Read a copy of an object from memory
template <typename Type>
Type& ReadCopy (uint Address)
{
Type Object;
Protection OldProtection = Protect(Address, sizeof(Object), Protection::WriteCopy);
memcpy(&Object, Address.AsPointer(), sizeof(Object));
Protect(Address, sizeof(Object), OldProtection);
return Object;
}
// Read an object from memory. The memory must be readable already.
template <typename Type>
inline Type& Read (uint Address)
{
return *reinterpret_cast<Type*>(Address.AsPointer());
}
// Write an object into memory
template <typename Type>
void Write (uint Address, const Type& Object)
{
Protection OldProtection = Protect(Address, sizeof(Object), Protection::ReadWrite);
memcpy(Address.AsPointer(), &Object, sizeof(Object));
if(*reinterpret_cast<const unsigned char*>(Address.AsPointer()) != *reinterpret_cast<const unsigned char*>(&Object))
{
throw exception("Memory write failed.");
}
Protect(Address, sizeof(Object), OldProtection);
FlushInstructionCache(GetCurrentProcess(), Address.AsPointer(), sizeof(Object));
return;
}
// Write an array of bytes into memory
inline void Write (uint Address, const unsigned char* Bytes, uint Size)
{
Protection OldProtection = Protect(Address, Size, Protection::ReadWrite);
memcpy(Address.AsPointer(), Bytes, Size);
if(*reinterpret_cast<unsigned char*>(Address.AsPointer()) != Bytes[0])
{
throw exception("Memory write failed.");
}
Protect(Address, Size, OldProtection);
FlushInstructionCache(GetCurrentProcess(), Address.AsPointer(), Size);
return;
}
}
}
}
#pragma warning (pop)