将单个 HANDLE 与两次 ReadProcessMemory 调用一起使用时无效的句柄
Invalid Handle when using a single HANDLE with two calls of ReadProcessMemory
我刚刚开始学习 Windows API,我想制作一个简单的程序来读取给定进程中的值。
这是我的代码
#include <stdio.h>
#include <Windows.h>
void printError();
int main()
{
int *buffer;
// process input
unsigned int pid = 0;
printf("process ID : ");
scanf("%d", &pid);
getchar();
HANDLE authorisation = OpenProcess(PROCESS_VM_READ, FALSE, pid);
if(authorisation == NULL)
{
printf("OpenProcess Failed. GetLastError = %d", GetLastError());
getchar();
return EXIT_FAILURE;
}
// adress memory input
int *memoryAddress = 0x0;
printf("memory address to read (in hexadecimal) : ");
scanf("%p", &memoryAddress);
getchar();
printf("Reading from address : %p", memoryAddress);
if(ReadProcessMemory(authorisation, (LPCVOID)memoryAddress, &buffer, 8,
NULL))
{
printf("\nptr2int = %p\n", buffer);
}
else
{
printError();
}
int varInt = 0;
// HERE IS THE PROBLEM
// GetLastError return 6 : Invalid Handle
if(ReadProcessMemory(authorisation, (LPCVOID)buffer, &varInt,
sizeof(int), NULL))
{
printf("varInt = %d\n", varInt);
}
else
{
printError();
}
printf("Press ENTER to quit");
getchar();
return 0;
}
void printError()
{
printf("ReadProcessMemory Failed. GetLastError = %d", GetLastError());
getchar();
return EXIT_FAILURE;
}
但是,如果我为第二次调用 RPM 创建一个新的句柄,它就可以正常工作。
我在 MSDN 上读到这个:
The handle returned by the OpenProcess function can be used in any
function that requires a handle to a process"
我做错了什么?
您的问题是:
int *buffer;
unsigned int pid = 0;
ReadProcessMemory(authorisation, (LPCVOID)memoryAddress, &buffer, 8, NULL);
比方说,buffer 的地址是0x0,pid 的地址是0x4,因为你正在编译一个32 位的应用程序,而指针是4 个字节。当您调用 RPM 时,您硬编码了 8 个字节的大小,这会覆盖 pid 使其无效。您基本上是自己缓冲区溢出了。
每当您使用 ReadProcessMemory() 时,您应该始终使用 sizeof(originalVariable) 作为字节数参数,这样您就不会遇到任何问题。
如果您打算经常访问其他进程的内存,您应该遵循以下做法:
使用uintptr_t存储地址,然后编译您的应用程序以匹配目标进程的体系结构。为 x64 编译时它将是 8 个字节,而在 x86 上它将是 4 个字节。如果你愿意,你也可以制作自己的 typedef。
为目标进程的相同体系结构编译在很多方面都有帮助,您会在您的旅程中发现,有几个 WINAPI 的东西更容易用这种方式工作。您不必这样做,但我强烈建议您这样做。
我刚刚开始学习 Windows API,我想制作一个简单的程序来读取给定进程中的值。
这是我的代码
#include <stdio.h>
#include <Windows.h>
void printError();
int main()
{
int *buffer;
// process input
unsigned int pid = 0;
printf("process ID : ");
scanf("%d", &pid);
getchar();
HANDLE authorisation = OpenProcess(PROCESS_VM_READ, FALSE, pid);
if(authorisation == NULL)
{
printf("OpenProcess Failed. GetLastError = %d", GetLastError());
getchar();
return EXIT_FAILURE;
}
// adress memory input
int *memoryAddress = 0x0;
printf("memory address to read (in hexadecimal) : ");
scanf("%p", &memoryAddress);
getchar();
printf("Reading from address : %p", memoryAddress);
if(ReadProcessMemory(authorisation, (LPCVOID)memoryAddress, &buffer, 8,
NULL))
{
printf("\nptr2int = %p\n", buffer);
}
else
{
printError();
}
int varInt = 0;
// HERE IS THE PROBLEM
// GetLastError return 6 : Invalid Handle
if(ReadProcessMemory(authorisation, (LPCVOID)buffer, &varInt,
sizeof(int), NULL))
{
printf("varInt = %d\n", varInt);
}
else
{
printError();
}
printf("Press ENTER to quit");
getchar();
return 0;
}
void printError()
{
printf("ReadProcessMemory Failed. GetLastError = %d", GetLastError());
getchar();
return EXIT_FAILURE;
}
但是,如果我为第二次调用 RPM 创建一个新的句柄,它就可以正常工作。
我在 MSDN 上读到这个:
The handle returned by the OpenProcess function can be used in any function that requires a handle to a process"
我做错了什么?
您的问题是:
int *buffer;
unsigned int pid = 0;
ReadProcessMemory(authorisation, (LPCVOID)memoryAddress, &buffer, 8, NULL);
比方说,buffer 的地址是0x0,pid 的地址是0x4,因为你正在编译一个32 位的应用程序,而指针是4 个字节。当您调用 RPM 时,您硬编码了 8 个字节的大小,这会覆盖 pid 使其无效。您基本上是自己缓冲区溢出了。
每当您使用 ReadProcessMemory() 时,您应该始终使用 sizeof(originalVariable) 作为字节数参数,这样您就不会遇到任何问题。
如果您打算经常访问其他进程的内存,您应该遵循以下做法:
使用uintptr_t存储地址,然后编译您的应用程序以匹配目标进程的体系结构。为 x64 编译时它将是 8 个字节,而在 x86 上它将是 4 个字节。如果你愿意,你也可以制作自己的 typedef。
为目标进程的相同体系结构编译在很多方面都有帮助,您会在您的旅程中发现,有几个 WINAPI 的东西更容易用这种方式工作。您不必这样做,但我强烈建议您这样做。