问题描述
我正在尝试为游戏创建游戏训练师。我找到了所需的内存地址,现在我想将我的值写入该地址。
例如:弹药地址为: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,NULL);
然后函数的第二个参数是 LPVOID
类型,我读到 LPVOID
是指向任何东西的指针。
那么,为什么我不能为第二个参数传递指向 int
(地址变量)的指针?
我为什么要使用 (void*)
?
解决方法
-
为什么要使用 (void*)
因为这是手册告诉您函数所期望的内容。具体:
lpBaseAddress
指向指定进程中写入数据的基地址的指针。在数据传输之前,系统会验证指定大小的基地址和内存中的所有数据是否都可以进行写访问,如果不可访问,则函数失败。
-
出于同样的原因,您不能依次传递包含地址的局部变量的地址,因为这不是函数所期望的。
-
LPVOID
只是void*
的 Windows 乱码,它们是相同的类型。 -
为了将整数地址转换为指针类型,您需要进行强制转换,因为 C 和 C++ 就是这样设计的。您不能将整数分配给指针,请参阅 "Pointer from integer/integer from pointer without a cast" issues。
-
值得注意的是
0x0E9AFD07
是一个未对齐的地址,因此向该地址写入一个 4 字节整数是可疑的。
请注意,您的两个代码片段不是等效的;相反,他们要求 WriteProcessMemory
函数将数据写入不同位置。
在第二个代码段中,您传递 0x0E9AFD07
(作为 void*
),它告诉函数从给定地址(传递的十六进制值)开始将数据写入内存。
然而,在第一个片段中,您传递的是 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;
}