WriteProcessMemory

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


#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

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


#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程序,点击窗口上的任意一个按钮,应该弹出如下的对话框:

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

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


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值