zoukankan      html  css  js  c++  java
  • 修改内存数据程序(MFC)

    在看Windows程序设计时,对第二章的修改内存数据程序很感兴趣,故把它改成了MFC程序以更好的操作。第一次在博客园发表博客,本人也是一个初学者,故有许多不懂,还恳请各位指教。

    这是我的界面图:

    程序代码:

    MemoRepairDlg.h:

    复制代码
    // MemoRepairDlg.h : 头文件
    //
    
    #pragma once
    #include "afxwin.h"
    
    
    // CMemoRepairDlg 对话框
    class CMemoRepairDlg : public CDialogEx
    {
    // 构造
    public:
        CMemoRepairDlg(CWnd* pParent = NULL);    // 标准构造函数
        ~CMemoRepairDlg();            //析构函数,释放进程句柄
    
    // 对话框数据
        enum { IDD = IDD_MEMOREPAIR_DIALOG };
    
        protected:
        virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
    
    
    // 实现
    protected:
        HICON m_hIcon;
    
        // 生成的消息映射函数
        virtual BOOL OnInitDialog();
        afx_msg void OnPaint();
        afx_msg HCURSOR OnQueryDragIcon();
        DECLARE_MESSAGE_MAP()
    public:
        afx_msg void OnBnClickedButton1();
        afx_msg void OnBnClickedButton2();
    
    
    public:
        DWORD addrList[1024];    //地址列表
        int addrCount;            //有效地址个数
        HANDLE hProcess;        //目标进程句柄
        BOOL conFirst;            //第一次查找
    public:
        BOOL FirstFind(DWORD valueChange);
        BOOL NextFind(DWORD valueChange);
        BOOL WriteMemory(DWORD valueAddr, DWORD valueChange);
        BOOL ComparePage(DWORD baseAddr, DWORD valueChange);
        void ShowList();
        afx_msg void OnBnClickedStartprocess();
        CEdit editBox1;
        CEdit editBox2;
        CEdit editBox3;
        int editValue;
        int editValue3;
        CString editStr;
    };
    复制代码

    MemoRepairDlg.cpp:

    复制代码
    // MemoRepairDlg.cpp : 实现文件
    //
    
    #include "stdafx.h"
    #include "MemoRepair.h"
    #include "MemoRepairDlg.h"
    #include "afxdialogex.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif
    
    
    // CMemoRepairDlg 对话框
    
    
    
    CMemoRepairDlg::CMemoRepairDlg(CWnd* pParent /*=NULL*/)
        : CDialogEx(CMemoRepairDlg::IDD, pParent)
        , editValue(0)
        , editValue3(0)
        , editStr(_T(""))
    {
        m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
        addrCount = 0;
        conFirst = TRUE;
    }
    
    void CMemoRepairDlg::DoDataExchange(CDataExchange* pDX)
    {
        CDialogEx::DoDataExchange(pDX);
        DDX_Control(pDX, IDC_EDIT1, editBox1);
        DDX_Control(pDX, IDC_EDIT2, editBox2);
        DDX_Control(pDX, IDC_EDIT3, editBox3);
        DDX_Text(pDX, IDC_EDIT2, editValue);
        DDX_Text(pDX, IDC_EDIT3, editValue3);
        DDX_Text(pDX, IDC_EDIT1, editStr);
    }
    
    BEGIN_MESSAGE_MAP(CMemoRepairDlg, CDialogEx)
        ON_WM_PAINT()
        ON_WM_QUERYDRAGICON()
        ON_BN_CLICKED(IDC_BUTTON1, &CMemoRepairDlg::OnBnClickedButton1)
        ON_BN_CLICKED(IDC_BUTTON2, &CMemoRepairDlg::OnBnClickedButton2)
        ON_BN_CLICKED(IDC_StartProcess, &CMemoRepairDlg::OnBnClickedStartprocess)
    END_MESSAGE_MAP()
    
    
    // CMemoRepairDlg 消息处理程序
    
    BOOL CMemoRepairDlg::OnInitDialog()
    {
        CDialogEx::OnInitDialog();
    
        // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
        //  执行此操作
        SetIcon(m_hIcon, TRUE);            // 设置大图标
        SetIcon(m_hIcon, FALSE);        // 设置小图标
    
        // TODO: 在此添加额外的初始化代码
    
        return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
    }
    
    // 如果向对话框添加最小化按钮,则需要下面的代码
    //  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
    //  这将由框架自动完成。
    
    void CMemoRepairDlg::OnPaint()
    {
        if (IsIconic())
        {
            CPaintDC dc(this); // 用于绘制的设备上下文
    
            SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
    
            // 使图标在工作区矩形中居中
            int cxIcon = GetSystemMetrics(SM_CXICON);
            int cyIcon = GetSystemMetrics(SM_CYICON);
            CRect rect;
            GetClientRect(&rect);
            int x = (rect.Width() - cxIcon + 1) / 2;
            int y = (rect.Height() - cyIcon + 1) / 2;
    
            // 绘制图标
            dc.DrawIcon(x, y, m_hIcon);
        }
        else
        {
            CDialogEx::OnPaint();
        }
    }
    
    //当用户拖动最小化窗口时系统调用此函数取得光标
    //显示。
    HCURSOR CMemoRepairDlg::OnQueryDragIcon()
    {
        return static_cast<HCURSOR>(m_hIcon);
    }
    
    
    
    void CMemoRepairDlg::OnBnClickedButton1()
    {
        // TODO: 在此添加控件通知处理程序代码
        int value;        //查找的值
        UpdateData(TRUE);
        value = editValue;
        if (conFirst == TRUE)
        {
            FirstFind(value);        //进行第一次查找
            ShowList();                    //打印出结果
            conFirst = FALSE;
        }
        else
        {
            NextFind(value);        //进行下一次查找
            ShowList();                //打印出结果
        }
        if (addrCount == 1)
        {
            MessageBox("OK, You Can Change Now!");
        }
        else
            MessageBox("NO, You Can't Change!");
    }
    
    void CMemoRepairDlg::OnBnClickedButton2()
    {
        // TODO: 在此添加控件通知处理程序代码
        if (addrCount > 1 || addrCount == 0)
        {
            MessageBox("Please Search Again!");
        }
        else
        {
            int valueWillChange;   //要修改的值
            UpdateData(TRUE);
            valueWillChange = editValue3;
            WriteMemory(addrList[0], valueWillChange);
        }
    }
    
    
    void CMemoRepairDlg::OnBnClickedStartprocess()
    {
        // TODO: 在此添加控件通知处理程序代码
    
        char szFileName[] = "Testor.exe";
        STARTUPINFO starUpInfo = {sizeof(starUpInfo)};
        PROCESS_INFORMATION process_information;
        //启动测试程序进程
        ::CreateProcess(NULL, szFileName, NULL, NULL, FALSE,CREATE_NEW_CONSOLE,
            NULL, NULL, &starUpInfo, &process_information);
        //关闭线程句柄
        ::CloseHandle(process_information.hThread);
        hProcess = process_information.hProcess;
    
    }
    CMemoRepairDlg::~CMemoRepairDlg()
    {
        ::CloseHandle(hProcess);
    }
    
    BOOL CMemoRepairDlg::ComparePage(DWORD baseAddr, DWORD valueChange)
    {
        BYTE pageByte[4096];
        if (!::ReadProcessMemory(hProcess,(LPVOID)baseAddr, pageByte,4096,NULL))
        {
            return FALSE;        //此页不可读
        }
        //在这页中查找
        DWORD* pageDword;
        for(int i=0; i<(int)4*1024; i++)
        {
            pageDword = (DWORD*)&pageByte[i];
            if (pageDword[0] == valueChange)
            {
                if (addrCount >= 1024)
                {
                    return FALSE;
                }
                    //添加到全局变量中
                addrList[addrCount] = baseAddr + i;
                addrCount++;
            }
        }
    }
    BOOL CMemoRepairDlg::FirstFind(DWORD valueChange)
    {
        const DWORD dwOneGB = 1024*1024*1024;
        const DWORD dwOnePage = 4096;
        if (hProcess == NULL)
        {
            return FALSE;
        }
        //操作系统类型
        DWORD systemBase;
        OSVERSIONINFO vinfo ={sizeof(vinfo)};
        ::GetVersionEx(&vinfo);
        if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
        {
            systemBase = 4*1024*1024;
        }
        else
        {
            systemBase = 640*1024;
        }
        //在开始地址到2GB的地址空间查找
        for (; systemBase < 2*dwOneGB; systemBase += dwOnePage)
        {
            ComparePage(systemBase, valueChange);
        }
        return TRUE;
    }
    
    BOOL CMemoRepairDlg::NextFind(DWORD valueChange)
    {
        //保存地址个数,初始化addrCount的值
        int mOrgCnt = addrCount;
        addrCount = 0;
        BOOL bRet = FALSE;
        DWORD dwReadValue;
        for (int i=0; i<mOrgCnt; i++)
        {
            if (::ReadProcessMemory(hProcess,(LPVOID)addrList[i],&dwReadValue,sizeof(DWORD),NULL))
            {
                if (dwReadValue == valueChange)
                {
                    addrList[addrCount] = addrList[i];
                    addrCount++;
                    bRet = TRUE;
                }
            }
        }
        return bRet;
    }
    
    void CMemoRepairDlg::ShowList()
    {
        editStr ="";
        CString str="";
        UpdateData(FALSE);
        editStr.Format("%d个相同的地址.",addrCount);
        for(int i=0; i<addrCount; i++)
        {
            str.Format("%s %d '\n';",editStr, addrList[i]);
            editStr = str;
        }
        UpdateData(FALSE);
    
    }
    
    BOOL CMemoRepairDlg::WriteMemory(DWORD valueAddr, DWORD valueChange)
    {
        return ::WriteProcessMemory(hProcess, (LPVOID)valueAddr, &valueChange, sizeof(DWORD), NULL);
    }
    复制代码

    再就是新建一个程序,作为启动的进程程序:Testor

    这个程序的Testor.exe文件将影响到上面启动进程的路径。 Testor.cpp:

    复制代码
    #include <iostream>
    
    using namespace std;
    
    int ChangeNum = 0;        //全局变量
    
    int main()
    {
        int insideNum = 200;        //局部变量
        ChangeNum = 1600;
    
        while (true)
        {
            printf(" insideNum = %d, addr = %X; ChangeNum = %d, addr = %X \n",
                ++insideNum, &insideNum, ++ChangeNum, &ChangeNum);
            getchar();
        }
        return 0;
    }
    复制代码

     运行过程图:

     

    至于实现原理:我感觉最奇妙的是那两次搜索。两次搜索就像坐标一样,能找到具体的地址。

  • 相关阅读:
    MYSQL 之 JDBC(十三):处理事务
    MYSQL 之 JDBC(十四):批量处理JDBC语句提高处理效率
    MYSQL 之 JDBC(十五):数据库连接池
    MYSQL 之 JDBC(十六): DBUtils
    MYSQL 之 JDBC(十七): 调用函数&存储过程
    Android初级教程理论知识(第八章网络编程二)
    android6.0SDK 删除HttpClient的相关类的解决方法
    iOS下WebRTC音视频通话(三)-音视频通话
    love~LBJ,奥布莱恩神杯3
    Android简易实战教程--第二话《两种进度条》
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2974433.html
Copyright © 2011-2022 走看看