修改内存数据程序(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/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did46559