ReadProcessMemory 与 WriteProcessMemory

修改一个程序的过程如下:1、获得进程的句柄 2、以一定的权限打开进程 3、调用ReadProcessMemory读取内存,WriteProcessMemory修改内存,这也是内存补丁的实现过程。下面贴出的是调用ReadProcessMemory的例程


01#include <windows.h>
02#include <tlhelp32.h>
03BOOL CALLBACK EnumChildWindowProc(HWND hWnd,LPARAM lParam);//枚举记事本中的子窗口
04char mess[999999];
05int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
06{
07    HWND nphWnd=::FindWindow("notepad",NULL);
08    if(nphWnd)
09    {
10        char temp[1024];
11        PROCESSENTRY32 pe32;
12        pe32.dwSize=sizeof(pe32);
13        HANDLE hProcessSnap=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//获得进程列表的快照,第一个参数可以有其他选项,详细请参考MSDN
14        if(hProcessSnap==INVALID_HANDLE_VALUE)
15        {
16            ::MessageBox(NULL,"CreateToolhelp32Snapshot error","error",MB_OK);
17            return 0;
18        }
19        HANDLE hProcess;
20        BOOL bMore=::Process32First(hProcessSnap,&pe32);//获得第一个进程的信息
21        while(bMore)
22        {
23            ::wsprintf(temp,"%s",pe32.szExeFile);
24            if(!::strcmp(temp,"Maxthon.exe"))
25            {
26                hProcess=::OpenProcess(PROCESS_ALL_ACCESS,false,(DWORD)pe32.th32ProcessID);
27                if(hProcess==NULL)
28                {
29                    ::wsprintf(temp,"%s","打开进程失败!");
30                    ::strcat(mess,temp);
31                }
32                else
33                {
34                    ::wsprintf(temp,"%s","打开进程成功!");
35                    ::strcat(mess,temp);
36                    //读取内存中内容
37                    int tmp;
38                    DWORD dwNumberOfBytesRead;
39                    if(!::ReadProcessMemory(hProcess,(LPCVOID)0x00400000,&tmp,4,&dwNumberOfBytesRead))
40                    {
41                        ::wsprintf(temp,"%s","读取失败");
42                        ::strcat(mess,temp);
43                    }
44                    else
45                    {
46                        ::wsprintf(temp,"%x",tmp);
47                        ::strcat(mess,temp);
48                    }
49                }
50                break;
51            }
52            bMore=::Process32Next(hProcessSnap,&pe32);//获得其他进程信息
53        }
54        ::EnumChildWindows(nphWnd,EnumChildWindowProc,0);//获得记事本的edit窗口,打印进程信息
55        return 0;
56    }
57    else
58    {
59        ::MessageBox(NULL,"please open notepad","error",MB_OK);
60        return 0;
61    }
62}
63BOOL CALLBACK EnumChildWindowProc(HWND hWnd,LPARAM lParam)
64{
65    char temp1[256];
66    if(hWnd)
67    {
68        ::GetClassName(hWnd,temp1,255);
69        if(!::strcmp(temp1,"Edit"))//得到edit子窗口句柄
70        {
71            ::SendMessage(hWnd,WM_SETTEXT,0,(LPARAM)mess);
72            return 0;
73        }
74    }
75    return true;
76}

以PROCESS_ALL_ACCESS权限打开进程以后既可以使用ReadProcessMemory读取程序内存,也可以使用WriteProcessMemory改写程序的内存,这也是一些内存补丁使用的招数,以下是程序的实现代码


01#include <windows.h>
02#include <tlhelp32.h>
03BOOL CALLBACK EnumChildWindowProc(HWND hWnd,LPARAM lParam);//枚举记事本中的子窗口
04char mess[999999];
05int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
06{
07    HWND nphWnd=::FindWindow("notepad",NULL);
08    if(nphWnd)
09    {
10        char temp[1024];
11        PROCESSENTRY32 pe32;
12        pe32.dwSize=sizeof(pe32);
13        HANDLE hProcessSnap=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//获得进程列表的快照,第一个参数可以有其他选项,详细请参考MSDN
14        if(hProcessSnap==INVALID_HANDLE_VALUE)
15        {
16            ::MessageBox(NULL,"CreateToolhelp32Snapshot error","error",MB_OK);
17            return 0;
18        }
19        HANDLE hProcess;
20        BOOL bMore=::Process32First(hProcessSnap,&pe32);//获得第一个进程的信息
21        while(bMore)
22        {
23            ::wsprintf(temp,"%s",pe32.szExeFile);
24            if(!::strcmp(temp,"button.exe"))
25            {
26                hProcess=::OpenProcess(PROCESS_ALL_ACCESS,false,(DWORD)pe32.th32ProcessID);
27                if(hProcess==NULL)
28                {
29                    ::wsprintf(temp,"%s","打开进程失败!");
30                    ::strcat(mess,temp);
31                }
32                else
33                {
34                    ::wsprintf(temp,"%s","打开进程成功!");
35                    ::strcat(mess,temp);
36                    //改写内存中内容
37                    int tmp=97;//ascii:a
38                    DWORD dwNumberOfBytesRead;
39                    if(!::WriteProcessMemory(hProcess,(LPVOID)0x0040505d,&tmp,1,&dwNumberOfBytesRead))
40                    {
41                        ::wsprintf(temp,"%s","写入失败");
42                        ::strcat(mess,temp);
43                    }
44                    else
45                    {
46                        ::wsprintf(temp,"%s","写入成功");
47                        ::strcat(mess,temp);
48                    }
49                }
50                break;
51            }
52            bMore=::Process32Next(hProcessSnap,&pe32);//获得其他进程信息
53        }
54        ::EnumChildWindows(nphWnd,EnumChildWindowProc,0);//获得记事本的edit窗口,打印进程信息
55        return 0;
56    }
57    else
58    {
59        ::MessageBox(NULL,"please open notepad","error",MB_OK);
60        return 0;
61    }
62}
63BOOL CALLBACK EnumChildWindowProc(HWND hWnd,LPARAM lParam)
64{
65    char temp1[256];
66    if(hWnd)
67    {
68        ::GetClassName(hWnd,temp1,255);
69        if(!::strcmp(temp1,"Edit"))//得到edit子窗口句柄
70        {
71            ::SendMessage(hWnd,WM_SETTEXT,0,(LPARAM)mess);
72            return 0;
73        }
74    }
75    return true;
76}

