当前所在位置:珠峰网资料 >> 计算机 >> 计算机等级考试 >> 正文
制作一个简单的游戏修改器
发布时间:2010/8/3 10:54:57 来源:城市学习网 编辑:ziteng
  一、制作背景和原理:
  在平时玩游戏的过程中,大家肯定会接触过形形色色的修改,特别是看到一些高手出的某某全能修,x项修改器,煞是羡慕,其实制作这样写一个这样的修改器一点也不神秘,  好了,请各位看官一同随我去揭开修改器之谜......“修改器”程序的就是修改我们想要数据的地址里面的数值,这句话比较拗口,但是这是“修改器”程序的关键。下面就以时兴的Normal tanks(坦克大战)为例,和大家讨论怎样去DIY一个游戏修改器请大家移步且随我步骤慢慢来。
  二、找到我们想要的内存地址:
  这是很关键的一步, 给大家介绍一款优秀的内存编辑工具)。
  在游戏中按热Ctrl+Tab返回桌面,在Quick Memory Editor中点击Add Task 。
  搜索炮弹的数量,当前游戏中是50,在Search value中填入50,然后点击Search,搜索速度很快,这会出来很结果,然后回到游戏里,随便放几炮,当前炮弹数量变为了47,然后返回桌面,在Quick
  Memory Editor中的Search value中填入47,点击Search, 这时候出来了几个结果,结果还是不是很精确。返回游戏,再随便放几炮,当前炮弹数量变成了43,再在Quick Memory
  Editor搜索43,这时候出来了仅一个结果,这就是我们需要的内存地址了,记下来004C9C84,等会儿我们要用到。
  三、介绍两个关键 API函数ReadProcessMemory()和 WriteProcessMemory():
  详细的注释我表明在函数里
  ①BOOL ReadProcessMemory(
  HANDLE hProcess, // 目标进程句柄
  LPCVOID lpBaseAddress, // 读取数据的起始地址
  LPVOID lpBuffer, // 存放数据的缓存区地址
  DWORD nSize, // 要读取的字节数
  LPDWORD lpNumberOfBytesRead ); // 实际读取的数据大小地址
  ReadProcessMemory()用于读取游戏进程中制定的内存数据; 在实际操作中,我们用它来读取存放炮弹数量地址中的数据。
  ②BOOL WriteProcessMemory(
  HANDLE hProcess, // 目标进程句柄
  LPVOID lpBaseAddress, // 进程的起始地址
  LPVOID lpBuffer, // 数据内容
  DWORD nSize, // 需要写入的字节数
  LPDWORD lpNumberOfBytesWritten); // 实际写入的数据大小的地址
  WriteProcessMemory()和上面的ReadProcessMemory()用法一样,在实际操作中,我们用它来修改存放炮弹数量地址中的数据。
  四、编程实现游戏修改(完整代码):
  #include <windows.h>
  HINSTANCE g_hInst;
  HWND  g_hWnd;
  char szAppName[]="TankFix"; //The name of the exe
  char szTitle[]="坦克大战修改";
  DWORD  addr=0x004C9C84;   //存放炮弹数量的内存地址
  DWORD  pid;      //坦克大战的PID
  int  val=1000;    //炮弹要修改的数量
  //-------------------------------------------------------------------------------------------------
  // WndProc- 窗口函数
  //-------------------------------------------------------------------------------------------------
  LRESULT CALLBACK WndProc(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
  {
  // int wmId,wmEvent;
  switch (message)
  {
  case WM_DESTROY:
  PostQuitMessage(0);
  break;
  case WM_TIMER:
  {
  HWND  hw=FindWindow(NULL,"Normal-tanks");  //FindWindow()得到坦克大战程序的句柄
  HANDLE hProcess;    //定义坦克大战的进程句柄
  if (hw!=0)
  {
  SetForegroundWindow(hw);    //使我们的坦克大战设置为当前窗口
  GetWindowThreadProcessId(hw,&pid);    //得到游戏的PID号
  hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);    //打开进程PROCESS_ALL_ACCESS参数,制定进程可读可写
  WriteProcessMemory(hProcess,(LPVOID)addr,&val,4,0);    //向坦克大战进程内存中写入数据
  }
  else
  MessageBox(g_hWnd,"游戏还没有运行吧!","提示信息",MB_OK|MB_ICONINFORMATION);
  }
  default:
  return (DefWindowProc(hWnd,message,wParam,lParam));
  }
  return 0;
  } [NextPage]   //-------------------------------------------------------------------------------------------------
  // InitApplication-注册窗口类
  //-------------------------------------------------------------------------------------------------
  BOOL InitApplication(HINSTANCE hInstance)
  {
  WNDCLASSEX winclass;
  winclass.cbSize = sizeof(WNDCLASSEX);
  winclass.style  = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  winclass.lpfnWndProc = WndProc;
  winclass.cbClsExtra = 0;
  winclass.cbWndExtra = 0;
  winclass.hInstance  = hInstance;
  winclass.hIcon  = LoadIcon(NULL, IDI_APPLICATION);
  winclass.hCursor  = LoadCursor(NULL, IDC_ARROW);
  winclass.hbrBackground  =(HBRUSH) GetStockObject(BLACK_BRUSH);
  winclass.lpszMenuName  = NULL;
  winclass.lpszClassName  = "WINCLASS1";
  winclass.hIconSm  = LoadIcon(NULL, IDI_APPLICATION);
  return (RegisterClassEx(&winclass));
  }
  //-------------------------------------------------------------------------------------------------
  // InitInstance-产生窗口,显示以及更新窗口
  //-------------------------------------------------------------------------------------------------
  BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
  {
  g_hInst=hInstance;
  g_hWnd=CreateWindowEx(NULL,
  "WINCLASS1",
  szTitle,
  WS_OVERLAPPEDWINDOW,
  CW_USEDEFAULT,
  CW_USEDEFAULT,
  CW_USEDEFAULT,
  CW_USEDEFAULT,
  NULL,
  NULL,
  hInstance,
  NULL);
  if(!g_hWnd)
  {
  return FALSE;
  }
  ShowWindow(g_hWnd,nCmdShow);
  UpdateWindow(g_hWnd);
  return TRUE;
  }
  int CALLBACK WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
  {
  MSG msg;
  UNREFERENCED_PARAMETER(lpCmdLine);
  if (!hPrevInstance)
  {
  if (!InitApplication(hInstance))
  {
  return (FALSE);
  }
  }
  if (!InitInstance(hInstance,nCmdShow))
  {
  return FALSE;
  }
  SetTimer(g_hWnd,1,150,NULL);
  while (GetMessage(&msg,NULL,0,0))
  {
  TranslateMessage(&msg);
  DispatchMessage(&msg);
  }
  return (msg.wParam);
  }
  五、总结
  利用我们再学校学习的C/C++对付平时的一些应用时足够的,只要我们打开思路,我们就能做出一些“高手”才能做的东西,这也是我们成长成为高手必经之路。有什么问题,欢迎大家及时与我讨论。
广告合作:400-664-0084 全国热线:400-664-0084
Copyright 2010 - 2017 www.my8848.com 珠峰网 粤ICP备15066211号
珠峰网 版权所有 All Rights Reserved