好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

修改内存数据程序(MFC)

修改内存数据程序(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  ;
} 

 运行过程图:

 

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

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于修改内存数据程序(MFC)的详细内容...

  阅读:46次