游戏内存修改器

来源:互联网 发布:php时间戳转换月 编辑:程序博客网 时间:2024/04/30 03:04

CMemScanner.h(内存扫描器类):

#ifndef CMEMSCANNER_H
#define CMEMSCANNER_H

#include 
<stdio.h>
#include 
"AddrList.h"
#include 
"PageList.h"

class CMemScanner  //内存扫描器类
{
private:
    HANDLE m_hProcess;  
//待扫描进程句柄
public:
    CAddrList 
* m_lpAddrList;  //地址列表对象指针
private:
    BOOL EnableDebugPrivilege();  
//提升应用程序权限,使能调试特权函数
    BOOL GetScanRegion(CPageList * lpPageList);  //获取扫描范围
public:
    CMemScanner();  
//类构造函数
    ~CMemScanner();  //类析构函数
    BOOL SetProcessForScanner(DWORD dwProcessId);  //设置欲扫描的进程
    BOOL ScanFirst(DWORD dwValue);  //第一次扫描函数
    BOOL ScanNext(DWORD dwValue);  //下一次扫描函数
    BOOL WriteMemory(DWORD dwAddr, DWORD dwValue);  //修改内存函数
    BOOL ReadMemory(DWORD dwAddr,DWORD * lpValue);  //读取内存函数
};

#endif

 CMemScanner.cpp:

#include "stdafx.h"
#include 
"MemScanner.h"

//类构造函数
CMemScanner::CMemScanner()
{
    m_hProcess 
= NULL;  //初始化类成员变量
    m_lpAddrList = NULL;
    EnableDebugPrivilege();  
//提升应用程序权限,使拥有调试特权
}

//类析构函数
CMemScanner::~CMemScanner()
{
    
if(m_hProcess)
        ::CloseHandle(m_hProcess);
    
if(m_lpAddrList)
        delete m_lpAddrList;
}

//设置欲扫描的进程
BOOL CMemScanner::SetProcessForScanner(DWORD dwProcessId)
{
    
if(m_hProcess)
        ::CloseHandle(m_hProcess);
    
    m_hProcess 
= ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, dwProcessId);  //打开欲扫描进程句柄
    
//m_hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);  //打开欲扫描进程句柄
    if(m_hProcess)  //OpenProcess函数调用失败返回值为零
        return TRUE;
    
else  
        
return FALSE;
}
    
//第一次扫描函数
BOOL CMemScanner::ScanFirst(DWORD dwValue)
{
    CPageList 
* lpPageList = NULL;
    CAddrList 
* lpAddrList = NULL;
    
int i,j;
    
char * lpBuf = NULL;
    MEMORY_BASIC_INFORMATION stMemInfo  
= {0};

    
if(!m_hProcess)
        
return FALSE;

    lpPageList 
= new CPageList(100);  //构造一个页面列表对象,初始大小或步进值为100个DWORD
    if(!GetScanRegion(lpPageList))  //获取扫描范围
        return FALSE;
    
    lpAddrList 
= new CAddrList(100);  //构造一个地址列表对象,初始大小或步进值为100个DWORD
    
    
for(i = 0; i < lpPageList ->m_nPageListCnt; i++)  //循环扫描已提交页面
    {
        lpBuf 
= new char[lpPageList ->m_lpPageSizeList[i]];
        
if(!::ReadProcessMemory(m_hProcess,(LPCVOID)(lpPageList ->m_lpPageBaseAddrList[i]),lpBuf,lpPageList ->m_lpPageSizeList[i],NULL))  //读取已提交的一块内存,失败返回零
        {
            
if(lpPageList)
                delete lpPageList;
            
return FALSE;
        }
        
        
for(j = 0; j < lpPageList ->m_lpPageSizeList[i] - 3; j++)  //逐个比较这一块已提交的内存
        {
            
if(dwValue == *(DWORD *)(lpBuf + j))  //等于要扫描的值
                lpAddrList ->AddToAddrList((DWORD)(lpPageList ->m_lpPageBaseAddrList[i] + j));  //添加数据到地址列表
        }
        
        
if(lpBuf)
            delete lpBuf;
    }
    
if(m_lpAddrList)  //删除原地址列表
        delete m_lpAddrList;
    m_lpAddrList 
= lpAddrList;  //保存新地址列表
    if(lpPageList)  //删除页面列表
        delete lpPageList;
    
return TRUE;
}

