C ++仅在过程范围内读取内存地址 [英] C++ read memory addresses within process range only

查看:65
本文介绍了C ++仅在过程范围内读取内存地址的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我一直试图用C ++进行内存读取,我认为一个很酷的项目将是读取进程正在使用的所有地址(类似于Cheat Engine的工作方式).

So I have been trying to get into memory reading in C++ and I thought a cool project would be to read all addresses a process is using (similar to how Cheat Engine works).

我从阅读开始

链接1 :读取进程C ++的内存

链接2 :读取64位进程地址的内存

链接3:: http://www.cplusplus.com/forum/general/42132/

我还观看了youtube上的教程,其中他解释了流程(游戏)如何处理地址.链接到youtube视频: https://www.youtube.com/观看?v = wiX5LmdD5yk

And I also watched a tutorial on youtube where he explained how a process (game) worked with addresses. Link to youtube video: https://www.youtube.com/watch?v=wiX5LmdD5yk

这导致我采用了三种不同的方法:

This resulted in me making three different methods:

DWORD GetProcId(const wchar_t* procName) {
    DWORD pid = 0;
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if(hSnap != INVALID_HANDLE_VALUE) {
        PROCESSENTRY32 procEntry;
        procEntry.dwSize = sizeof(procEntry);
        if(Process32First(hSnap, &procEntry)) {
            do {
                if(!_wcsicmp(procEntry.szExeFile, procName)) {
                    pid = procEntry.th32ProcessID;
                    break;
                }
            } while (Process32Next(hSnap, &procEntry));
        }
    }
    CloseHandle(hSnap);
    return pid;
}

此方法是要获取process-id,我也可以通过在任务管理器中找到相同的PID来手动键入该ID(稍后为我提供相同的基址).

This method is to get the process-id which I could also just type manually by finding the same PID in task-manager (which gave me the same baseaddress later on).

uintptr_t GetModuleBaseAddress(DWORD procId, const wchar_t* modName) {
    uintptr_t modBaseAddr = 0;
//I use 0x10 instead of TH32CS_SNAPMODULE32 since it didnt work and according to documentation 
// this is the value it should have.
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | 0x10, procId); 
    if(hSnap != INVALID_HANDLE_VALUE) {
        MODULEENTRY32 modEntry;
        modEntry.dwSize = sizeof(modEntry);
        if(Module32First(hSnap, &modEntry)) {
            do {
                if(!_wcsicmp(modEntry.szModule, modName)) {
                    modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
                    break;
                }
            } while(Module32Next(hSnap, &modEntry));
        }
    }
    CloseHandle(hSnap);
    return modBaseAddr;
}

此方法(我假设)将返回进程的基地址.例如,在我的代码中,我试图找到discord.exe进程的基地址.当discord.exe没有运行时,我得到了0,而当它运行时,我得到了一个地址(我相信这是正确的基地址,如果我输入错了,请更正我).

This method (I assume) will return the base address of the process. Which for example in my code I tried to find the base address of the discord.exe process. When discord.exe wasn't running I got 0 and when it was running I got an address (which I believe is the correct base address, correct me if I am wrong).

还有我的 main 方法:

int main() {
    DWORD procId = GetProcId(L"Discord.exe");
    uintptr_t moduleBase = GetModuleBaseAddress(procId, L"Discord.exe");

    HANDLE hProcess = 0;
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, NULL, procId);

    uintptr_t dynamicPtrBaseAddr = moduleBase;

    std::cout << "Dynamic: " << dynamicPtrBaseAddr << std::endl;

    int value = 0;
    int arr [10000] = {};
    for (int i = 0; i < 100000; i++) {
        ReadProcessMemory(hProcess, (BYTE*)dynamicPtrBaseAddr, &value, sizeof(value),0);
        dynamicPtrBaseAddr += 1;
        arr[i] = value;
    }
}

我尝试将所有100000个地址的所有值放在一个数组中.

Where I try to put all the values of all 100000 addresses in an array.

所以我的问题是:

  • 我是否正确检索了进程的基地址?
  • 要读取其他地址,我仅将dynamicPtrBaseAddr加1,是否有更好的方法来实现偏移量?还是这是正确的方法?
  • 现在我将基址增加100000.我能找到进程的最后一个地址吗?

我使用 g ++ main.cpp -o test -lpsapi -DUNICODE (MinGW)进行编译.

I compile with g++ main.cpp -o test -lpsapi -DUNICODE (MinGW).

推荐答案

您必须以管理员身份运行,并且必须以与目标进程相同的位数进行编译.

You must run as administrator and you must compile for the same bitness as the target process.

您不应该一次读取1个字节,尤其是在外部黑客中.

You should not be reading 1 byte at a time, especially in an external hack.

您应该使用VirtualQueryEx()仅在适当的内存区域中正确循环:

You should be using VirtualQueryEx() to properly loop through only proper memory regions:

    DWORD procid = GetProcId("ac_client.exe");

    unsigned char* addr = 0;

    HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procid);

    MEMORY_BASIC_INFORMATION mbi;

    while (VirtualQueryEx(hProc, addr, &mbi, sizeof(mbi)))
    {
        if (mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS && mbi.Protect != PAGE_GUARD)
        {
            std::cout << "base : 0x" << std::hex << mbi.BaseAddress << " end : 0x" << std::hex << (uintptr_t)mbi.BaseAddress + mbi.RegionSize << "\n";
        }
        addr += mbi.RegionSize;
    }

这可确保您仅读取正确的内存.接下来,您将一次访问每个区域的本地缓冲区,这将极大地提高速度,因为您无需为每个字节调用API.

This ensures you're only reading proper memory. Next you would reach each region into a local buffer in one go, this will increase speed dramatically as you won't have the overhead of calling the API for each byte.

您要尝试执行的操作是模式扫描.您可以在找到原始教程的同一位置找到我们的模式扫描教程.

What you're looks like you're trying to do is pattern scanning. You can find our pattern scanning tutorials in the same place you found the original tutorial you were following.

这篇关于C ++仅在过程范围内读取内存地址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