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