269 lines
6.9 KiB
C++
269 lines
6.9 KiB
C++
#include "memory.hpp"
|
|
#include <tlhelp32.h>
|
|
#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<uint8_t> signature)
|
|
{
|
|
std::unique_ptr<uint8_t[]> data;
|
|
data = std::make_unique<uint8_t[]>(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<uint8_t*>(reinterpret_cast<uintptr_t>(&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<uint8_t> signature)
|
|
{
|
|
std::unique_ptr<uint8_t[]> data;
|
|
data = std::make_unique<uint8_t[]>(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<uint8_t*>(reinterpret_cast<uintptr_t>(&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<uint8_t> 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_);
|
|
} |