关于怎样写植物大战僵尸游戏修改器的详细过程,在手把手教你写游戏修改器里面已经详细介绍了,这里就不再说了。前面那个修改器是基于控制台程序下面的,紧紧对于植物大战僵尸有用,采用上面那个教程已经将游戏修改器的制作流程和原理讲清楚了,现在我们开始做一个完整的游戏修改器。
1、建立一个对话框工程,建立过程VC怎样建立对话框工程中已经介绍了。这里不再介绍
2、绘制如下界面
其中个控件ID如下:
列表控件:IDC_PROCESSINFO
编辑框 :IDC_INPUT
静态文本框:IDC_SHOW
查看进程信息按钮:IDC_LOOKUPINFO
确定按钮 :IDC_OK
3、具体思路
首先应该得到目前所有进程的ID,因为后面要找到进程的句柄,因此当用户点击查看所有进程信息时显示目前计算机所有进程信息,并记录每个进程的ID。如下图
根据输入的进程编号,锁定用户想查找的进程。
然后根据用户输入的数据根据上篇文章说的方法进行查找就行,主要问题就是Windows编程中涉及的一些知识,都是一些简单的从控制台转换到Windows界面控制,应该不难。
下面直接给出代码:
#include "stdafx.h"
#include <windows.h>
#include <windowsx.h>
#include "resource.h"
#include "MainDlg.h"
#include <commctrl.h>
#include <tlhelp32.h>
typedef struct PROCESSINFOS {TCHAR Info[255];int no;DWORD ProcessID;} ProcessInfos;
ProcessInfos ProcessInfoS[200];
int MaxNum = 0;
int x=0;
DWORD tProcessID;
DWORD g_arList[999999]; //地址列表
int g_nListCnt=0; //有效地址个数
TCHAR Mess1[20] = "进程编号:";
TCHAR Mess2[20] = "进程名称";
void InitListView(HWND hwnd)
{
HWND hwndListView=GetDlgItem(hwnd,IDC_PROCESSINFO);
//设置列表框控件格式
DWORD dwExStyle =LVS_EX_GRIDLINES;
ListView_SetExtendedListViewStyle(hwndListView,dwExStyle);
//设置列
LVCOLUMN column[2];
ZeroMemory(column,sizeof(column));
column[0].mask = LVCF_TEXT|LVCF_FMT|LVCF_WIDTH;
column[0].pszText = Mess1;
column[0].fmt = LVCFMT_CENTER;
column[0].cx = 80;
column[1].mask = LVCF_TEXT|LVCF_FMT|LVCF_WIDTH;
column[1].pszText = Mess2;
column[1].fmt = LVCFMT_CENTER;
column[1].cx = 410;
SendDlgItemMessage(hwnd, IDC_PROCESSINFO, LVM_INSERTCOLUMN,0, (LPARAM)&column[0]);
SendDlgItemMessage(hwnd, IDC_PROCESSINFO, LVM_INSERTCOLUMN,1, (LPARAM)&column[1]);
}
void ShowProcessInfo(HWND hwnd)
{
int i=0;
char ans[100];
LVITEM lvItem;
lvItem.mask = LVIF_TEXT;
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);
HWND hwndListView=GetDlgItem(hwnd,IDC_PROCESSINFO);
HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(hProcessSnap == INVALID_HANDLE_VALUE) return;
BOOL bMore = ::Process32First(hProcessSnap,&pe32);
while(bMore)
{
lvItem.iItem = i;
itoa(i,ans,10);
lvItem.iSubItem = 0;
lvItem.pszText = ans;
ListView_InsertItem(hwndListView,(LPARAM)&lvItem);
ListView_SetItemText(hwndListView, i, 1, pe32.szExeFile);
wsprintf(ProcessInfoS[i].Info,pe32.szExeFile);
ProcessInfoS[i].no = i;
ProcessInfoS[i].ProcessID = pe32.th32ProcessID;
i++;
MaxNum++;
bMore = ::Process32Next(hProcessSnap,&pe32);
}
::CloseHandle(hProcessSnap);
}
int LockProcess(HWND hwnd)
{
int num;
TCHAR info[255];
ZeroMemory(info,sizeof(info));
GetDlgItemText(hwnd,IDC_INPUT,info,sizeof(info));
num = atoi(info);
if(num<MaxNum)
{
x=1;
tProcessID = ProcessInfoS[num].ProcessID;
// MessageBox(hwnd,ProcessInfoS[num].Info,TEXT(""),MB_OK);
SetDlgItemText(hwnd,IDC_SHOW,TEXT("请输入第一次查找的值:"));
return 1;
}
else
{
MessageBox(hwnd,TEXT("不存在改编号的进程!!!"),TEXT("错误"),MB_OK|MB_ICONERROR);
return 0;
}
}
BOOL CompareAPage(HANDLE hProcess,DWORD dwBaseAddr,DWORD dwValue)
{
//读取第一页
BYTE arBytes[4094];
if(!::ReadProcessMemory(hProcess,(LPVOID)dwBaseAddr,arBytes,4096,NULL))
{
return FALSE; //此页不可读
}
DWORD *pdw;
for(int i=0;i<(int)4*1024-3;i++)
{
pdw = (DWORD *)&arBytes[i];
if(pdw[0]==dwValue) //等于要查找的值
{
g_arList[g_nListCnt++] = dwBaseAddr+i;
}
}
return TRUE;
}
//第一次查找
BOOL FindFirst(HANDLE hProcess,DWORD dwValue)
{
const DWORD dwOneGB = 1024*1024*1024; //1GB
const DWORD dwOnePage = 4*1024; //4KB
if(hProcess==FALSE)
{
return FALSE;
}
//查看操作系统类型,确定开始地址
DWORD dwBase;
OSVERSIONINFO vi = {sizeof(vi)};
::GetVersionEx(&vi);
if(vi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
dwBase = 4*1024*1024; //4MB
else
{
dwBase = 640*1024; //64KB
}
//在开始地址到2GB地址空间寻找
for(;dwBase<2*dwOneGB;dwBase +=dwOnePage)
{
//比较一页大小的内存
CompareAPage(hProcess,dwBase,dwValue);
}
return TRUE;
}
void ShowList(HWND hwnd)
{
LVITEM lvItem;
lvItem.mask = LVIF_TEXT;
int i;
TCHAR ans[20];
TCHAR MessAdd[20];
HWND hwndListView=GetDlgItem(hwnd,IDC_PROCESSINFO);
for(i=0;i<g_nListCnt;i++)
{
ZeroMemory(ans,sizeof(ans));
ZeroMemory(MessAdd,sizeof(MessAdd));
lvItem.iItem = i;
itoa(i,ans,10);
lvItem.iSubItem = 0;
lvItem.pszText = ans;
ListView_InsertItem(hwndListView,(LPARAM)&lvItem);
wsprintf(MessAdd,"%x",g_arList[i]);
ListView_SetItemText(hwndListView, i, 1, MessAdd);
// printf("%08X\n",g_arList[i]);
}
}
BOOL FindNext(HWND hwnd,HANDLE hProcess,DWORD dwValue)
{
//保存g_arList数组有效地址的个数,初始化g_nLisatCnt值
int nOrgCnt = g_nListCnt;
g_nListCnt = 0;
//在g_arList中寻找
BOOL bRet = FALSE;
DWORD dwReadValue;
for(int i=0;i<nOrgCnt;i++)
{
if(::ReadProcessMemory(hProcess,(LPVOID)g_arList[i],&dwReadValue,sizeof(DWORD),NULL))
{
if(dwReadValue==dwValue)
{
g_arList[g_nListCnt++] = g_arList[i];
bRet = TRUE;
}
}
}
if(g_nListCnt>1)
{
SetDlgItemText(hwnd,IDC_INPUT,"");
}
if(g_nListCnt==1)
{
x=3;
SetDlgItemText(hwnd,IDC_SHOW,"请输入要修改的值:");
SetDlgItemText(hwnd,IDC_INPUT,"");
}
return bRet;
}
BOOL WriteMemory(HANDLE hProcess,DWORD dwAddr,DWORD dwValue)
{
return ::WriteProcessMemory(hProcess,(LPVOID)dwAddr,&dwValue,sizeof(DWORD),NULL);
}
BOOL WINAPI Main_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
HANDLE_MSG(hWnd, WM_INITDIALOG, Main_OnInitDialog);
HANDLE_MSG(hWnd, WM_COMMAND, Main_OnCommand);
HANDLE_MSG(hWnd,WM_CLOSE, Main_OnClose);
}
return FALSE;
}
BOOL Main_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
{
InitListView(hwnd);
SetDlgItemText(hwnd,IDC_SHOW,"输入锁定的进程编号:");
ZeroMemory(ProcessInfoS,sizeof(ProcessInfoS));
return TRUE;
}
void Main_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
{
switch(id)
{
case IDC_OK:
{
HANDLE hProcess;
if(0==x)
{
SetDlgItemText(hwnd,IDC_SHOW,"输入锁定的进程编号:");
int i = LockProcess(hwnd);
//查找进程的句柄
if(i==1)
{
hProcess = ::OpenProcess(PROCESS_ALL_ACCESS,FALSE,tProcessID);
MessageBox(hwnd,TEXT("进程已锁定!!!"),TEXT("锁定进程成功"),MB_OK);
}
break;
}
if(1==x)
{
int iVal;
TCHAR Fnum[255];
hProcess = ::OpenProcess(PROCESS_ALL_ACCESS,FALSE,tProcessID);
GetDlgItemText(hwnd,IDC_INPUT,Fnum,sizeof(Fnum));
iVal = atoi(Fnum);
FindFirst(hProcess,iVal);
wsprintf(Mess1,"序号");
wsprintf(Mess2,"地址");
InitListView(hwnd);
if(g_nListCnt>=1)
{
if(g_nListCnt>1)
{
MessageBox(hwnd,TEXT("第一次搜索完成!!!"),TEXT("成功"),MB_OK);
ShowList(hwnd);
SetDlgItemText(hwnd,IDC_SHOW,"请输入下一次的值:");
SetDlgItemText(hwnd,IDC_INPUT,"");
x=2;
}
if(g_nListCnt==1)
{
MessageBox(hwnd,TEXT("第一次搜索完成!!!"),TEXT("成功"),MB_OK);
ShowList(hwnd);
SetDlgItemText(hwnd,IDC_SHOW,"请输入要修改的值:");
SetDlgItemText(hwnd,IDC_INPUT,"");
x=3;
}
}
break;
}
if(2==x)
{
DWORD iVal;
TCHAR Fnum[255];
while(g_nListCnt>1)
{
hProcess = ::OpenProcess(PROCESS_ALL_ACCESS,FALSE,tProcessID);
GetDlgItemText(hwnd,IDC_INPUT,Fnum,sizeof(Fnum));
iVal = atoi(Fnum);
FindNext(hwnd,hProcess,iVal);
//显示查找结果
ShowList(hwnd);
}
break;
}
if(3==x)
{
int iVal;
TCHAR Fnum[255];
hProcess = ::OpenProcess(PROCESS_ALL_ACCESS,FALSE,tProcessID);
GetDlgItemText(hwnd,IDC_INPUT,Fnum,sizeof(Fnum));
iVal = atoi(Fnum);
if(WriteMemory(hProcess,g_arList[0],iVal))
{
MessageBox(NULL,TEXT("修改成功"),TEXT("成功"),MB_OK);
}
break;
}
}
break;
case IDC_LOOKUPINFO:
{
ShowProcessInfo(hwnd);
}
break;
default:
break;
}
}
void Main_OnClose(HWND hwnd)
{
EndDialog(hwnd, 0);
}