【问题标题】:Why should I use (void*) in second parameter of WriteProcessMemory() func?为什么我应该在 WriteProcessMemory() 函数的第二个参数中使用 (void*)?
【发布时间】:2021-06-19 00:31:34
【问题描述】:

我正在尝试为游戏创建游戏教练。我找到了所需的内存地址,现在我想将我的值写入该地址。

例如:弹药地址为:0x0E9AFD07

Windows API 中的WriteProcessMemory() 函数可以做到这一点。

我的来源:

int main(){
    DWORD pid;
    int address = 0x0E9AFD07;
    const int data = 20;
    HWND hwnd = FindWindow(0 , "Max Payne v1.05");
    GetWindowThreadProcessId(hwnd , &pid);
    HANDLE hndl = OpenProcess(PROCESS_ALL_ACCESS , false ,pid);
    WriteProcessMemory(hndl , &address , &data , 4 , NULL); 

    return 0;
}

但是这段代码不起作用!

如果我应该使用WriteProcessMemory,如下所示:

WriteProcessMemory(hndl , (void*)0x0E9AFD07 , &data , 4 , NULL); 

那么函数的第二个参数是LPVOID 类型,我读到LPVOID 是指向任何东西的指针。

那么,为什么我不能为第二个参数传递指向int(地址变量)的指针?

我为什么要使用(void*)

【问题讨论】:

  • 哦,对不起。为什么我们在地址前使用 (void*) ?
  • 对多次编辑感到抱歉。但请澄清哪种语言(C 或 C++)。 false suggests C++ 的使用,但可以在 C 中定义(为 0)。OpenProcess 进程采用 BOOL 第二个参数。
  • 非常感谢 :))

标签: c++ c winapi memory cheat-engine


【解决方案1】:
  • 为什么要使用 (void*)

    因为这是手册告诉您该功能所期望的。具体来说:

    lpBaseAddress

    指向要写入数据的指定进程中的基地址的指针。在数据传输发生之前,系统会验证指定大小的基地址和内存中的所有数据都可以写访问,如果不可访问,则函数失败。

  • 出于同样的原因,您不能传递包含地址的局部变量的地址,因为这不是函数所期望的。

  • LPVOID 只是 void* 的 Windows 乱码,它们是相同的类型。

  • 为了将整数地址转换为指针类型,您需要进行强制转换,因为 C 和 C++ 就是这样设计的。您不能将整数分配给指针,请参阅"Pointer from integer/integer from pointer without a cast" issues

  • 值得注意的是,0x0E9AFD07 是一个未对齐的地址,因此向该地址写入一个 4 字节整数是有问题的。

【讨论】:

    【解决方案2】:

    请注意,您的两个代码 sn-ps 是等效的;相反,他们要求WriteProcessMemory 函数将数据写入不同的位置。

    在第二个 sn-p 中,您传递 0x0E9AFD07(作为 void*),它告诉函数从给定地址(传递的十六进制值)开始将数据写入内存。

    但是,在第一个 sn-p 中,您传递了 int 变量的地址(恰好包含值 0x0E9AFD07);这将指示函数将数据写入该变量的位置 - 因此,覆盖那里的 0x0E9AFD07 值(或尝试这样做失败)。

    如果要传递存储在局部变量中的地址,则需要将该变量的 转换为 void* 指针,如下所示:

    int main(){
        DWORD pid;
        int address = 0x0E9AFD07;
        const int data = 20;
        HWND hwnd = FindWindow(0 , "Max Payne v1.05");
        GetWindowThreadProcessId(hwnd , &pid);
        HANDLE hndl = OpenProcess(PROCESS_ALL_ACCESS , false ,pid);
        // The "int" variable's VALUE is the target address, so cast/pass that...
        WriteProcessMemory(hndl , (void*)address , &data , 4 , NULL); 
    
        return 0;
    }
    

    【讨论】:

    • 虽然是比较常见的C扩展,但int的扩展,无需强制转换即可转换为任意指针类型。即使使用提供此类扩展的 C 编译器,通常也取决于编译选项是否会执行此类转换。
    • "如果使用 C,编译器会将 int 隐式转换为 void*" 不,这是完全错误的。如果您使用的是符合标准的编译器,则会出现一条诊断消息,因为您编写了无效的 C。stackoverflow.com/questions/52186834/…
    猜你喜欢
    • 2013-04-03
    • 1970-01-01
    • 2018-10-23
    • 1970-01-01
    • 2019-09-18
    • 2016-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多