通过WriteProcessMemory改写进程的内存

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

ContractedBlock.gif ExpandedBlockStart.gif Code
#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,"button.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=97;//ascii:a
                    DWORD dwNumberOfBytesRead;
                    
if(!::WriteProcessMemory(hProcess,(LPVOID)0x0040505d,&tmp,1,&dwNumberOfBytesRead))
                    {
                        ::wsprintf(temp,
"%s","写入失败");
                        ::strcat(mess,temp);
                    }
                    
else
                    {
                        ::wsprintf(temp,
"%s","写入成功");
                        ::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;
}

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

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

ContractedBlock.gif ExpandedBlockStart.gif Code
#include <windows.h>
#include 
<stdio.h>
LRESULT CALLBACK _procWinMain(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
    HWND hWinMain,hButton1,hButton2;
    MSG stMsg;
    WNDCLASSEX stWndClass;
    RtlZeroMemory(
&stWndClass,sizeof(stWndClass));//WNDCLASSEX结构置零
    
//注册窗口类
    stWndClass.hCursor=::LoadCursor(0,IDC_ARROW);
    stWndClass.hInstance
=hInstance;
    stWndClass.cbSize
=sizeof(WNDCLASSEX);
    stWndClass.style
=CS_HREDRAW||CS_VREDRAW;
    stWndClass.lpfnWndProc
=_procWinMain;
    stWndClass.hbrBackground
=(HBRUSH)GetStockObject(BLACK_BRUSH);
    stWndClass.lpszClassName
="myclass";
    ::RegisterClassEx(
&stWndClass);
    
//建立并显示窗口
    hWinMain=::CreateWindowEx(WS_EX_CLIENTEDGE,"myclass","firstwindow",WS_OVERLAPPEDWINDOW,100,100,600,400,NULL,NULL,hInstance,NULL);
    
//建立按钮
    hButton1=::CreateWindowEx(NULL,"BUTTON","button1",WS_VISIBLE|WS_CHILD,300,200,60,20,hWinMain,(HMENU)1,hInstance,NULL);
    hButton2
=::CreateWindowEx(NULL,"BUTTON","button2",WS_VISIBLE|WS_CHILD,100,200,60,20,hWinMain,(HMENU)2,hInstance,NULL);
    
    ::ShowWindow(hWinMain,SW_SHOWNORMAL);
    ::UpdateWindow(hWinMain);
    
while(1)
    {
        
if(::GetMessage(&stMsg,NULL,0,0)==0)//消息为WM_QUIT
            break;
        
else
        {
            ::TranslateMessage(
&stMsg);
            ::DispatchMessage(
&stMsg);
        }
    }
    
return 0;
}
LRESULT CALLBACK _procWinMain(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
    
if(uMsg==WM_CLOSE)
    {
        ::DestroyWindow(hWnd);
    }
    
else if(uMsg==WM_DESTROY)
    {
        ::PostQuitMessage(NULL);
    }
    
else if(uMsg==WM_COMMAND)
    {
        
char temp1[256],temp2[256];
        ::itoa((
int)wParam,temp1,10);
        ::strcpy(temp2,
"wParam: ");
        ::strcat(temp2,temp1);
        ::strcat(temp2,
" lParam: ");
        ::itoa((
int)lParam,temp1,10);
        ::strcat(temp2,temp1);
        ::strcat(temp2,
" mess");
        ::MessageBox(NULL,temp2,
"command",MB_OK);
    }
    
else
    {
        
return ::DefWindowProc(hWnd,uMsg,wParam,lParam);
    }
    
return 0;
}

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

将两端代码编译以后先打开button程序,点击窗口上的任意一个按钮,应该弹出如下的对话框:通过WriteProcessMemory改写进程的内存_第1张图片

此时打开改写内存的程序,然后再点击button程序窗口上的按钮,弹出的窗口就变成了下图:

通过WriteProcessMemory改写进程的内存_第2张图片

字符串mess成功地修改为aess!

转载于:https://www.cnblogs.com/feiyucq/archive/2009/10/21/1587628.html

你可能感兴趣的:(通过WriteProcessMemory改写进程的内存)