程序的功能是改写名为button.exe程序中内存地址为0x0040505d的值为97,即ASCII值的a,此处内存的原内容为ASCII值的m

被修改的程序实现代码如下:


01#include <windows.h>
02#include <stdio.h>
03LRESULT CALLBACK _procWinMain(HWND,UINT,WPARAM,LPARAM);
04int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
05{
06    HWND hWinMain,hButton1,hButton2;
07    MSG stMsg;
08    WNDCLASSEX stWndClass;
09    RtlZeroMemory(&stWndClass,sizeof(stWndClass));//WNDCLASSEX结构置零
10    //注册窗口类
11    stWndClass.hCursor=::LoadCursor(0,IDC_ARROW);
12    stWndClass.hInstance=hInstance;
13    stWndClass.cbSize=sizeof(WNDCLASSEX);
14    stWndClass.style=CS_HREDRAW||CS_VREDRAW;
15    stWndClass.lpfnWndProc=_procWinMain;
16    stWndClass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
17    stWndClass.lpszClassName="myclass";
18    ::RegisterClassEx(&stWndClass);
19    //建立并显示窗口
20    hWinMain=::CreateWindowEx(WS_EX_CLIENTEDGE,"myclass","firstwindow",WS_OVERLAPPEDWINDOW,100,100,600,400,NULL,NULL,hInstance,NULL);
21    //建立按钮
22    hButton1=::CreateWindowEx(NULL,"BUTTON","button1",WS_VISIBLE|WS_CHILD,300,200,60,20,hWinMain,(HMENU)1,hInstance,NULL);
23    hButton2=::CreateWindowEx(NULL,"BUTTON","button2",WS_VISIBLE|WS_CHILD,100,200,60,20,hWinMain,(HMENU)2,hInstance,NULL);
24     
25    ::ShowWindow(hWinMain,SW_SHOWNORMAL);
26    ::UpdateWindow(hWinMain);
27    while(1)
28    {
29        if(::GetMessage(&stMsg,NULL,0,0)==0)//消息为WM_QUIT
30            break;
31        else
32        {
33            ::TranslateMessage(&stMsg);
34            ::DispatchMessage(&stMsg);
35        }
36    }
37    return 0;
38}
39LRESULT CALLBACK _procWinMain(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
40{
41    if(uMsg==WM_CLOSE)
42    {
43        ::DestroyWindow(hWnd);
44    }
45    else if(uMsg==WM_DESTROY)
46    {
47        ::PostQuitMessage(NULL);
48    }
49    else if(uMsg==WM_COMMAND)
50    {
51        char temp1[256],temp2[256];
52        ::itoa((int)wParam,temp1,10);
53        ::strcpy(temp2,"wParam: ");
54        ::strcat(temp2,temp1);
55        ::strcat(temp2," lParam: ");
56        ::itoa((int)lParam,temp1,10);
57        ::strcat(temp2,temp1);
58        ::strcat(temp2," mess");
59        ::MessageBox(NULL,temp2,"command",MB_OK);
60    }
61    else
62    {
63        return ::DefWindowProc(hWnd,uMsg,wParam,lParam);
64    }
65    return 0;
66}

这个程序的功能是在窗口上建立两个button,点击任何一个button都会弹出一个对话框,输出button回调函数的wParam、lParam参数的值,外加一段字符串“mess”,我们要修改的就是字符串“mess”的第一个字符“m”为“a”。




原文链接: ReadProcessMemory 与 WriteProcessMemory 版权所有,转载时请注明出处,违者必究。
注明出处格式:流沙团 ( http://www.gyarmy.com/?post=385 )

发表评论

0则评论给“ReadProcessMemory 与 WriteProcessMemory”