函数功能描述:该函数用来读取指定进程的空间的数据,此空间必须是可以访问的,否则读取操作会失败!函数原型
BOOL ReadProcessMemory(
HANDLE hProcess, // 目标进程句柄
LPCVOID lpBaseAddress, // 读取数据的起始地址
LPVOID lpBuffer, // 存放数据的缓存区地址
DWORD nSize, // 要读取的字节数
LPDWORD lpNumberOfBytesRead // 实际读取数存放地址
);
参数
hProcess
目标进程的句柄,该句柄必须对目标进程具有PROCESS_VM_READ 的访问权限。
lpBaseAddress
从目标进程中读取数据的起始地址。在读取数据前,系统将先检验该地址的数据是否可读,如果不可读,函数将调用失败。
lpBuffer
用来接收数据的缓存区地址。
nSize
从目标进程读取数据的字节数。
lpNumberOfBytesRead
实际被读取数据大小的存放地址。如果被指定为NULL,那么将忽略此参数。
返回值
如果函数执行成功,返回值非零。
如果函数执行失败,返回值为零。调用 GetLastError 函数可以获取该函数执行错误的信息。
如果要读取一个进程中不可访问空间的数据,该函数就会失败。
备注
ReadProcessMemory 函数从目标进程复制指定大小的数据到自己进程的缓存区,任何拥有PROCESS_VM_READ 权限句柄的进程都可以调用该函数,目标进程的地址空间很显然要是可读的,但也并不是必须的,如果目标进程处于被调试状态的话。
使用环境[包括适合WINDOWS的版本、所需头文件、所需链接库]
读取内存流程
1.获得程序的句柄---->findwindow
2.获得进程ID---->GetWindowThreadProcessId
3.获得进程句柄---->OpenProcess
4.内存操作(读取写放)---->ReadProcessMemory
修改一个程序的过程如下:1、获得进程的句柄 2、以一定的权限打开进程 3、调用ReadProcessMemory读取内存,WriteProcessMemory修改内存,这也是内存补丁的实现过程。下面贴出的是调用ReadProcessMemory的例程
#include <windows.h>
#include <tlhelp32.h>
BOOL CALLBACK EnumChildWindowProc(HWND hWnd,LPARAM lParam);//枚举记事本中的子窗口
char mess[999999];
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
HWND nphWnd=::FindWindow("notepad",NULL);
if(nphWnd)
{
char temp[1024];
PROCESSENTRY32 pe32;
pe32.dwSize=sizeof(pe32);
HANDLE hProcessSnap=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//获得进程列表的快照,第一个参数可以有其他选项,详细请参考MSDN
if(hProcessSnap==INVALID_HANDLE_VALUE)
{
::MessageBox(NULL,"CreateToolhelp32Snapshot error","error",MB_OK);
return 0;
}
HANDLE hProcess;
BOOL bMore=::Process32First(hProcessSnap,&pe32);//获得第一个进程的信息
while(bMore)
{
::wsprintf(temp,"%s",pe32.szExeFile);
if(!::strcmp(temp,"Maxthon.exe"))
{
hProcess=::OpenProcess(PROCESS_ALL_ACCESS,false,(DWORD)pe32.th32ProcessID);
if(hProcess==NULL)
{
::wsprintf(temp,"%s","打开进程失败!");
::strcat(mess,temp);
}
else
{
::wsprintf(temp,"%s","打开进程成功!");
::strcat(mess,temp);
//读取内存中内容
int tmp;
DWORD dwNumberOfBytesRead;
if(!::ReadProcessMemory(hProcess,(LPCVOID)0x00400000,&tmp,4,&dwNumberOfBytesRead))
{
::wsprintf(temp,"%s","读取失败");
::strcat(mess,temp);
}
else
{
::wsprintf(temp,"%x",tmp);
::strcat(mess,temp);
}
}
break;
}
bMore=::Process32Next(hProcessSnap,&pe32);//获得其他进程信息
}
::EnumChildWindows(nphWnd,EnumChildWindowProc,0);//获得记事本的edit窗口,打印进程信息
return 0;
}
else
{
::MessageBox(NULL,"please open notepad","error",MB_OK);
return 0;
}
}
BOOL CALLBACK EnumChildWindowProc(HWND hWnd,LPARAM lParam)
{
char temp1[256];
if(hWnd)
{
::GetClassName(hWnd,temp1,255);
if(!::strcmp(temp1,"Edit"))//得到edit子窗口句柄
{
::SendMessage(hWnd,WM_SETTEXT,0,(LPARAM)mess);
return 0;
}
}
return true;
}
程序读取400000地址4个字节的数据,对于exe文件,也就是PE文件,读出来的内容永远都是905a4d,翻译成ASCII字符也就是“MZ”,下面要进行的就是调用WriteProcessMemory修改内存的内容了,具体程序放在下篇文章中