读取进程内存多级指针(DLL注入)

时间:2018-08-26 20:14:06

标签: c++ pointers dll-injection readprocessmemory cheat-engine

我已成功将.dll注入.exe,并且需要通过多级指针访问值。

这是一个能获得正确值的有效示例:

#include <Windows.h>
#include <iostream>
#include <vector>
#include <TlHelp32.h>
#include <tchar.h>
using namespace std;

DWORD dwGetModuleBaseAddress(TCHAR *lpszModuleName, DWORD pID)
{
    DWORD dwBaseAddress = 0;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pID);
    MODULEENTRY32 moduleEntry32 = { 0 };
    moduleEntry32.dwSize = sizeof(MODULEENTRY32);
    if (Module32First(hSnapshot, &moduleEntry32))
    {
        do {
            if (_tcscmp(moduleEntry32.szModule, lpszModuleName) == 0)
            {
                dwBaseAddress = (DWORD)moduleEntry32.modBaseAddr;
                break;
            }
        } while (Module32Next(hSnapshot, &moduleEntry32));
    }
    CloseHandle(hSnapshot);
    return dwBaseAddress;
}

int main()
{
    DWORD pID;
    DWORD off1, off2, off3, off4, off5;
    DWORD baseAddress;
    DWORD xAddress;
    int newX;
    int currentX;
    char moduleName[] = "TibiaInjected2.exe";
    HWND hGameWindow;
    HANDLE pHandle;

    // Getting handles
    hGameWindow = FindWindowA(NULL, "Tibia - 127.0.0.1:7171");
    GetWindowThreadProcessId(hGameWindow, &pID);
    pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);

    // Getting base address
    DWORD clientBase = dwGetModuleBaseAddress(_T(moduleName), pID);

    ReadProcessMemory(pHandle, (LPCVOID)(clientBase + 0x0031D0CC), &baseAddress, sizeof(baseAddress), NULL);
    cout << "Base address: " << hex << baseAddress << endl;

    ReadProcessMemory(pHandle, (LPCVOID)(baseAddress + 0x4), &off1, sizeof(off1), NULL);
    cout << "Offset 1: " << hex << off1 << endl;

    ReadProcessMemory(pHandle, (LPCVOID)(off1 + 0x4), &off2, sizeof(off2), NULL);
    cout << "Offset 2: " << hex << off2 << endl;

    ReadProcessMemory(pHandle, (LPCVOID)(off2 + 0xA0), &off3, sizeof(off3), NULL);
    cout << "Offset 3: " << hex << off3 << endl;

    ReadProcessMemory(pHandle, (LPCVOID)(off3 + 0x100), &off4, sizeof(off4), NULL);
    cout << "Offset 4: " << hex << off4 << endl;

    ReadProcessMemory(pHandle, (LPCVOID)(off4 + 0x14), &off5, sizeof(off5), NULL);
    cout << "Offset 5: " << hex << off5 << endl;

    cin.get();
}

我宁愿使用我的静态注入的DLL,而且据我所知,我可以将整个dwGetModuleBaseAddress替换为GetModuleHandle(NULL),因为它来自注入的DLL中。我也不需要打开任何进程。但是,如果我不做所有这些事情,该如何替换ReadProcessMemory?

ReadProcessMemory(pHandle, (LPCVOID)(clientBase + 0x0031D0CC), &baseAddress, sizeof(baseAddress), NULL);
ReadProcessMemory(pHandle, (LPCVOID)(baseAddress + 0x4), &off1, sizeof(off1), NULL);
ReadProcessMemory(pHandle, (LPCVOID)(off1 + 0x4), &off2, sizeof(off2), NULL);
ReadProcessMemory(pHandle, (LPCVOID)(off2 + 0xA0), &off3, sizeof(off3), NULL);
ReadProcessMemory(pHandle, (LPCVOID)(off3 + 0x100), &off4, sizeof(off4), NULL);
ReadProcessMemory(pHandle, (LPCVOID)(off4 + 0x14), &off5, sizeof(off5), NULL);

我已经设法通过以下方式直接从静态地址访问值:

int* exampleValue = *(int*)0x12345678;

但是无法弄清楚如何使用指针和偏移量。

2 个答案:

答案 0 :(得分:1)

是的,您可以使用GetModuleHandle(NULL);获取主.exe模块的句柄或将NULL替换为与DLL名称匹配的字符串。

您可以使用此功能循环偏移,在每个级别取消引用并添加偏移:

uintptr_t FindDMAAddy(uintptr_t ptr, std::vector<unsigned int> offsets)
{
    uintptr_t addr = ptr;
    for (unsigned int i = 0; i < offsets.size() ; ++i)
    {
        addr = *(uintptr_t*)addr;
        addr += offsets[i];
    }
    return addr;
}

uintptr_t ammoAddr = FindDMAAddy(dynamicPtrBaseAddr, { 0x374, 0x14, 0x0 });

//or

int * ammoAddr = (int*)FindDMAAddy(dynamicPtrBaseAddr, { 0x374, 0x14, 0x0 });

您还可以做一些疯狂的事情,例如:

 
int * ammo = (int*)((*(uintptr_t*)((*(uintptr_t*)(dynamicPtrBaseAddr)) +0x374)) + 0x14);

但这比它的价值更令人困惑和烦人。

答案 1 :(得分:0)

这对我有用(可以像其他答案一样放在一个循环中):

DWORD base = *(DWORD*)(clientBase + 0x0031D0CC);
DWORD offsets[] = { 0x4, 0x4, 0xA0, 0x100, 0x14 };

DWORD off1 = *(DWORD*)(base + offsets[0]);
DWORD off2 = *(DWORD*)(off1 + offsets[1]);
DWORD off3 = *(DWORD*)(off2 + offsets[2]);
DWORD off4 = *(DWORD*)(off3 + offsets[3]);
DWORD off5 = *(DWORD*)(off4 + offsets[4]);
cout << "Value: " << off5 << endl;