简体   繁体   English

ReadProcessMemory 读取进程中的所有 0 memory

[英]ReadProcessMemory reads all 0s in a process memory

I am trying to write a process memory scanner that scans for nonzero values in the 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;
}

I tried it on chrome.exe and the scanner found a ton of nonzero values.我在chrome.exe上尝试过,扫描仪发现了大量非零值。 But when I tried it on a game process that comes with an anticheat it fails to work, ReadProcessMemory returns ERROR_ACCESS_DENIED in each call of ReadProcessMemory .但是,当我在带有反作弊功能的游戏进程上尝试它时,它无法工作, ReadProcessMemory在每次调用ReadProcessMemory时都会返回ERROR_ACCESS_DENIED The handle hProc had no problem attaching to the game process and the correct PID was found.句柄hProc连接到游戏进程没有问题,并且找到了正确的 PID。 Why is that and how can we increase our privilege to bypass the anticheat?为什么会这样?我们如何才能增加绕过反作弊的特权?

According to this thread , you need to enumerate all modules for a process to get a valid handle to the module you are interested in. Then you can use ReadProcessMemory like this running as an Administrator to read the multilevel pointer:根据这个线程,您需要枚举进程的所有模块以获得您感兴趣的模块的有效句柄。然后您可以使用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;
}

For more details, you may research from the internet.更多详情,您可以从网上查询。

A trimmed down version of your code does approximately this:您的代码的精简版本大致执行以下操作:

dtype readVal;
if (readVal != 0) {
    printf("Found a good value!");
    system("pause");
}

There's a (probably) uninitialized value ( readVal ), some code with a code path that doesn't alter the value, followed by a read access.有一个(可能)未初始化的值( readVal ),一些代码的代码路径不会改变该值,然后是读取访问。 Doing so has no specified behavior.这样做没有指定的行为。 Its behavior is thus implied to be undefined.因此,它的行为被暗示为未定义的。

To fix your code you'll need to make two changes:要修复您的代码,您需要进行两项更改:

  • readVal needs to be initialized, and reset in the innermost loop. readVal需要初始化,并在最里面的循环中重置。 Though without knowing what data type readVal is, it's impossible to know whether it is or isn't initialized.尽管不知道readVal是什么数据类型,但不可能知道它是否已初始化。 That's left as an exercise.这留作练习。
  • ReadProcessMemory can fail. ReadProcessMemory可能会失败。 It reports failure by returning FALSE .它通过返回FALSE来报告失败。 You will need to check for failure, and optionally call GetLastError if you need extended error information.您将需要检查失败,如果需要扩展错误信息,还可以选择调用GetLastError

Why is that and how can we bypass the anticheat?为什么会这样,我们如何绕过反作弊?

We don't know, since you decided to keep vital information private (eg the specific name and version of the target).我们不知道,因为您决定对重要信息保密(例如目标的具体名称和版本)。 Bypassing software protection is designed to be difficult.绕过软件保护被设计为很困难。 Spend a decade in binary exploitation and you might be prepared to come up with a way.花十年的时间在二进制开发中,你可能已经准备好想出一个方法。 Not something Stack Overflow can help you with. Stack Overflow 无法为您提供帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM