1.继续任务管理器
1.1 给 第一次搜索 按钮添加事件处理函数 CTaskManagerDlg::OnBnClickedButton5 ;
1.给 CModifyMemory 类添加函数: void FirstFind(DWORD nFindValue) ; void FindOnePage(DWORD dwPageBeginAddr, DWORD nFindValue) ;
2.在 void FirstFind(DWORD nFindValue) 函数中首先查找虚拟空间中前2GB的地址,定义查找的起始位置: DWORD dw_begin_addr = 64 * 1024 ;
3.定义查找结束的地址: ULONG dw_end_addr = (ULONG)(2UL * 1024UL * 1024UL * 1024UL) ;
4.定义一页的大小: DWORD dw_one_page = 4096 ;
5.开始查找
void CModifyMemory::FirstFind(DWORD nFindValue)
{
DWORD dw_begin_addr = 64 * 1024; // 开始查找的地址
ULONG dw_end_addr = (ULONG)(2UL * 1024UL * 1024UL * 1024UL); // 结束查找的地址
DWORD dw_one_page = 4096; // 一页的大小
// 进行一页一页地查找
for(; dw_begin_addr<dw_end_addr; dw_begin_addr+=dw_one_page)
this->FindOnePage(dw_begin_addr, nFindValue);
}
6.完成 FindOnePage 函数,首先用一个数组来存储查找到的内容: DWORD sz_buffer[1024] = {0} ;
7.读进程地址空间的内容,读失败则返回: if(0 == ::ReadProcessMemory(m_hOpenPracess, (LPCVOID)dwPageBeginAddr, (LPVOID)sz_buffer, 4096, 0)) return ;
8.读取成功则查找偏移量,创建一个成员 list m_lst_addr 来存储与查找值相同的地址;
// 读取一页的内容
void CModifyMemory::FindOnePage(DWORD dwPageBeginAddr, DWORD nFindValue)
{
// 用一个数组来存储读到的内容
DWORD sz_buffer[1024] = {0};
// 读进程地址空间的内容
// 读取失败则返回
if(0 == ::ReadProcessMemory(m_hOpenPracess, (LPCVOID)dwPageBeginAddr, (LPVOID)sz_buffer, 4096, 0))
return;
// 读取成功则查找偏移量
for(int i=0; i<1024; i++)
{
if(sz_buffer[i] == nFindValue)
{
// 将其地址插入到链表中
m_lst_addr.push_back(dwPageBeginAddr + i * 4);
}
}
}
1.2 给 CModifyMemory 类添加函数 ShowAllAddr
1.该函数的功能就是在右侧的 List 控件中显示与要查找值相同的地址;
2.遍历 m_lst_addr 中的元素,并在 List 控件中显示地址;
void CModifyMemory::ShowAllAddr(CListCtrl* pListCtrl)
{
list<DWORD>::iterator ite = m_lst_addr.begin();
while (ite != m_lst_addr.end())
{
CString str_addr;
str_addr.Format(L"%d", (*ite));
pListCtrl->InsertItem(pListCtrl->GetItemCount(), str_addr);
++ite;
}
}
3.在 第一次查找 按钮中进行调用该函数
// 第一次查找按钮
void CTaskManagerDlg::OnBnClickedButton5()
{
m_ls_showaddr.DeleteAllItems();
// 取得要查找的值
UpdateData(TRUE);
// 开始查找
mm.FirstFind(m_dw_findvalue);
if(mm.m_lst_addr.empty() == false)
{
// 将所有查找结果进行显示
mm.ShowAllAddr(&m_ls_showaddr);
}
}
1.3 完成 第二次查找 按钮的消息处理函数
1.给类 CModifyMemory 添加一个 void SecondFind(DWORD nFindValue) 函数;
2.在该函数中,我们首先遍历存储第一次查找结果的链表,其次读取每个地址的值,读取成功则与第二次要查找的值进行比较,否则删除链表中的节点;
void CModifyMemory::SecondFind(DWORD nFindValue)
{
list<DWORD>::iterator ite = m_lst_addr.begin();
while (ite != m_lst_addr.end())
{
// 读取4个字节
DWORD n_value = 0;
if(::ReadProcessMemory(m_hOpenPracess, (LPCVOID)(*ite), (LPVOID)&n_value, 4, 0) == TRUE)
{
// 读取成功则判断是不是要找的值
if(n_value != nFindValue)
{
// 若不是要查找的值,则删除这个节点
ite = m_lst_addr.erase(ite);
}
else
{
++ite;
}
}
else
{
// 读取失败也要删除该节点
ite = m_lst_addr.erase(ite);
}
}
}
3.在 第二次查找 按钮的消息处理函数中调用上述函数;
// 第二次查找按钮
void CTaskManagerDlg::OnBnClickedButton6()
{
m_ls_showaddr.DeleteAllItems();
// 取得要查找的值
UpdateData(TRUE);
// 开始查找
mm.SecondFind(m_dw_findvalue);
if(mm.m_lst_addr.empty() == false)
{
// 将所有查找结果进行显示
mm.ShowAllAddr(&m_ls_showaddr);
}
}
1.4 修改钱币的值
1.在 CModifyMemory 类中添加一个 bool ModifyMemory(DWORD mModifyAddr, DWORD mModifyValue) 函数;
2.在 CModifyMemory::ModifyMemory 函数中进行写内存的操作;
bool CModifyMemory::ModifyMemory(DWORD mModifyAddr, DWORD mModifyValue)
{
if(::WriteProcessMemory(m_hOpenPracess, (LPVOID)mModifyAddr, (LPCVOID)&mModifyValue, 4, 0) == TRUE)
{
return true;
}
else
{
return false;
}
}
3.在 修改 按钮处进行调用该函数;
// 修改值的按钮
void CTaskManagerDlg::OnBnClickedButton8()
{
// 取得要查找的值
UpdateData(TRUE);
if(mm.ModifyMemory(m_dw_changeaddr, m_dw_changevalue) == true)
{
MessageBox(L"修改成功");
}
else
{
MessageBox(L"修改失败");
}
}
1.5 清空 按钮
// 清空 按钮
void CTaskManagerDlg::OnBnClickedButton7()
{
// 清空链表
mm.m_lst_addr.clear();
m_ls_showaddr.DeleteAllItems();
}