C++ 如何使用来自 CE 的包含浮点数的给定地址来执行 read/writeprocess?

C++ How can i do read/writeprocess with a given address from CE that contains a float?

我目前正在为游戏训练师开发传送功能。我找到了包含浮点数的正确静态地址:

picture of addresses with offsets

这个地址指向我的 X 坐标。现在我正在尝试使用 read/write processmemory 更改我的 X 坐标(浮点数)。但是无论我做什么都行不通(我对更改普通整数没有任何问题)。我想用我之前选择的浮点数替换该值。

有人可以给我一个详细的例子吗?

提前致谢

1) 获取进程基址 - Getting base address of a process hprocess 是句柄,将 openprocess 返回值传递给那里 (https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320(v=vs.85).aspx)

2) 将'teleport'偏移量添加到基址

3) 将给定值写入进程内存

HANDLE hProcess = openProcess(processId); //you also need to pass desired mode, use read & write
DWORD dwBaseAddress = getBaseAddress(hProcess): 
DWORD dwPositionAddress = dwBaseAddress + POSITION_OFFSET; 
float newPosition = 123.5;
WriteProcessMemory(hProcess, dwPositionAddress, &newPosition, sizeof(float));

你需要检查错误,这只是伪代码,让你知道你需要做什么,还要确保你 运行 你的培训师是管理员并且可以访问游戏内存

您必须读取指针并添加指针的相对偏移量才能到达传送地址。

您可以使用 WriteProcessMemory() 直接写入进程内存,并使用 ReadProcessMemory() 从内存读取。

但是,如果您正在阅读 二三 级指针,这样做会变得很麻烦。

所以我建议使用 Game Trainer 或内存破解库 轻松地 read/write 指针。

你可以使用 GTLibc Game Trainer libray for C/C ++。 GTLibc Game trainer library

或者您可以使用 Memory.dll 用于 C# 的游戏黑客库。 Memory.dll

改为在内部进行

Readprocessmemory 和 writeprocessmemory 会相对简单,但更好的选择是将 DLL 注入目标进程以提高速度和简单性。您可以使用 * 手动遵从,或者执行首选方法并设置具有适当大小的 classes,这样您就不必以相同的方式处理偏移量。查看 Reclass.NET 以实现自动化。

class unk3{
public:
    char pad_001[0x10];
    float location;
}

class unk2{
public:
    unk3* m_unk3;
}

class unk1{
public:
    char pad_001[0x78];
    unk2* m_unk2;
}

然后在您的静态偏移量处声明一个实例,并且read/write像它是您自己的内存一样。

unk1* p_unk1 = (unk1*)(uintptr_t*)(OFFSET);
p_unk1->m_unk2->m_unk3->location = 300f;

使用 RPM

如果您想转到外部,您需要先打开进程的句柄。

void attach(LPCSTR WindowName) {
    HWND hWindow = FindWindowA(NULL, WindowName); 
    if (hWindow)
    {
        GetWindowThreadProcessId(hWindow, &Proc_ID); 
        hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION/*PROCESS_ALL_ACCESS*/, FALSE, Proc_ID); 
        HANDLE hModule = INVALID_HANDLE_VALUE; 
        MODULEENTRY32 ePoint; 
        hModule = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, Proc_ID); 
        ePoint.dwSize = sizeof(MODULEENTRY32); 
        Module32First(hModule, &ePoint);
        base = (DWORD*)ePoint.modBaseAddr; 
        CloseHandle(hModule);
    }
}

那么我建议设置模板来为您完成 reading/writing。

template <class T>
T read(DWORD_PTR Address){
    T buffer;
    ReadProcessMemory(this->hProcess, (LPCVOID)Address, &buffer, sizeof(buffer), NULL);
    return buffer;
}

那么写法就差不多了。那么执行将是:

DWORD_PTR p_unk1 = mem.read<DWORD_PTR>(OFFSET);
DWORD_PTR p_unk2 = mem.read<DWORD_PTR>(p_unk1 + 0x78);
DWORD_PTR p_unk3 = mem.read<DWORD_PTR>(p_unk2);
float location = mem.read<float>(p_unk3 + 0x10);

外在效率

与其只准备好 sizeof(DWORD_PTR) 并读取 class 中的每个元素,不如这样做更好:

class unk3{
public:
    char pad_001[0x10];
    float location;
}

class unk2{
public:
    DWORD_PTR m_unk3;
}

class unk1{
public:
    char pad_001[0x78];
    DWORD_PTR m_unk2;
}

将每个 class* 替换为 DWORD_PTR

然后用

执行
unk1 p_unk1 = mem.read<unk1>(OFFSET);
unk2 p_unk2 = mem.read<unk2>(p_unk1.m_unk2);
unk3 p_unk3 = mem.read<unk3>(p_unk2.m_unk3);
float location = p_unk3.Location;

对于那些想知道的人,这样写就完成了:

mem.write<float>(p_unk2 + offsetof(unk3, location), value);

总结

在内部执行此操作明显更好,麻烦更少。 注意你的问题,writeprocessmemory 只是推送字节,它不关心类型。当整数和浮点数使用小端字节序进行不同编码时,您可能将整数的地址作为要写入的缓冲区传递。确保将其声明为浮点数,或者更好的是,使用模板。或者更好的是,只写一个 dll :)