//下一次扫描函数
BOOL CMemScanner::ScanNext(DWORD dwValue)
{
    CAddrList 
* lpAddrList = NULL;
    DWORD dwBuf 
= 0;
    
int i;

    
if(!m_hProcess)
        
return FALSE;

    lpAddrList 
= new CAddrList(100);  //构造一个地址列表对象,初始大小或步进值为100个DWORD

    
for(i = 0; i < m_lpAddrList ->m_nAddrListCnt; i++)
    {
        
if(!::ReadProcessMemory(m_hProcess,(LPCVOID)(m_lpAddrList ->m_lpAddrList[i]),&dwBuf,sizeof dwBuf,NULL))
        {
            
if(lpAddrList)
                delete lpAddrList;
            
return FALSE;
        }

        
if(dwValue == dwBuf)  //等于要扫描的值
            lpAddrList ->AddToAddrList(m_lpAddrList ->m_lpAddrList[i]);  //添加数据到地址列表
    }
    
    
if(m_lpAddrList)  //删除原地址列表
        delete m_lpAddrList;
    m_lpAddrList 
= lpAddrList;  //保存新地址列表
    return TRUE;
}

//修改内存函数
BOOL CMemScanner::WriteMemory(DWORD dwAddr, DWORD dwValue)
{
    DWORD dwOldProtect;
    MEMORY_BASIC_INFORMATION stMemInfo  
= {0};

    
if(!m_hProcess)
        
return FALSE;

    
if(!::VirtualQueryEx(m_hProcess,(LPCVOID)dwAddr,&stMemInfo,sizeof(stMemInfo)))
        
return FALSE;
    
if(!::VirtualProtectEx(m_hProcess,(LPVOID)dwAddr,sizeof(DWORD),PAGE_READWRITE,&dwOldProtect))
        
return FALSE;
    
    
if(::WriteProcessMemory(m_hProcess,(LPVOID)dwAddr,&dwValue,sizeof(DWORD), NULL))
    {
        ::VirtualProtectEx(m_hProcess,(LPVOID)dwAddr,
sizeof(DWORD),dwOldProtect,0);
        
return TRUE;
    }
    
else
    {
        ::VirtualProtectEx(m_hProcess,(LPVOID)dwAddr,
sizeof(DWORD),dwOldProtect,0);
        
return FALSE;
    }
}

//读取内存函数
BOOL CMemScanner::ReadMemory(DWORD dwAddr,DWORD * lpValue)
{
    
if(!m_hProcess)
        
return FALSE;

    
return ::ReadProcessMemory(m_hProcess,(LPVOID)dwAddr,lpValue,sizeof(DWORD),0);
}

//提升应用程序权限,使能调试特权函数
BOOL CMemScanner::EnableDebugPrivilege()
{
    HANDLE hProcess 
= NULL;
    HANDLE hToken 
= NULL;
    LUID uID 
= {0};
    TOKEN_PRIVILEGES stToken_Privileges 
= {0};

    hProcess 
= ::GetCurrentProcess();  //获取当前应用程序进程句柄
    
    
if(!::OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES,&hToken))  //打开当前进程的访问令牌句柄(OpenProcessToken函数调用失败返回值为零)
        return FALSE;

    
if(!::LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&uID))  //获取权限名称为"SetDebugPrivilege"的LUID(LookupPrivilegeValue函数调用失败返回值为零)
        return FALSE;

    stToken_Privileges.PrivilegeCount 
= 1;  //欲调整的权限个数
    stToken_Privileges.Privileges[0].Luid = uID;  //权限的LUID
    stToken_Privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;  //权限的属性,SE_PRIVILEGE_ENABLED为使能该权限
    
    
if(!::AdjustTokenPrivileges(hToken,FALSE,&stToken_Privileges,sizeof stToken_Privileges,NULL,NULL))  //调整访问令牌里的指定权限(AdjustTokenPrivileges函数调用失败返回值为零)
        return FALSE;

    
if(::GetLastError() != ERROR_SUCCESS)  //查看权限是否调整成功
        return FALSE;

    ::CloseHandle(hToken);
    
return TRUE;
}

