-
-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: use protect check instead of state for region scanner (#23)
- Loading branch information
Showing
1 changed file
with
119 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,137 +1,146 @@ | ||
#pragma once | ||
|
||
// clang-format off | ||
#include <Windows.h> | ||
#include <string> | ||
#include <Psapi.h> | ||
// clang-format on | ||
#include <string> | ||
#include <tlhelp32.h> | ||
#include <vector> | ||
#include <winnt.h> | ||
|
||
#pragma comment(lib, "Psapi.lib") | ||
|
||
namespace memory { | ||
template <class T> | ||
inline std::tuple<T, bool> read(HANDLE hProcess, uintptr_t address) { | ||
T value; | ||
auto result = ReadProcessMemory(hProcess, reinterpret_cast<void*>(address), &value, sizeof(T), 0); | ||
return {value, result}; | ||
namespace memory { | ||
|
||
template <class T> | ||
inline std::tuple<T, bool> read(HANDLE hProcess, uintptr_t address) { | ||
T value; | ||
auto result = ReadProcessMemory(hProcess, reinterpret_cast<void *>(address), | ||
&value, sizeof(T), 0); | ||
return {value, result}; | ||
} | ||
|
||
inline bool read_buffer(HANDLE hProcess, uintptr_t address, size_t size, | ||
char *dstBuffer) { | ||
return ReadProcessMemory(hProcess, reinterpret_cast<void *>(address), | ||
dstBuffer, size, 0) == 1; | ||
} | ||
|
||
inline uintptr_t get_base_address(HANDLE process) { | ||
MODULEINFO mi; | ||
if (GetModuleInformation(process, nullptr, &mi, sizeof(mi))) | ||
return (uintptr_t)mi.EntryPoint; | ||
return 0; | ||
} | ||
|
||
inline uint32_t scan(const std::vector<uint8_t> buffer, | ||
const std::vector<uint8_t> signature) { | ||
for (int i = 0; i + signature.size() <= buffer.size(); i++) { | ||
bool found = true; | ||
for (int j = 0; j < signature.size(); j++) { | ||
if (buffer[i + j] != signature[j] && signature[j] != 0x00) { | ||
found = false; | ||
break; | ||
} | ||
} | ||
|
||
inline bool read_buffer(HANDLE hProcess, uintptr_t address, size_t size, char* dstBuffer) { | ||
return ReadProcessMemory(hProcess, reinterpret_cast<void*>(address), dstBuffer, size, 0) == 1; | ||
if (found) { | ||
return i; | ||
} | ||
|
||
inline uintptr_t get_base_address(HANDLE process) | ||
{ | ||
MODULEINFO mi; | ||
if (GetModuleInformation(process, nullptr, &mi, sizeof(mi))) | ||
return (uintptr_t)mi.EntryPoint; | ||
return 0; | ||
} | ||
|
||
return -1; | ||
} | ||
|
||
static std::vector<MEMORY_BASIC_INFORMATION> regions; | ||
static bool regionFlag; | ||
|
||
inline void cache_regions(HANDLE process) { | ||
regions.clear(); | ||
uintptr_t address = 0; | ||
MEMORY_BASIC_INFORMATION mbi; | ||
while (VirtualQueryEx(process, reinterpret_cast<void *>(address), &mbi, | ||
sizeof(mbi))) { | ||
if (mbi.Protect == PAGE_EXECUTE_READWRITE || | ||
mbi.Protect == PAGE_READWRITE) { | ||
regions.push_back(mbi); | ||
} | ||
|
||
inline uint32_t scan(const std::vector<uint8_t> buffer, const std::vector<uint8_t> signature) { | ||
for (int i = 0; i + signature.size() <= buffer.size(); i++) { | ||
bool found = true; | ||
for (int j = 0; j < signature.size(); j++) { | ||
if (buffer[i + j] != signature[j] && signature[j] != 0x00) { | ||
found = false; | ||
break; | ||
} | ||
} | ||
|
||
if (found) { | ||
return i; | ||
} | ||
} | ||
|
||
return -1; | ||
} | ||
address = reinterpret_cast<uintptr_t>(mbi.BaseAddress) + mbi.RegionSize; | ||
} | ||
} | ||
|
||
static std::vector<MEMORY_BASIC_INFORMATION> regions; | ||
static bool regionFlag; | ||
inline DWORD find_pattern(HANDLE process, const std::vector<uint8_t> signature, | ||
bool refresh = false, int baseAddress = 0) { | ||
if (refresh) | ||
regionFlag = false; | ||
|
||
inline void cache_regions(HANDLE process) { | ||
regions.clear(); | ||
uintptr_t address = 0; | ||
MEMORY_BASIC_INFORMATION mbi; | ||
while (VirtualQueryEx(process, reinterpret_cast<void*>(address), &mbi, sizeof(mbi))) { | ||
if (mbi.State != MEM_FREE && (mbi.Protect & PAGE_GUARD) == 0) { | ||
regions.push_back(mbi); | ||
} | ||
if (!regionFlag) { | ||
cache_regions(process); | ||
regionFlag = true; | ||
} | ||
|
||
address = reinterpret_cast<uintptr_t>(mbi.BaseAddress) + mbi.RegionSize; | ||
} | ||
} | ||
|
||
inline DWORD find_pattern(HANDLE process, const std::vector<uint8_t> signature, bool refresh = false, int baseAddress = 0) { | ||
if (refresh) | ||
regionFlag = false; | ||
|
||
if (!regionFlag) { | ||
cache_regions(process); | ||
regionFlag = true; | ||
} | ||
|
||
MEMORY_BASIC_INFORMATION mbi; | ||
auto size = sizeof(mbi); | ||
|
||
for (auto& region : regions) { | ||
auto regionSize = region.RegionSize; | ||
auto regionAddress = (uintptr_t)region.BaseAddress; | ||
|
||
if (regionAddress < baseAddress) | ||
continue; | ||
|
||
if (regionSize > 10000000) | ||
continue; | ||
|
||
auto buffer = std::vector<uint8_t>(regionSize); | ||
ReadProcessMemory(process, (void*)regionAddress, buffer.data(), regionSize, 0); | ||
|
||
auto offset = scan(buffer, signature); | ||
if (offset != -1) { | ||
return regionAddress + offset; | ||
} | ||
} | ||
|
||
return 0; | ||
MEMORY_BASIC_INFORMATION mbi; | ||
auto size = sizeof(mbi); | ||
|
||
for (auto ®ion : regions) { | ||
auto regionSize = region.RegionSize; | ||
auto regionAddress = (uintptr_t)region.BaseAddress; | ||
|
||
if (regionAddress < baseAddress) | ||
continue; | ||
|
||
auto buffer = std::vector<uint8_t>(regionSize); | ||
ReadProcessMemory(process, (void *)regionAddress, buffer.data(), regionSize, | ||
0); | ||
|
||
auto offset = scan(buffer, signature); | ||
if (offset != -1) { | ||
return regionAddress + offset; | ||
} | ||
} | ||
|
||
inline std::vector<uint32_t> find_processes(const std::string& process_name) { | ||
PROCESSENTRY32 processEntry; | ||
processEntry.dwSize = sizeof(PROCESSENTRY32); | ||
return 0; | ||
} | ||
|
||
std::vector<uint32_t> processes; | ||
inline std::vector<uint32_t> find_processes(const std::string &process_name) { | ||
PROCESSENTRY32 processEntry; | ||
processEntry.dwSize = sizeof(PROCESSENTRY32); | ||
|
||
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); | ||
if (Process32First(snapshot, &processEntry)) { | ||
do { | ||
if (process_name == processEntry.szExeFile) { | ||
processes.push_back(processEntry.th32ProcessID); | ||
} | ||
} while (Process32Next(snapshot, &processEntry)); | ||
} | ||
std::vector<uint32_t> processes; | ||
|
||
CloseHandle(snapshot); | ||
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); | ||
if (Process32First(snapshot, &processEntry)) { | ||
do { | ||
if (process_name == processEntry.szExeFile) { | ||
processes.push_back(processEntry.th32ProcessID); | ||
} | ||
} while (Process32Next(snapshot, &processEntry)); | ||
} | ||
|
||
return processes; | ||
} | ||
CloseHandle(snapshot); | ||
|
||
inline HANDLE open_process(uint32_t id) { | ||
return OpenProcess(PROCESS_ALL_ACCESS, FALSE, id); | ||
} | ||
return processes; | ||
} | ||
|
||
inline bool is_process_exist(HANDLE handle) { | ||
DWORD returnCode{}; | ||
if (GetExitCodeProcess(handle, &returnCode)) { | ||
return returnCode == STILL_ACTIVE; | ||
} | ||
return false; | ||
} | ||
inline HANDLE open_process(uint32_t id) { | ||
return OpenProcess(PROCESS_ALL_ACCESS, FALSE, id); | ||
} | ||
|
||
inline std::string get_process_path(HANDLE handle) { | ||
char filePath[MAX_PATH]; | ||
GetModuleFileNameExA(handle, NULL, filePath, MAX_PATH); | ||
inline bool is_process_exist(HANDLE handle) { | ||
DWORD returnCode{}; | ||
if (GetExitCodeProcess(handle, &returnCode)) { | ||
return returnCode == STILL_ACTIVE; | ||
} | ||
return false; | ||
} | ||
|
||
return filePath; | ||
} | ||
} | ||
inline std::string get_process_path(HANDLE handle) { | ||
char filePath[MAX_PATH]; | ||
GetModuleFileNameExA(handle, NULL, filePath, MAX_PATH); | ||
|
||
return filePath; | ||
} | ||
|
||
} // namespace memory |