请教高手!MFC编写游戏内存修改器遇到错误:仅完成部分的 ReadProcessMemoty 或 WriteProcessMemory 请求。

xujiaming303 2012-03-01 05:35:21
编写该程序执行以下步骤:
1) 提高本进程的权限;
2)进程快照,找到游戏进程ID号;
3)通过游戏进程ID号打开游戏进程,OpenProcess();
4)通过ReadProcess()搜索游戏中对应游戏角色属性(如:血条)的变量地址;
5) 通过WriteProcess()修改搜索到的地址单元的数据;

部分代码如下:
1)提高本进程的权限:
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);
HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(hProcessSnap == INVALID_HANDLE_VALUE)
{
MessageBox("进程快照操作失败!");
return FALSE;
}
TOKEN_PRIVILEGES tkp; // 进程令牌环权限结构
HANDLE hToken; // 进程令牌环句柄
// 在快照列表中找到本进程并提升本进程的权限
BOOL bMore = ::Process32First(hProcessSnap,&pe32);
while(bMore)
{
char arProcName[50];
::wsprintf(arProcName,"%s",pe32.szExeFile);
// 提升本进程权限
if(!strcmp(arProcName,"GameModify.exe"))
{
//获得debug权限的LUID
if(!::LookupPrivilegeValue(NULL,"SeDebugPrivilege",&tkp.Privileges[0].Luid))
{
::MessageBox(NULL,"LookupPrivilegeValue error","error",MB_OK);
exit(0);
}
tkp.PrivilegeCount=1;
tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED; // 进程权限使能
//打开进程的令牌环
if(!::OpenProcessToken(::GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
{
::MessageBox(NULL,"OpenProcessToken error","error",MB_OK);
exit(0);
}
//修改进程权限
if(!::AdjustTokenPrivileges(hToken,FALSE,&tkp,0,(PTOKEN_PRIVILEGES)NULL, 0))
{
::MessageBox(NULL,"AdjustTokenPrivileges error","error",MB_OK);
exit(0);
}
CloseHandle(hToken);
break;
}
bMore = ::Process32Next(hProcessSnap,&pe32);
}
if(!bMore)
MessageBox("未找到 GameModify.exe 进程!");
::CloseHandle(hProcessSnap);

2)进程快照,找到游戏进程ID号;
BOOL CGameModifyDlg::UpdateProcList()
{
m_ctlProcList.ResetContent();
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);
HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(hProcessSnap == INVALID_HANDLE_VALUE)
{
MessageBox("进程快照操作失败!");
exit(0);
}
char strText[50];
BOOL bMore = ::Process32First(hProcessSnap,&pe32);
int nItem=0; // 列表项序号
while(bMore)
{
wsprintf(strText,"%s ( %d )",pe32.szExeFile,pe32.th32ProcessID);
m_ctlProcList.InsertString(nItem,strText);
m_ctlProcList.SetItemData(nItem,pe32.th32ProcessID);
nItem++;
bMore = ::Process32Next(hProcessSnap,&pe32);
}
m_ctlProcList.SetCurSel(nItem-1);
m_dwProcessID = m_ctlProcList.GetItemData(nItem-1);
::CloseHandle(hProcessSnap);
UpdateData(FALSE);
return TRUE;
}

void CGameModifyDlg::OnSelchangeComboProclist()
{
// TODO: Add your control notification handler code here
int nItem = m_ctlProcList.GetCurSel(); // 获取当前选择的索引序号
m_dwProcessID = m_ctlProcList.GetItemData(nItem);
UpdateData(FALSE);
}


3)通过游戏进程ID号打开游戏进程,OpenProcess();
void CGameModifyDlg::OnButtonSearch()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);

m_ctlProcList.EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON_UPDATE)->EnableWindow(FALSE);

g_hProcess = OpenProcess(PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_VM_OPERATION,FALSE,m_dwProcessID);
if(!g_hProcess)
{
DWORD dwErrorCode = GetLastError();
CString str;
str.Format("打开进程错误,错误代码:%d",dwErrorCode);
MessageBox(str,"错误!");
}
FindFirst(m_dwValue);
m_strResult.Format("搜索到%d个结果",g_nListCnt);

UpdateData(FALSE);

::CloseHandle(g_hProcess);
}

BOOL CGameModifyDlg::FindFirst(DWORD dwValue)
{
const DWORD dwOneGB = 1024*1024*1024; // 1GB
const DWORD dwOnePage = 4*1024; //4KB
if(g_hProcess == NULL)
{
MessageBox("尚未打开进程!");
return FALSE;
}
// 查看操作系统类型,以决定开始地址
DWORD dwBaseAddr;
OSVERSIONINFO vi = { sizeof(vi) };
::GetVersionEx(&vi);
if(vi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
dwBaseAddr = 4*1024*1024; // Windows 98系列,4MB
else
dwBaseAddr = 640*24; // Windows 2000系列,64KB
// 以内存页为步进,遍历进程2GB的虚拟内存
for(;dwBaseAddr<2*dwOneGB;dwBaseAddr+=dwOnePage)
{
if(!CompareAPage(dwBaseAddr,dwValue))
return FALSE;
}
return TRUE;
}

BOOL CGameModifyDlg::CompareAPage(DWORD dwBaseAddr, DWORD dwValue)
{
BYTE arBytes[4096]; // 读取一页地址内存
if(!::ReadProcessMemory(g_hProcess,(LPCVOID)dwBaseAddr,arBytes,4096,NULL))
{
DWORD dwErrorCode = GetLastError();
char Text[30];
wsprintf(Text,"读取进程内存数据失败!\r\n错误代码:%d",dwErrorCode);
MessageBox(Text,"失败!");
return FALSE;
}
DWORD* pdw;
for(int i=0;i<(int)4*1024-3;i++)
{
pdw = (DWORD*)&arBytes[i];
if(pdw[0] == dwValue)
{
if(g_nListCnt>=ADDRLIST_MAXNUM)
{
MessageBox("地址列表产生溢出!");
return FALSE;
}
g_arAddrList[g_nListCnt++] = dwBaseAddr + i;
}
}
return TRUE;
}

程序执行到:
if(!::ReadProcessMemory(g_hProcess,(LPCVOID)dwBaseAddr,arBytes,4096,NULL))
{
DWORD dwErrorCode = GetLastError();
char Text[30];
wsprintf(Text,"读取进程内存数据失败!\r\n错误代码:%d",dwErrorCode);
MessageBox(Text,"失败!");
return FALSE;
}
出错,错误代码299:仅完成部分的 ReadProcessMemoty 或 WriteProcessMemory 请求。

小弟是初学者,初来乍道,请高手大虾指点指点!!
...全文
324 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