//获取扫描范围
BOOL CMemScanner::GetScanRegion(CPageList * lpPageList)
{
    SYSTEM_INFO stSysInfo 
= {0};
    
int nAppStartAddr = 0,nAppEndAddr = 0;
    MEMORY_BASIC_INFORMATION stMemInfo  
= {0};
    
int i;

    ::GetSystemInfo(
&stSysInfo);
    nAppStartAddr 
= (int)stSysInfo.lpMinimumApplicationAddress;  //应用程序私有地址空间的起始地址
    nAppEndAddr = (int)stSysInfo.lpMaximumApplicationAddress;  //应用程序私有地址空间的终止地址
    
    
for(i = nAppStartAddr; i < nAppEndAddr;)
    {
        
if(!::VirtualQueryEx(m_hProcess,(LPCVOID)i,&stMemInfo,sizeof(stMemInfo)))  //查询基地址从i开始的页面的属性
            return FALSE;

        
if(stMemInfo.State == MEM_COMMIT)  //该页面是已提交的并且属性是可读写和可执行的
            if(stMemInfo.Protect == PAGE_READWRITE || stMemInfo.Protect == PAGE_EXECUTE_READWRITE)
                lpPageList 
->AddToPageList((DWORD)stMemInfo.BaseAddress,(DWORD)stMemInfo.RegionSize);  //添加数据到页面列表
        
        i 
= i + stMemInfo.RegionSize;  //跳到下一个页面基址
    }
    
return TRUE;
}

AddrList.h(地址列表类):

#ifndef CADDRLIST_H
#define CADDRLIST_H

#include 
<windows.h>

class CAddrList
{
private:
    
int m_nAddrListMaxCnt;  //地址列表最大计数
    int m_nStep;  //调用realloc时相对原列表空间大小的步进值
public:
    DWORD 
* m_lpAddrList;  //地址列表指针
    int m_nAddrListCnt;  //地址列表计数
public:
    CAddrList(
int nStep);  //类构造函数
    ~CAddrList();  //类析构函数
    void AddToAddrList(DWORD dwAddr);  //添加数据到地址列表
};

#endif

AddrList.cpp

#include "stdafx.h"
#include 
"AddrList.h"

//类构造函数
CAddrList::CAddrList(int nStep)
{
    m_nAddrListCnt 
= 0;
    m_nStep 
= nStep;
    m_nAddrListMaxCnt 
= nStep;
    m_lpAddrList 
= (DWORD *)malloc(m_nAddrListMaxCnt * sizeof(DWORD));
}

//类析构函数
CAddrList::~CAddrList()
{
    
if(m_lpAddrList)
        free(m_lpAddrList);
}

//添加数据到地址列表
void CAddrList::AddToAddrList(DWORD dwAddr)
{
    
if(m_nAddrListMaxCnt <= m_nAddrListCnt)
    {
        m_nAddrListMaxCnt 
= m_nAddrListMaxCnt + m_nStep;
        m_lpAddrList 
= (DWORD *)realloc(m_lpAddrList,m_nAddrListMaxCnt  * sizeof(DWORD));
    }
    m_lpAddrList[m_nAddrListCnt] 
= dwAddr;
    m_nAddrListCnt
++;
}

PageList.h(页面列表类):

#ifndef CPAGELIST_H
#define CPAGELIST_H

#include 
<windows.h>

class CPageList  //页面列表类
{
private:
    
int m_nPageListMaxCnt;  //页面列表最大计数(以上两个列表的计数,相同)
    int m_nStep;  //每次realloc时相对原来空间大小的步进值
public:
    DWORD 
* m_lpPageBaseAddrList;  //页面基址列表指针
    DWORD * m_lpPageSizeList;  //页面大小列表指针
    int m_nPageListCnt;  //页面列表计数(以上两个列表的计数,相同)
public:
    CPageList(
int nStep);  //类构造函数
    ~CPageList();  //类析构函数
    void AddToPageList(DWORD dwPageBaseAddr,DWORD dwPageSize);  //添加数据到页面列表
};

#endif

PageList..cpp

#include "stdafx.h"
#include 
"PageList.h"

//类构造函数
CPageList::CPageList(int nStep)
{
    m_nPageListCnt 
= 0;
    m_nStep 
= nStep;
    m_nPageListMaxCnt 
= nStep;
    m_lpPageBaseAddrList 
= (DWORD *)malloc(m_nPageListMaxCnt * sizeof(DWORD));
    m_lpPageSizeList 
= (DWORD *)malloc(m_nPageListMaxCnt * sizeof(DWORD));
}

