-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathMemoryHelper.cpp
More file actions
201 lines (176 loc) · 5.43 KB
/
MemoryHelper.cpp
File metadata and controls
201 lines (176 loc) · 5.43 KB
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#include <windows.h>
#include <vector>
#include <cstdint>
#include <algorithm>
#include <functional>
bool IsValidMemoryRange(LPCVOID address, int length)
{
auto endAddress = static_cast<const uint8_t*>(address) + length;
do
{
MEMORY_BASIC_INFORMATION info;
if (!VirtualQuery(address, &info, sizeof(MEMORY_BASIC_INFORMATION)))
{
return false;
}
if (info.State != MEM_COMMIT)
{
return false;
}
switch (info.Protect)
{
case PAGE_EXECUTE_READ:
case PAGE_EXECUTE_READWRITE:
case PAGE_EXECUTE_WRITECOPY:
case PAGE_READONLY:
case PAGE_READWRITE:
case PAGE_WRITECOPY:
break;
default:
return false;
}
address = (uint8_t*)info.BaseAddress + info.RegionSize;
} while (endAddress > address);
return true;
}
//---------------------------------------------------------------------------
bool ReadMemory(LPCVOID address, std::vector<uint8_t>& buffer)
{
if (!IsValidMemoryRange(address, (int)buffer.size()))
{
return false;
}
std::memcpy(buffer.data(), address, buffer.size());
return true;
}
//---------------------------------------------------------------------------
bool WriteMemory(LPVOID address, const std::vector<uint8_t>& buffer)
{
if (!IsValidMemoryRange(address, (int)buffer.size()))
{
return false;
}
DWORD oldProtect;
if (VirtualProtect(address, buffer.size(), PAGE_EXECUTE_READWRITE, &oldProtect))
{
std::memcpy(address, buffer.data(), buffer.size());
VirtualProtect(address, buffer.size(), oldProtect, nullptr);
return true;
}
return false;
}
//---------------------------------------------------------------------------
void EnumerateRemoteSectionsAndModules(const std::function<void(const void*, const void*, std::wstring&&)>& moduleCallback, const std::function<void(const void*, const void*, std::wstring&&, int, int, int, std::wstring&&)>& sectionCallback)
{
struct SectionInfo
{
LPVOID BaseAddress;
SIZE_T RegionSize;
WCHAR Name[IMAGE_SIZEOF_SHORT_NAME + 1];
DWORD State;
DWORD Protection;
DWORD Type;
WCHAR ModulePath[260];
};
std::vector<SectionInfo> sections;
// First enumerate all memory sections.
MEMORY_BASIC_INFORMATION memInfo = { 0 };
memInfo.RegionSize = 0x1000;
size_t address = 0;
while (VirtualQuery((LPCVOID)address, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) != 0 && address + memInfo.RegionSize > address)
{
if (memInfo.State == MEM_COMMIT)
{
SectionInfo section = {};
section.BaseAddress = memInfo.BaseAddress;
section.RegionSize = memInfo.RegionSize;
section.State = memInfo.State;
section.Protection = memInfo.Protect;
section.Type = memInfo.Type;
sections.push_back(std::move(section));
}
address = (size_t)memInfo.BaseAddress + memInfo.RegionSize;
}
struct UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
};
struct LDR_MODULE
{
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID BaseAddress;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
};
struct PEB_LDR_DATA
{
ULONG Length;
BOOLEAN Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
};
struct PEB
{
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
BOOLEAN Spare;
HANDLE Mutant;
PVOID ImageBaseAddress;
PEB_LDR_DATA *LoaderData;
};
// Second enumerate all modules.
#ifdef _WIN64
auto peb = reinterpret_cast<PEB*>(__readgsqword(0x60));
#else
auto peb = reinterpret_cast<PEB*>(__readfsdword(0x30));
#endif
auto ldr = reinterpret_cast<LDR_MODULE*>(peb->LoaderData->InLoadOrderModuleList.Flink);
while (ldr->BaseAddress != nullptr)
{
moduleCallback(ldr->BaseAddress, (const void*)(intptr_t)ldr->SizeOfImage, ldr->FullDllName.Buffer);
auto it = std::lower_bound(std::begin(sections), std::end(sections), ldr->BaseAddress, [§ions](const SectionInfo& lhs, const LPVOID& rhs)
{
return lhs.BaseAddress < rhs;
});
auto dosHeader = reinterpret_cast<IMAGE_DOS_HEADER*>(ldr->BaseAddress);
auto ntHeader = reinterpret_cast<IMAGE_NT_HEADERS*>((intptr_t)ldr->BaseAddress + dosHeader->e_lfanew);
int i = 0;
for (auto sectionHeader = IMAGE_FIRST_SECTION(ntHeader); i < ntHeader->FileHeader.NumberOfSections; i++, sectionHeader++)
{
auto sectionAddress = (intptr_t)ldr->BaseAddress + (intptr_t)sectionHeader->VirtualAddress;
for (auto j = it; j != std::end(sections); ++j)
{
if (sectionAddress >= (intptr_t)j->BaseAddress && sectionAddress < (intptr_t)j->BaseAddress + (intptr_t)j->RegionSize)
{
// Copy the name because it is not null padded.
char buffer[IMAGE_SIZEOF_SHORT_NAME + 1] = { 0 };
std::memcpy(buffer, sectionHeader->Name, IMAGE_SIZEOF_SHORT_NAME);
size_t convertedChars = 0;
mbstowcs_s(&convertedChars, j->Name, IMAGE_SIZEOF_SHORT_NAME, buffer, _TRUNCATE);
std::memcpy(j->ModulePath, ldr->FullDllName.Buffer, sizeof(SectionInfo::ModulePath));
break;
}
}
}
ldr = reinterpret_cast<LDR_MODULE*>(ldr->InLoadOrderModuleList.Flink);
}
for (auto&& section : sections)
{
sectionCallback(section.BaseAddress, (const void*)section.RegionSize, section.Name, section.State, section.Protection, section.Type, section.ModulePath);
}
}
//---------------------------------------------------------------------------