参考C++项目开发实战入门的第四章内容,书里面写的太简略了,自己实现的时候整理了一下。
建立对话框
建立一个基于对话框的MFC程序MemoryCheatDlg,绘制主界面,主对话框ID:IDD_MEMORYCHEAT_DIALOG:
包括进度条,多个编辑框,两个复选框,多个按钮,两个List Box。
新建一个对话框用于32位进程显示,对话框ID:IDD_DIALOG_PROGRESS_LIST
为进程对话框添加关联类CDialogProgress
对话框跳转
双击主对话框的“进程”按钮,添加打开32位进程列表对话框的按键处理函数。进程对话框返回时,主对话框获取进程对话框设置的当前选中的进程id值,根据选择的进程id,在主对话框中打开该进程。
void CMemoryCheatDlg::OnBnClickedButtonProgress()
{
// 显示 进程列表对话框
CDialogProgress dlg(this);
if (IDOK != dlg.DoModal()) {
// 取消的情况下,清0
m_dwProcessId = 0;
return;
}
// 获得选择的进程id
m_dwProcessId = CDialogProgress::m_dwProcessId;
// 把本窗口设置为 目标进程名
SetWindowText(CDialogProgress::m_strProcessName);
// 打开进程
m_pFinder->OpenProcess(m_dwProcessId);
}
列出所有32位进程
对进程对话框的关联类CDialogProgress进行编辑。对进程列表关联变量m_lst,设置一个进程ID和双击列表项的事件处理函数OnNMDblclkList1
public:
// 32位进程列表
CListCtrl m_lst;
// 进程列表的图标
CImageList m_imgList;
// 获取32位进程,并更新到进程列中
BOOL GetProcessList();
// 当选选中的进程的ID
static DWORD m_dwProcessId;
// 录脱选中的进程名
static CString m_strProcessName;
// 双击进程列表事件(当选中了一行时, 设置 m_dwProcessId 和 m_strProcessName,并关闭本对话框)
afx_msg void OnNMDblclkList1(NMHDR *pNMHDR, LRESULT *pResult);
在GetProcessList()函数中读取系统所有的32位程序并显示在列表中,hh是一个自定义的namespace,里面包括一些判断进程位数的方法。
/ 通过进程快照,遍历进程
// 并判断进程是否是32位进程
// 如果是32位进程,则加入进程列表m_lst中
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;
hProcessSnap = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE) {
// 创建快照失败,返回
return(FALSE);
}
// 获得第一个进程
pe32.dwSize = sizeof (PROCESSENTRY32);
if (!Process32First (hProcessSnap, &pe32)) {
CloseHandle (hProcessSnap);
return(FALSE);
}
do {
// 判数是否是32位进程
if (hh::Is32BitProcess (pe32.th32ProcessID)) {
// 如果获取图标成功, 表示图标在m_imgList中的位置
int indexIco = -1;
// 获取进程图标,并加入到 m_imgList中
{
HICON hIco = 0;
if (hh::GetProcessIco (pe32.th32ProcessID, hIco)) {
// 如果有图标,加入列表
indexIco = m_imgList.Add (hIco);
}
}
// 插入新行
{
// 进程名
int index = m_lst.InsertItem (m_lst.GetItemCount (),
pe32.szExeFile, indexIco);
//进程ID
CString s;
s.Format (_T ("%d"), pe32.th32ProcessID);
m_lst.SetItemText (index, 1, s);
// 设置该行数据
m_lst.SetItemData (index, (DWORD_PTR)pe32.th32ProcessID);
}
}
else {
// 不是32位进程,什么也不做
}
}
// 获得下一个进程
while (Process32Next (hProcessSnap, &pe32));
// 关闭 快照句柄
CloseHandle (hProcessSnap);
return(TRUE);
}
初始化函数中添加:
// 控件
{
LONG lStyle = GetWindowLong (m_lst.m_hWnd, GWL_STYLE);
lStyle &= ~LVS_TYPEMASK;
lStyle |= LVS_REPORT;
SetWindowLong (m_lst.GetSafeHwnd (), GWL_STYLE, lStyle);
DWORD dwStyle = m_lst.GetExtendedStyle ();
dwStyle |= LVS_EX_FULLROWSELECT; //选中行 整征高亮
dwStyle |= LVS_EX_GRIDLINES; //网络线
m_lst.SetExtendedStyle (dwStyle);
// 设置列,并设置大小
{
CRect rc;
m_lst.GetClientRect (rc);
m_lst.InsertColumn (0, _T ("进程名"), LVCFMT_LEFT, rc.Width () / 2);
m_lst.InsertColumn (1, _T ("进程ID"), LVCFMT_LEFT, rc.Width () / 2);
}
// 设置控件关联的图标列表,这样才可以在每行的开头显示图标
m_imgList.Create (16, 16, ILC_COLOR32, 1, 1);
m_lst.SetImageList (&m_imgList, LVSIL_SMALL);
}
//列出进程
GetProcessList ();
打开该对话框后,直接列出所有32位进程:
变量搜索
修改程序需要通过输入变量值对变量地址进行搜索来定位控制当前物体的变量地址。在主对话框设置搜索值、搜索范围、值类型就可以进行首次搜索。
比如阳光数为100,就可以输入100点首次搜索,可以获得植物大战僵尸程序进程当中所有值为100的变量地址。进度条显示当前搜索的进度。
MemFinder
新建一个头文件MemFinder.h专门存放用于进程处理的代码。
打开进程
// 打开进程
bool OpenProcess(DWORD dwProcessId)
{
// 如果进程是打开的,关闭
if(IsValidHandle()) {
SafeCloseHandle();
}
// 打开
m_hProcess = ::OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE |
PROCESS_VM_OPERATION | PROCESS_CREATE_THREAD |
PROCESS_QUERY_INFORMATION,
FALSE, dwProcessId);
if(IsValidHandle()) {
return true;
}
else {
SafeCloseHandle();
return false;
}
}
首次搜索
定义一个public的
bool FindFirst(DWORD dwProcessId, DWORD dwBegin, DWORD dwEnd, T value)
{
m_arList.clear();
return _FindFirst(dwProcessId, dwBegin, dwEnd, value);
}
再定义一个private的
bool _FindFirst(DWORD dwProcessId, DWORD dwBegin, DWORD dwEnd, T value)