//类析构函数
CPageList::~CPageList()
{
    
if(m_lpPageBaseAddrList)
        free(m_lpPageBaseAddrList);
    
if(m_lpPageSizeList)
        free(m_lpPageSizeList);
}

//添加数据到页面列表
void CPageList::AddToPageList(DWORD dwPageBaseAddr,DWORD dwPageSize)
{
    
if(m_nPageListMaxCnt <= m_nPageListCnt)
    {
        m_nPageListMaxCnt 
= m_nPageListMaxCnt + m_nStep;
        m_lpPageBaseAddrList 
= (DWORD *)realloc(m_lpPageBaseAddrList,m_nPageListMaxCnt * sizeof(DWORD));
        m_lpPageSizeList 
= (DWORD *)realloc(m_lpPageSizeList,m_nPageListMaxCnt * sizeof(DWORD));
    }
    
//char Buf[128] = {0};
    
//sprintf(Buf,"总%d,当%d",m_nPageListMaxCnt,m_nPageListCnt);
    
//MessageBox(NULL,Buf,"222",0);
    m_lpPageBaseAddrList[m_nPageListCnt] = dwPageBaseAddr;  //该页面的基址
    m_lpPageSizeList[m_nPageListCnt] = dwPageSize;  //该页的大小
    m_nPageListCnt++;
}

GameEditor.h(应用程序类)

// GameEditor.h : main header file for the GAMEEDITOR application
//

#if !defined(AFX_GAMEEDITOR_H__AC0A553E_7E31_49B9_BA63_FF72A2CE15F8__INCLUDED_)
#define AFX_GAMEEDITOR_H__AC0A553E_7E31_49B9_BA63_FF72A2CE15F8__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#ifndef __AFXWIN_H__
    
#error include 'stdafx.h' before including this file for PCH
#endif

#include 
"resource.h"        // main symbols

/////////////////////////////////////////////////////////////////////////////
// CGameEditorApp:
// See GameEditor.cpp for the implementation of this class
//

class CGameEditorApp : public CWinApp
{
public:
    CGameEditorApp();

// Overrides
    
// ClassWizard generated virtual function overrides
    
//{{AFX_VIRTUAL(CGameEditorApp)
    public:
    
virtual BOOL InitInstance();
    
//}}AFX_VIRTUAL

// Implementation

    
//{{AFX_MSG(CGameEditorApp)
        
// NOTE - the ClassWizard will add and remove member functions here.
        
//    DO NOT EDIT what you see in these blocks of generated code !
    
//}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};


/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_GAMEEDITOR_H__AC0A553E_7E31_49B9_BA63_FF72A2CE15F8__INCLUDED_)

GameEditor.cpp

// GameEditor.cpp : Defines the class behaviors for the application.
//

#include 
"stdafx.h"
#include 
"GameEditor.h"
#include 
"GameEditorDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CGameEditorApp

BEGIN_MESSAGE_MAP(CGameEditorApp, CWinApp)
    
//{{AFX_MSG_MAP(CGameEditorApp)
        
// NOTE - the ClassWizard will add and remove mapping macros here.
        
//    DO NOT EDIT what you see in these blocks of generated code!
    
//}}AFX_MSG
    ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGameEditorApp construction

