#include "memory.hpp" #include #include "handle_hijack.hpp" uint32_t pProcess::FindProcessIdByProcessName(const char* ProcessName) { std::wstring wideProcessName; int wideCharLength = MultiByteToWideChar(CP_UTF8, 0, ProcessName, -1, nullptr, 0); if (wideCharLength > 0) { wideProcessName.resize(wideCharLength); MultiByteToWideChar(CP_UTF8, 0, ProcessName, -1, &wideProcessName[0], wideCharLength); } HANDLE hPID = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); PROCESSENTRY32W process_entry_{ }; process_entry_.dwSize = sizeof(PROCESSENTRY32W); DWORD pid = 0; if (Process32FirstW(hPID, &process_entry_)) { do { if (!wcscmp(process_entry_.szExeFile, wideProcessName.c_str())) { pid = process_entry_.th32ProcessID; break; } } while (Process32NextW(hPID, &process_entry_)); } CloseHandle(hPID); return pid; } uint32_t pProcess::FindProcessIdByWindowName(const char* WindowName) { DWORD process_id = 0; HWND windowHandle = FindWindowA(nullptr, WindowName); if (windowHandle) GetWindowThreadProcessId(windowHandle, &process_id); return process_id; } HWND pProcess::GetWindowHandleFromProcessId(DWORD ProcessId) { HWND hwnd = NULL; do { hwnd = FindWindowEx(NULL, hwnd, NULL, NULL); DWORD pid = 0; GetWindowThreadProcessId(hwnd, &pid); if (pid == ProcessId) { TCHAR windowTitle[MAX_PATH]; GetWindowText(hwnd, windowTitle, MAX_PATH); if (IsWindowVisible(hwnd) && windowTitle[0] != '\0') { return hwnd; } } } while (hwnd != NULL); return NULL; // No main window found for the given process ID } HANDLE OpenProcessNt(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId) { // At last is same with "OpenProcess", but we call NativeAPI instead of WindowsAPI directly. HANDLE hProcess = 0; _NtOpenProcess NtOpenProcess = (_NtOpenProcess)GetProcAddress( GetModuleHandleA("ntdll.dll"), "NtOpenProcess"); CLIENT_ID clientId = {(HANDLE)dwProcessId, NULL}; OBJECT_ATTRIBUTES objAttr = hj::InitObjectAttributes(NULL, 0, NULL, NULL); NtOpenProcess(&hProcess, dwDesiredAccess, &objAttr, &clientId); return hProcess; } bool pProcess::AttachProcess(const char* ProcessName) { this->pid_ = this->FindProcessIdByProcessName(ProcessName); if (pid_) { HMODULE modules[0xFF]; MODULEINFO module_info; DWORD _; handle_ = OpenProcessNt(PROCESS_QUERY_INFORMATION |PROCESS_VM_OPERATION | PROCESS_VM_READ,FALSE, pid_); EnumProcessModulesEx(this->handle_, modules, sizeof(modules), &_, LIST_MODULES_64BIT); base_client_.base = (uintptr_t)modules[0]; GetModuleInformation(this->handle_, modules[0], &module_info, sizeof(module_info)); base_client_.size = module_info.SizeOfImage; hwnd_ = this->GetWindowHandleFromProcessId(pid_); return true; } return false; } bool pProcess::AttachProcessHj(const char* ProcessName) { this->pid_ = this->FindProcessIdByProcessName(ProcessName); if (pid_) { HMODULE modules[0xFF]; MODULEINFO module_info; DWORD _; // Using Apxaey's handle hijack function to safely open a handle handle_ = hj::HijackExistingHandle(pid_); if (!hj::IsHandleValid(handle_)) { std::cout << "[cheat] Handle Hijack failed, falling back to OpenProcess method." << std::endl; return pProcess::AttachProcess(ProcessName); // Handle hijacking failed, so we fall back to the normal OpenProcess method } EnumProcessModulesEx(this->handle_, modules, sizeof(modules), &_, LIST_MODULES_64BIT); base_client_.base = (uintptr_t)modules[0]; GetModuleInformation(this->handle_, modules[0], &module_info, sizeof(module_info)); base_client_.size = module_info.SizeOfImage; hwnd_ = this->GetWindowHandleFromProcessId(pid_); return true; } return false; } bool pProcess::AttachWindow(const char* WindowName) { this->pid_ = this->FindProcessIdByWindowName(WindowName); if (pid_) { HMODULE modules[0xFF]; MODULEINFO module_info; DWORD _; handle_ = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid_); EnumProcessModulesEx(this->handle_, modules, sizeof(modules), &_, LIST_MODULES_64BIT); base_client_.base = (uintptr_t)modules[0]; GetModuleInformation(this->handle_, modules[0], &module_info, sizeof(module_info)); base_client_.size = module_info.SizeOfImage; hwnd_ = this->GetWindowHandleFromProcessId(pid_); return true; } return false; } bool pProcess::UpdateHWND() { hwnd_ = this->GetWindowHandleFromProcessId(pid_); return hwnd_ == nullptr; } ProcessModule pProcess::GetModule(const char* lModule) { std::wstring wideModule; int wideCharLength = MultiByteToWideChar(CP_UTF8, 0, lModule, -1, nullptr, 0); if (wideCharLength > 0) { wideModule.resize(wideCharLength); MultiByteToWideChar(CP_UTF8, 0, lModule, -1, &wideModule[0], wideCharLength); } HANDLE handle_module = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid_); MODULEENTRY32W module_entry_{}; module_entry_.dwSize = sizeof(MODULEENTRY32W); do { if (!wcscmp(module_entry_.szModule, wideModule.c_str())) { CloseHandle(handle_module); return { (DWORD_PTR)module_entry_.modBaseAddr, module_entry_.dwSize }; } } while (Module32NextW(handle_module, &module_entry_)); CloseHandle(handle_module); return { 0, 0 }; } LPVOID pProcess::Allocate(size_t size_in_bytes) { return VirtualAllocEx(this->handle_, NULL, size_in_bytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); } uintptr_t pProcess::FindSignature(std::vector signature) { std::unique_ptr data; data = std::make_unique(this->base_client_.size); if (!ReadProcessMemory(this->handle_, (void*)(this->base_client_.base), data.get(), this->base_client_.size, NULL)) { return 0x0; } for (uintptr_t i = 0; i < this->base_client_.size; i++) { for (uintptr_t j = 0; j < signature.size(); j++) { if (signature.at(j) == 0x00) continue; if (*reinterpret_cast(reinterpret_cast(&data[i + j])) == signature.at(j)) { if (j == signature.size() - 1) return this->base_client_.base + i; continue; } break; } } return 0x0; } uintptr_t pProcess::FindSignature(ProcessModule target_module, std::vector signature) { std::unique_ptr data; data = std::make_unique(0xFFFFFFF); if (!ReadProcessMemory(this->handle_, (void*)(target_module.base), data.get(), 0xFFFFFFF, NULL)) { return NULL; } for (uintptr_t i = 0; i < 0xFFFFFFF; i++) { for (uintptr_t j = 0; j < signature.size(); j++) { if (signature.at(j) == 0x00) continue; if (*reinterpret_cast(reinterpret_cast(&data[i + j])) == signature.at(j)) { if (j == signature.size() - 1) return this->base_client_.base + i; continue; } break; } } return 0x0; } uintptr_t pProcess::FindCodeCave(uint32_t length_in_bytes) { std::vector cave_pattern = {}; for (uint32_t i = 0; i < length_in_bytes; i++) { cave_pattern.push_back(0x00); } return FindSignature(cave_pattern); } void pProcess::Close() { CloseHandle(handle_); }