0

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

带偏移地址的图片

这个地址指向我的 X 坐标。现在我正在尝试使用读/写 processmemory 更改我的 X 坐标(浮点数)。但无论我做什么它都不起作用(我在改变正常整数方面没有问题)。我想用我之前选择的浮点数替换该值。

有人可以给我一个详细的例子,我该怎么做?

先感谢您

4

3 回答 3

1

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

2) 将“传送”偏移量添加到基地址

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));

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

于 2018-02-28T12:50:21.303 回答
0

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

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

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

所以我建议使用Game Trainer 或内存黑客库来轻松读/写指针。

您可以将GTLibc Game Trainer libray用于C /C++。 GTLibc 游戏教练库

或者你可以使用 C# 的 Memory.dll 游戏黑客库。 内存.dll

于 2018-04-12T14:30:56.000 回答
0

而是在内部进行

Readprocessmemory 和 writeprocessmemory 会相对简单,但更好的选择是将 DLL 注入目标进程以提高速度和简单性。您可以使用 a 手动遵守,也可以使用*首选方法并设置具有适当大小的类,这样您就不必以相同的方式处理偏移量。查看 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;
}

然后在你的静态偏移处声明一个实例,并像你自己的内存一样读/写它。

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);
    }
}

然后,我建议您设置模板来为您进行阅读/写作。

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 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;
}

用 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 :)

于 2018-04-23T02:56:56.493 回答