Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
axstin
GitHub Repository: axstin/rbxfpsunlocker
Path: blob/master/Source/procutil.cpp
259 views
1
#include "procutil.h"
2
3
#include <TlHelp32.h>
4
#include <filesystem>
5
6
#include "sigscan.h"
7
8
#define READ_LIMIT (1024 * 1024 * 2) // 2 MB
9
10
std::vector<DWORD> ProcUtil::GetProcessIdsByImageName(const char *image_name, size_t limit)
11
{
12
std::vector<DWORD> result;
13
14
PROCESSENTRY32 entry;
15
entry.dwSize = sizeof(PROCESSENTRY32);
16
17
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
18
size_t count = 0;
19
20
if (Process32First(snapshot, &entry) == TRUE)
21
{
22
while (count < limit && Process32Next(snapshot, &entry) == TRUE)
23
{
24
if (_stricmp(entry.szExeFile, image_name) == 0)
25
{
26
result.push_back(entry.th32ProcessID);
27
count++;
28
}
29
}
30
}
31
32
CloseHandle(snapshot);
33
return result;
34
}
35
36
std::vector<HANDLE> ProcUtil::GetProcessesByImageName(const char *image_name, DWORD access, size_t limit)
37
{
38
std::vector<HANDLE> result;
39
40
for (DWORD pid : GetProcessIdsByImageName(image_name, limit))
41
{
42
if (HANDLE process = OpenProcess(access, FALSE, pid))
43
{
44
result.push_back(process);
45
}
46
}
47
48
return result;
49
}
50
51
HANDLE ProcUtil::GetProcessByImageName(const char* image_name)
52
{
53
auto processes = GetProcessesByImageName(image_name, 1);
54
return processes.size() > 0 ? processes[0] : NULL;
55
}
56
57
std::vector<ProcUtil::ModuleInfo> ProcUtil::GetProcessModules(DWORD process_id, size_t limit)
58
{
59
if (!process_id) return {};
60
61
std::vector<ProcUtil::ModuleInfo> result;
62
63
MODULEENTRY32W entry;
64
entry.dwSize = sizeof(MODULEENTRY32W);
65
66
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, process_id);
67
if (snapshot == INVALID_HANDLE_VALUE)
68
{
69
printf("[ProcUtil] GetProcessModules(%u, ...) could not create snapshot: %X\n", process_id, GetLastError());
70
}
71
else
72
{
73
if (Module32FirstW(snapshot, &entry) == TRUE)
74
{
75
do
76
{
77
ProcUtil::ModuleInfo info{};
78
info.path = entry.szExePath;
79
info.base = entry.modBaseAddr;
80
info.size = entry.modBaseSize;
81
result.push_back(std::move(info));
82
}
83
while (result.size() < limit && Module32NextW(snapshot, &entry) == TRUE);
84
}
85
86
CloseHandle(snapshot);
87
}
88
return result;
89
}
90
91
92
ProcUtil::ModuleInfo ProcUtil::GetMainModuleInfo(HANDLE process)
93
{
94
char buffer[MAX_PATH];
95
DWORD size = sizeof(buffer);
96
97
if (!QueryFullProcessImageName(process, 0, buffer, &size)) // Requires at least PROCESS_QUERY_LIMITED_INFORMATION
98
return {};
99
100
ModuleInfo result{};
101
bool found;
102
103
printf("[ProcUtil] QueryFullProcessImageName(%p) returned %s\n", process, buffer);
104
105
try
106
{
107
found = FindModuleInfo(process, buffer, result);
108
}
109
catch (WindowsException& e)
110
{
111
printf("[ProcUtil] GetModuleInfo(%p, NULL) failed: %s (%X)\n", process, e.what(), e.GetLastError());
112
found = false;
113
}
114
115
if (!found) // Couldn't enum modules or GetModuleFileNameEx/GetModuleInformation failed
116
{
117
result.path = buffer;
118
result.base = nullptr;
119
result.size = 0;
120
}
121
122
return result;
123
}
124
125
bool ProcUtil::FindModuleInfo(HANDLE process, const std::filesystem::path& path, ModuleInfo& out)
126
{
127
printf("[ProcUtil] FindModuleInfo(%p, %s)\n", process, path.string().c_str());
128
129
for (const auto &info : GetProcessModules(GetProcessId(process)))
130
{
131
try
132
{
133
printf("\tbase=%p, size=%zu, path=%s\n", info.base, info.size, info.path.string().c_str());
134
135
if (std::filesystem::equivalent(info.path, path))
136
{
137
out = info;
138
return true;
139
}
140
}
141
catch (std::filesystem::filesystem_error& e)
142
{
143
}
144
}
145
146
return false;
147
}
148
149
void *ScanRegion(HANDLE process, const char *aob, const char *mask, const uint8_t *base, size_t size)
150
{
151
std::vector<uint8_t> buffer;
152
buffer.resize(READ_LIMIT);
153
154
size_t aob_len = strlen(mask);
155
156
while (size >= aob_len)
157
{
158
size_t bytes_read = 0;
159
160
if (ReadProcessMemory(process, base, buffer.data(), size < buffer.size() ? size : buffer.size(), (SIZE_T *)&bytes_read) && bytes_read >= aob_len)
161
{
162
if (uint8_t *result = sigscan::scan(aob, mask, (uintptr_t)buffer.data(), (uintptr_t)buffer.data() + bytes_read))
163
{
164
return (uint8_t *)base + (result - buffer.data());
165
}
166
}
167
else
168
{
169
return nullptr;
170
}
171
172
if (bytes_read > aob_len) bytes_read -= aob_len;
173
174
size -= bytes_read;
175
base += bytes_read;
176
}
177
178
return nullptr;
179
}
180
181
182
void *ProcUtil::ScanProcess(HANDLE process, const char *aob, const char *mask, const uint8_t *start, const uint8_t *end)
183
{
184
auto i = start;
185
186
while (i < end)
187
{
188
MEMORY_BASIC_INFORMATION mbi;
189
if (!VirtualQueryEx(process, i, &mbi, sizeof(mbi)))
190
{
191
return nullptr;
192
}
193
194
size_t size = mbi.RegionSize - (i - (const uint8_t *)mbi.BaseAddress);
195
if (i + size >= end) size = end - i;
196
197
if (mbi.State & MEM_COMMIT && mbi.Protect & PAGE_READABLE && !(mbi.Protect & PAGE_GUARD))
198
{
199
if (void *result = ScanRegion(process, aob, mask, i, size))
200
{
201
return result;
202
}
203
}
204
205
i += size;
206
}
207
208
return nullptr;
209
}
210
211
bool ProcUtil::IsOS64Bit()
212
{
213
#ifdef _WIN64
214
return true;
215
#else
216
SYSTEM_INFO info;
217
GetNativeSystemInfo(&info);
218
219
return info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ||
220
info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64; // lol arm
221
#endif
222
}
223
224
bool ProcUtil::IsProcess64Bit(HANDLE process)
225
{
226
if (IsOS64Bit())
227
{
228
BOOL result;
229
if (!IsWow64Process(process, &result))
230
throw WindowsException("unable to check process wow64");
231
232
return result == 0;
233
}
234
else
235
{
236
return false;
237
}
238
}
239
240