CGameEditorApp::CGameEditorApp()
{
    
// TODO: add construction code here,
    
// Place all significant initialization in InitInstance
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CGameEditorApp object

CGameEditorApp theApp;

/////////////////////////////////////////////////////////////////////////////
// CGameEditorApp initialization

BOOL CGameEditorApp::InitInstance()
{
    AfxEnableControlContainer();

    
// Standard initialization
    
// If you are not using these features and wish to reduce the size
    
//  of your final executable, you should remove from the following
    
//  the specific initialization routines you do not need.

#ifdef _AFXDLL
    Enable3dControls();            
// Call this when using MFC in a shared DLL
#else
    Enable3dControlsStatic();    
// Call this when linking to MFC statically
#endif

    CGameEditorDlg dlg;
    m_pMainWnd 
= &dlg;
    
int nResponse = dlg.DoModal();
    
if (nResponse == IDOK)
    {
        
// TODO: Place code here to handle when the dialog is
        
//  dismissed with OK
    }
    
else if (nResponse == IDCANCEL)
    {
        
// TODO: Place code here to handle when the dialog is
        
//  dismissed with Cancel
    }

    
// Since the dialog has been closed, return FALSE so that we exit the
    
//  application, rather than start the application's message pump.
    return FALSE;
}

GameEditorDlg.h(主对话框类)

// GameEditorDlg.h : header file
//

#if !defined(AFX_GAMEEDITORDLG_H__457F57F1_F4EA_4B2B_BA4C_3220F297B11F__INCLUDED_)
#define AFX_GAMEEDITORDLG_H__457F57F1_F4EA_4B2B_BA4C_3220F297B11F__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

/////////////////////////////////////////////////////////////////////////////
// CGameEditorDlg dialog
#include "MemScanner.h"  //包含内存扫描器类头文件

class CGameEditorDlg : public CDialog
{
// Construction
public:
    CGameEditorDlg(CWnd
* pParent = NULL);    // standard constructor

public:
    
void UpdataProcessList();  //更新进程列表函数
    void UpdataAddrList();  //更新地址列表函数

// Dialog Data
    
//{{AFX_DATA(CGameEditorDlg)
    enum { IDD = IDD_GAMEEDITOR_DIALOG };
    CListCtrl    m_clsAddrList;
    CListCtrl    m_clsProcessList;
    
//}}AFX_DATA

    
// ClassWizard generated virtual function overrides
    
//{{AFX_VIRTUAL(CGameEditorDlg)
    public:
    
virtual BOOL PreTranslateMessage(MSG* pMsg);
    
protected:
    
virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    
//}}AFX_VIRTUAL

// Implementation
protected:
    HICON m_hIcon;
    BOOL m_bFirst;  
//是否是第一次搜索标志
public:
    CMemScanner m_clsMemScanner;  
//内存扫描器对象

    
// Generated message map functions
    
//{{AFX_MSG(CGameEditorDlg)
    virtual BOOL OnInitDialog();
    afx_msg 
void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    afx_msg 
void OnSearch();
    afx_msg 
void OnDblclkProcesslist(NMHDR* pNMHDR, LRESULT* pResult);
    afx_msg 
void OnReset();
    afx_msg 
void OnDblclkAddrlist(NMHDR* pNMHDR, LRESULT* pResult);
    
//}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_GAMEEDITORDLG_H__457F57F1_F4EA_4B2B_BA4C_3220F297B11F__INCLUDED_)

GameEditorDlg.cpp

// GameEditorDlg.cpp : implementation file
//

#include 
"stdafx.h"
#include 
"GameEditor.h"
#include 
"GameEditorDlg.h"
#include 
<tlhelp32.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CGameEditorDlg dialog
#include "ModifyDlg.h"  //

CGameEditorDlg::CGameEditorDlg(CWnd
* pParent /*=NULL*/)
    : CDialog(CGameEditorDlg::IDD, pParent)
{
    
//{{AFX_DATA_INIT(CGameEditorDlg)
        
// NOTE: the ClassWizard will add member initialization here
    
//}}AFX_DATA_INIT
    
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CGameEditorDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    
//{{AFX_DATA_MAP(CGameEditorDlg)
    DDX_Control(pDX, IDL_ADDRLIST, m_clsAddrList);
    DDX_Control(pDX, IDL_PROCESSLIST, m_clsProcessList);
    
//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CGameEditorDlg, CDialog)
    
//{{AFX_MSG_MAP(CGameEditorDlg)
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDB_SEARCH, OnSearch)
    ON_NOTIFY(NM_DBLCLK, IDL_PROCESSLIST, OnDblclkProcesslist)
    ON_BN_CLICKED(IDB_RESET, OnReset)
    ON_NOTIFY(NM_DBLCLK, IDL_ADDRLIST, OnDblclkAddrlist)
    
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGameEditorDlg message handlers

BOOL CGameEditorDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    
// Set the icon for this dialog.  The framework does this automatically
    
//  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);            // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon
    
    
// TODO: Add extra initialization here
    DWORD dwStyle;

    m_clsProcessList.InsertColumn(
0,"Name",LVCFMT_IMAGE | LVCFMT_LEFT,120);  //初始化进程列表框控件
    m_clsProcessList.InsertColumn(1,"PID",LVCFMT_CENTER,50);

    dwStyle 
= m_clsProcessList.GetExtendedStyle();
    dwStyle 
= dwStyle | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES;  //设置选择一整行和高亮显示选择行的扩展风格
    m_clsProcessList.SetExtendedStyle(dwStyle);

    m_clsAddrList.InsertColumn(
0,"序号",LVCFMT_CENTER,80);  //初始化地址列表框控件
    m_clsAddrList.InsertColumn(1,"地址",LVCFMT_CENTER,120);
    m_clsAddrList.InsertColumn(
2,"当前值",LVCFMT_CENTER,130);

    dwStyle 
= m_clsAddrList.GetExtendedStyle();
    dwStyle 
= dwStyle | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES;  //设置选择一整行和高亮显示选择行的扩展风格
    m_clsAddrList.SetExtendedStyle(dwStyle);

    m_bFirst 
= TRUE;
    UpdataProcessList();  
//更新进程列表
    return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CGameEditorDlg::OnPaint() 
{
    
if (IsIconic())
    {
        CPaintDC dc(
this); // device context for painting

        SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 
0);

        
// Center icon in client rectangle
        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;

        
// Draw the icon
        dc.DrawIcon(x, y, m_hIcon);
    }
    
else
    {
        CDialog::OnPaint();
    }
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CGameEditorDlg::OnQueryDragIcon()
{
    
return (HCURSOR) m_hIcon;
}

void CGameEditorDlg::OnSearch()  //搜索按钮单击事件处理过程
{
    
// TODO: Add your control notification handler code here
    DWORD dwProcessId,dwValue;
    CString strTip;

    
if(GetDlgItem(IDE_PID) ->GetWindowTextLength() <= 0)
    {
        MessageBox(
"请双击进程列表框选择一个目标进程!");
        
return;
    }

    
if(GetDlgItem(IDE_SEARCH) ->GetWindowTextLength() <= 0)
    {
        MessageBox(
"请输入一个搜索值!");
        GetDlgItem(IDE_SEARCH) 
->SetFocus();
        
return;
    }

    dwProcessId 
= GetDlgItemInt(IDE_PID);  //获取进程ID文本框的值
    dwValue = GetDlgItemInt(IDE_SEARCH);  //获取用户输入搜索文本框的值

    
if(m_bFirst)  //第一次搜索
    {
        
if(!m_clsMemScanner.SetProcessForScanner(dwProcessId))
        {
            MessageBox(
"打开目标进程时失败!");
            
return;
        }
        m_clsMemScanner.ScanFirst(dwValue);
        
if(m_clsMemScanner.m_lpAddrList ->m_nAddrListCnt)
            m_bFirst 
= FALSE;
    }
    
else
    {
        m_clsMemScanner.ScanNext(dwValue);
    }
    UpdataAddrList();  
//更新地址列表
    
    strTip.Format(
"总共搜索到%d个结果!",(m_clsMemScanner.m_lpAddrList ->m_nAddrListCnt));
    MessageBox(strTip);
}

void CGameEditorDlg::UpdataProcessList()  //更新进程列表函数
{
    HANDLE hSnapShot;
    PROCESSENTRY32 stProcessEntry32 
= {0};
    
int nIndex;
    CString strItemText;

    hSnapShot 
= ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    
if(hSnapShot == INVALID_HANDLE_VALUE)
        
return;

    m_clsProcessList.DeleteAllItems();  
//删除进程列表框所有项
    nIndex = 0;

    stProcessEntry32.dwSize 
= sizeof stProcessEntry32;
    
if(::Process32First(hSnapShot,&stProcessEntry32))
    { 
        
do
        {     
            strItemText 
= stProcessEntry32.szExeFile;
            m_clsProcessList.InsertItem(nIndex,strItemText,
0);
            strItemText.Format(
"%d",stProcessEntry32.th32ProcessID);
            m_clsProcessList.SetItemText(nIndex,
1,strItemText);
            nIndex
++;
        } 
        
while(::Process32Next(hSnapShot, &stProcessEntry32)); 
    }
    
//strItemText.Format("总共进程数:%d",nIndex);
    
//MessageBox(strItemText);
    ::CloseHandle(hSnapShot);
}

void CGameEditorDlg::OnDblclkProcesslist(NMHDR* pNMHDR, LRESULT* pResult)  //进程列表框鼠标双击事件处理过程
{
    
// TODO: Add your control notification handler code here
    int nIndex;
    CString strItemText;

    nIndex 
= (int)m_clsProcessList.GetFirstSelectedItemPosition();  //获取进程列表框当前所选择的行的索引号(从1开始)
    if(!nIndex)  //索引号为0则未选择任何一行
        return;

    strItemText 
= m_clsProcessList.GetItemText(nIndex - 1,0);  //获取进程列表框指定行和列的文本值(从0开始);
    SetDlgItemText(IDE_PNAME,strItemText);  //设置进程名称文本框内容
    strItemText = m_clsProcessList.GetItemText(nIndex - 1,1);  //获取进程列表框指定行和列的文本值(从0开始);
    SetDlgItemText(IDE_PID,strItemText);  //设置进程ID文本框内容
    m_bFirst = TRUE;

    
*pResult = 0;
}

void CGameEditorDlg::UpdataAddrList()  //更新地址列表函数
{
    
int nCount,i;
    DWORD dwAddr,dwValue 
= 0;
    CString strItemText;

    m_clsAddrList.DeleteAllItems();  
//删除地址列表框所有项

    nCount 
= m_clsMemScanner.m_lpAddrList ->m_nAddrListCnt;
    
for(i = 0; i < nCount; i++)
    {
        dwAddr 
= m_clsMemScanner.m_lpAddrList ->m_lpAddrList[i];
        m_clsMemScanner.ReadMemory(dwAddr,
&dwValue);
        strItemText.Format(
"%d",i + 1);
        m_clsAddrList.InsertItem(i,strItemText,
0);
        strItemText.Format(
"0x%08X",dwAddr);
        m_clsAddrList.SetItemText(i,
1,strItemText);
        strItemText.Format(
"%d",dwValue);
        m_clsAddrList.SetItemText(i,
2,strItemText);
    }
}

void CGameEditorDlg::OnReset()  //重置按钮单击事件处理过程
{
    
// TODO: Add your control notification handler code here
    m_bFirst = TRUE;
}

void CGameEditorDlg::OnDblclkAddrlist(NMHDR* pNMHDR, LRESULT* pResult)  //地址列表框鼠标双击事件处理过程
{
    
// TODO: Add your control notification handler code here
    int nIndex = 0;
    
    nIndex 
= (int)m_clsAddrList.GetFirstSelectedItemPosition();  //获取进程列表框当前所选择的行的索引号(从1开始)
    if(!nIndex)  //索引号为0则未选择任何一行
        return;
    
    CModifyDlg clsModifyDlg 
= new CModifyDlg(this);
    clsModifyDlg.m_lpMainDlg 
= this;
    clsModifyDlg.m_strModifyAddr 
= m_clsAddrList.GetItemText(nIndex - 1,1);  //获取进程列表框指定行和列的文本值(从0开始);
    if(clsModifyDlg.DoModal() == 1)  //显示修改内存模态对话框
        UpdataAddrList();  //更新地址列表
    delete clsModifyDlg;

    
*pResult = 0;
}

BOOL CGameEditorDlg::PreTranslateMessage(MSG
* pMsg) 
{
    
// TODO: Add your specialized code here and/or call the base class
    if(pMsg -> message == WM_KEYDOWN)
    {
        
switch(pMsg -> wParam)
        {
        
case VK_RETURN:  //屏蔽回车键
        case VK_ESCAPE:  //屏蔽ESC键
            return TRUE;
        }
    }
    
return CDialog::PreTranslateMessage(pMsg);
}

ModifyDlg.h(修改对话框类)

#if !defined(AFX_MODIFYDLG_H__540F01D9_9707_4D58_885D_3131C1FA4AB8__INCLUDED_)
#define AFX_MODIFYDLG_H__540F01D9_9707_4D58_885D_3131C1FA4AB8__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// ModifyDlg.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CModifyDlg dialog
#include "GameEditorDlg.h"

class CModifyDlg : public CDialog
{
// Construction
public:
    CModifyDlg(CWnd
* pParent = NULL);   // standard constructor

// Dialog Data
    
//{{AFX_DATA(CModifyDlg)
    enum { IDD = IDD_MODIFYDLG };
        
// NOTE: the ClassWizard will add data members here
    
//}}AFX_DATA


// Overrides
    
// ClassWizard generated virtual function overrides
    
//{{AFX_VIRTUAL(CModifyDlg)
    public:
    
virtual BOOL PreTranslateMessage(MSG* pMsg);
    
protected:
    
virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    
//}}AFX_VIRTUAL

// Implementation
protected:
    HICON m_hIcon;
public:
    CGameEditorDlg 
* m_lpMainDlg;  //主窗口对象指针
    CString m_strModifyAddr;  //从主窗口传递过来的用户欲修改的内存的地址值

    
// Generated message map functions
    
//{{AFX_MSG(CModifyDlg)
    afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
    afx_msg 
void OnOk();
    
virtual BOOL OnInitDialog();
    afx_msg 
void OnCancel();
    
//}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_MODIFYDLG_H__540F01D9_9707_4D58_885D_3131C1FA4AB8__INCLUDED_)

ModifyDlg.cpp

// ModifyDlg.cpp : implementation file
//

#include 
"stdafx.h"
#include 
"GameEditor.h"
#include 
"ModifyDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CModifyDlg dialog


CModifyDlg::CModifyDlg(CWnd
* pParent /*=NULL*/)
    : CDialog(CModifyDlg::IDD, pParent)
{
    
//{{AFX_DATA_INIT(CModifyDlg)
        
// NOTE: the ClassWizard will add member initialization here
    
//}}AFX_DATA_INIT
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}


void CModifyDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    
//{{AFX_DATA_MAP(CModifyDlg)
        
// NOTE: the ClassWizard will add DDX and DDV calls here
    
//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CModifyDlg, CDialog)
    
//{{AFX_MSG_MAP(CModifyDlg)
    ON_WM_CTLCOLOR()
    ON_BN_CLICKED(IDB_OK, OnOk)
    ON_BN_CLICKED(IDB_CANCEL, OnCancel)
    
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CModifyDlg message handlers

HBRUSH CModifyDlg::OnCtlColor(CDC
* pDC, CWnd* pWnd, UINT nCtlColor) 
{
    HBRUSH hbr 
= CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
    
    
// TODO: Change any attributes of the DC here
    if(pWnd -> GetDlgCtrlID() == IDE_ADDR)
    {
        pDC
->SetBkColor(RGB(255,255,255));
        pDC
->SetTextColor(RGB(255,0,0));   
        
return (HBRUSH)GetStockObject(WHITE_BRUSH);
    }
    
// TODO: Return a different brush if the default is not desired
    return hbr;
}

void CModifyDlg::OnOk()  //确定按钮单击事件处理过程
{
    
// TODO: Add your control notification handler code here
    DWORD dwAddr = 0,dwValue = 0;

    
if(GetDlgItem(IDE_VALUE) ->GetWindowTextLength() <= 0)
        
return;

    m_strModifyAddr 
= m_strModifyAddr.Mid(2);  //去掉"0x"
    sscanf(m_strModifyAddr,"%x",&dwAddr);  //转换成数字

    dwValue 
= GetDlgItemInt(IDE_VALUE);
    m_lpMainDlg 
->m_clsMemScanner.WriteMemory(dwAddr,dwValue);  //修改内存
    MessageBox("修改成功!");
    EndDialog(
1);
}

BOOL CModifyDlg::OnInitDialog()  
//对话框初始化函数
{
    CDialog::OnInitDialog();
    
    
// TODO: Add extra initialization here
    SetIcon(m_hIcon, TRUE);            // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon

    SetDlgItemText(IDE_ADDR,m_strModifyAddr);  
//设置目标地址文本框内容

    
return TRUE;  // return TRUE unless you set the focus to a control
                  
// EXCEPTION: OCX Property Pages should return FALSE
}

void CModifyDlg::OnCancel()  //取消对话框单击事件处理过程
{
    
// TODO: Add your control notification handler code here
    EndDialog(0);
}

BOOL CModifyDlg::PreTranslateMessage(MSG
* pMsg) 
{
    
// TODO: Add your specialized code here and/or call the base class
    if(pMsg -> message == WM_KEYDOWN)
    {
        
switch(pMsg -> wParam)
        {
        
case VK_RETURN:  //屏蔽回车键
        case VK_ESCAPE:  //屏蔽ESC键
            return TRUE;
        }
    }
    
return CDialog::PreTranslateMessage(pMsg);
}