[英]ReadProcessMemory reads all 0s in a process memory
我正在嘗試編寫一個進程 memory 掃描儀,用於掃描 memory 中的非零值:
MEMORY_BASIC_INFORMATION mbi;
char* addr = 0;
dtype readVal = 0;
while (VirtualQueryEx(hProc, addr, &mbi, sizeof(mbi))) { // HANDLE hProc is defined earlier
if (mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS) {
for (int i = 0; i < mbi.RegionSize; i += sizeof(readVal)) {
BOOL ret = ReadProcessMemory(hProc, (char*) mbi.BaseAddress + i, &readVal, sizeof(readVal), 0);
printf("ReadProcessMemory returns %d\n", ret); // returns 5 (ERROR_ACCESS_DENIED)
if (readVal != 0) {
printf("Found a good value!");
system("pause");
}
}
}
addr += mbi.RegionSize;
}
我在chrome.exe
上嘗試過,掃描儀發現了大量非零值。 但是,當我在帶有反作弊功能的游戲進程上嘗試它時,它無法工作, ReadProcessMemory
在每次調用ReadProcessMemory
時都會返回ERROR_ACCESS_DENIED
。 句柄hProc
連接到游戲進程沒有問題,並且找到了正確的 PID。 為什么會這樣?我們如何才能增加繞過反作弊的特權?
根據這個線程,您需要枚舉進程的所有模塊以獲得您感興趣的模塊的有效句柄。然后您可以使用ReadProcessMemory
像這樣以管理員身份運行來讀取多級指針:
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
#include <tchar.h>
using namespace std;
DWORD_PTR dwGetModuleBaseAddress(DWORD dwProcID, TCHAR *szModuleName);
int main()
{
HWND hwnd = FindWindowA(NULL, "Game");
if (hwnd == NULL)
{
cout << "Cannot find window." << endl;
Sleep(3000);
exit(-1);
}
else
{
DWORD procID;
GetWindowThreadProcessId(hwnd, &procID);
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID);
DWORD_PTR ModuleBaseAddress = 0;
ModuleBaseAddress = dwGetModuleBaseAddress(procID, _T("Game.exe"));
if (procID == NULL)
{
cout << "Cannot find process.";
Sleep(3000);
exit(-1);
}
else {
while (true)
{
DWORD temp;
ReadProcessMemory(handle, (LPCVOID)(ModuleBaseAddress + 0x43021C), &temp, sizeof(temp), NULL);
ReadProcessMemory(handle, (LPCVOID)(temp + 0xAC), &temp, sizeof(temp), NULL);
int curhp;
ReadProcessMemory(handle, (LPCVOID)(temp + 0x4C), &curhp, sizeof(curhp), NULL);
cout << "Current HP: " << curhp << endl;
Sleep(100);
system("CLS");
}
}
}
system("PAUSE");
}
DWORD_PTR dwGetModuleBaseAddress(DWORD dwProcID, TCHAR *szModuleName)
{
DWORD_PTR dwModuleBaseAddress = 0;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, dwProcID);
if (hSnapshot != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 ModuleEntry32;
ModuleEntry32.dwSize = sizeof(MODULEENTRY32);
if (Module32First(hSnapshot, &ModuleEntry32))
{
do
{
if (_tcsicmp(ModuleEntry32.szModule, szModuleName) == 0)
{
dwModuleBaseAddress = (DWORD_PTR)ModuleEntry32.modBaseAddr;
break;
}
} while (Module32Next(hSnapshot, &ModuleEntry32));
}
CloseHandle(hSnapshot);
}
return dwModuleBaseAddress;
}
更多詳情,您可以從網上查詢。
您的代碼的精簡版本大致執行以下操作:
dtype readVal;
if (readVal != 0) {
printf("Found a good value!");
system("pause");
}
有一個(可能)未初始化的值( readVal
),一些代碼的代碼路徑不會改變該值,然后是讀取訪問。 這樣做沒有指定的行為。 因此,它的行為被暗示為未定義的。
要修復您的代碼,您需要進行兩項更改:
readVal
需要初始化,並在最里面的循環中重置。 盡管不知道readVal
是什么數據類型,但不可能知道它是否已初始化。 這留作練習。FALSE
來報告失敗。 您將需要檢查失敗,如果需要擴展錯誤信息,還可以選擇調用GetLastError 。為什么會這樣,我們如何繞過反作弊?
我們不知道,因為您決定對重要信息保密(例如目標的具體名稱和版本)。 繞過軟件保護被設計為很困難。 花十年的時間在二進制開發中,你可能已經准備好想出一個方法。 Stack Overflow 無法為您提供幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.