上分宝:值得大家信赖的下载网站!

所在位置:首页 > 攻略资讯 > 如何快速获取植物大战僵尸无限阳光修改器(完整教程)

如何快速获取植物大战僵尸无限阳光修改器(完整教程)

时间:2023-05-18 10:31:30来源:互联网

  今天小编花点时间给大家讲讲植物大战僵尸外挂教程,希望大家给点意见。

  关于CE(Cheat Engine)的用法,以后有时间的话 会发表相关视频教程。

  根据查到指针永久基址+偏移地址 就可以获得/设置 阳光值。所以我们可以通过打开游戏进程,改写进程内相应的内存就可以实现游戏的修改。

  现在直接上源代码:

  #include

  #include

  #include

  int main(void)

  {

  char input;

  HWND hWnd; //窗口句柄

  DWORD pid; //进程句柄

  HANDLE hProcess = 0;

  //阳光的基地址和偏移

  DWORD ba_addr = 0x007794F8;//基地址

  DWORD m_offset1 = 0x868;//偏移1

  DWORD m_offset2 = 0x5578;//偏移2

  printf(" O.打开游戏进程 M.修改阳光 ");

  printf(" Q.退出外挂 ");

  printf("------------------------------------------ ");

  while (1)

  {

  input = getchar();

  if (input == 'O' || input == 'o')

  {

  hWnd = FindWindow(NULL, _T("Plants vs. Zombies 1.2.0.1073 RELEASE") );

  if (hWnd != 0)

  {

  GetWindowThreadProcessId(hWnd, &pid);

  hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);//打开进程,取得句柄

  if (hProcess == 0)

  {

  printf("打开游戏进程失败 ");

  }

  else

  {

  printf("打开游戏进程成功!! ");

  }

  }

  else

  {

  printf("游戏没有运行,或者没有使用管理员身份运行本外挂. ");

  }

  }if (input == 'M' || input == 'm')

  {

  if (hProcess == 0)

  {

  printf("请先打开游戏进程");

  }

  else

  {

  DWORD m_tempadd;

  DWORD YG;

  //读取基址里面的数据(是一个指针)

  ReadProcessMemory(hProcess, (LPVOID)ba_addr, &m_tempadd, 4, 0);

  //基址加偏移地址1的数据(是一个指针)

  ReadProcessMemory(hProcess, (LPVOID)(m_tempadd + m_offset1), &m_tempadd, 4, 0);

  /**********************

  *这里相当于一个二级指针(加偏移地址)

  *ReadProcessMemory函数 读取相应进程的指定位置 指定大小的数据到缓冲区

  *基址加偏移地址 为二级指针

  *基址加偏移地址取内容 再加 偏移地址为一级指针 (这个指针就是指向了阳光值的内存单元)

  ******************/

  //要修改的内存地址是(tempadd+offset4)

  DWORD res = WriteProcessMemory(hProcess, (LPVOID)(m_tempadd+m_offset2), &YG, 4, 0);

  if (res == 0)

  {

  printf("修改失败");

  }

  else

  {

  printf("修改成功");

  }

  }

  }

  if (input == 'Q' || input == 'q')

  {

  break;

  }

  }

  return 0;

  }

  GUI版本修改器

  WG.h

  #pragma once

  #include

  #include

  #include

  extern HWND hWnd; //窗口句柄

  extern DWORD pid; //进程句柄

  extern HANDLE hProcess;

  //阳光的基地址和偏移

  extern DWORD ba_addr;//基地址

  extern DWORD m_offset1;//偏移1

  extern DWORD m_offset2;//偏移2

  extern int openGameJc();//打开游戏进程

  extern int UpdateYG(int value);//修改阳光

  WG.c

  #include"WG.h"

  HWND hWnd; //窗口句柄

  DWORD pid; //进程句柄

  HANDLE hProcess = 0;

  //阳光的基地址和偏移

  DWORD ba_addr = 0x007794F8;//基地址

  DWORD m_offset1 = 0x868;//偏移1

  DWORD m_offset2 = 0x5578;//偏移2

  int UpdateYG(int value)

  {

  if (hProcess == 0)

  {

  return 0;

  }

  else

  {

  DWORD m_tempadd;

  DWORD YG;

  YG = (unsigned long)value;

  //读取基址里面的数据(是一个指针)

  ReadProcessMemory(hProcess, (LPVOID)ba_addr, &m_tempadd, 4, 0);

  //基址加偏移地址1的数据(是一个指针)

  ReadProcessMemory(hProcess, (LPVOID)(m_tempadd + m_offset1), &m_tempadd, 4, 0);

  /**********************

  *这里相当于一个二级指针(加偏移地址)

  *ReadProcessMemory函数 读取相应进程的指定位置 指定大小的数据到缓冲区

  *基址加偏移地址 为二级指针

  *基址加偏移地址取内容 再加 偏移地址为一级指针 (这个指针就是指向了阳光值的内存单元)

  ******************/

  //要修改的内存地址是(tempadd+offset4)

  DWORD res = WriteProcessMemory(hProcess, (LPVOID)(m_tempadd + m_offset2), &YG, 4, 0);

  if (res == 0)

  {

  return 0;

  }

  else

  {

  return 1;

  }

  }

  }

  int openGameJc()

  {

  hWnd = FindWindow(NULL, _T("Plants vs. Zombies 1.2.0.1073 RELEASE"));

  if (hWnd != 0)

  {

  GetWindowThreadProcessId(hWnd, &pid);

  hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);//打开进程,取得句柄

  if (hProcess == 0)

  {

  return 0;

  }

  else

  {

  return 1;

  }

  }

  else

  {

  return 0;

  }

  }

  main.c

  #include

  #include"WG.h"

  #include

  HINSTANCE appInstance;

  LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

  int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, PSTR szCmdLine, int iCmdShow)

  {

  //

  appInstance = hInstance;

  //

  static TCHAR szAppName[] = TEXT("MyWindows");

  HWND hwnd;

  MSG msg;

  WNDCLASS wndclass;

  wndclass.style = CS_HREDRAW | CS_VREDRAW;

  wndclass.lpfnWndProc = WndProc;

  wndclass.cbClsExtra = 0; //额外空间

  wndclass.cbWndExtra = 0; //额外空间

  wndclass.hInstance = hInstance; //实例句柄

  wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标

  wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);//光标

  wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//白色

  wndclass.lpszMenuName = NULL;//菜单

  wndclass.lpszClassName = szAppName;//窗口类名

  //注册窗口类

  if (!RegisterClass(&wndclass))

  {

  MessageBox(NULL, TEXT("这个程序需要在 Windows NT 才能执行"), szAppName, MB_OK);

  return 0;

  };

  //创建窗口 设置窗口属性

  hwnd = CreateWindow(szAppName, //窗口类名称

  TEXT("植物大战僵尸外挂v1.0"), //窗口标题

  WS_OVERLAPPEDWINDOW, //窗口风格

  200, //CW 创建窗口选项 初始 x坐标

  200, //初始y坐标

  300, //初始 x方向尺寸

  300, //初始y方向尺寸

  NULL, //父窗口句柄

  NULL, //窗口菜单句柄

  hInstance, //程序实例句柄

  NULL //创建参数

  );

  //CreateWindow后 会产生几个 非队列消息 直接调用过程函数(重点)

  ShowWindow(hwnd, iCmdShow);

  UpdateWindow(hwnd);//(重点) UpdateWindow会 直接发送一个非队列的 WM_PAINT消息 让窗口绘制

  //因为 WM_PAINT默认是在 队列最后的 但是这里在最后的话 就不好,一个窗口创建 后 ShowWindow后就应该立即显示上面的文字

  //所以调用UpdateWIndow 让它立即绘制

  /******************

  *消息循环,操作系统 会把所有 消息 分配给 每个应用程序

  * 所以每个应用程序都有一个消息队列,GetMessage就是向当前程序的 消息队列内获取消息

  *lpMsg第一个参数 用于存放当前获取的消息

  *hWnd需要获取消息的 窗口句柄,为NULL时 获取当前程序所有窗口的消息(必须属于当前线程)

  *wMsgFilterMin 指定获取消息值的最小整数(消息其实就是整数)

  *wMsgFilterMax 指定获取小的最大值

  *********************/

  while (GetMessage(&msg, NULL, 0, 0))

  {

  TranslateMessage(&msg);//函数将虚拟键消息 转换为字符消息,

  DispatchMessage(&msg);//函数分派一个消息给窗口过程函数,实际上是给操作系统操作系统调用的

  }

  return msg.wParam;

  /***************

  *1、在WinMain主函数中,最后的返回值是msg.wParam,这个参数是传递给void PostQuitMessage(int nExitCode); 这个函数的参数nExitCode的。

  * 2、nExitCode:指定应用程序退出代码。此值被用作消息WM_QUIT的wParam参数。

  *3、总之,当接收到一个WM_QUIT消息时,程序就中止。这时,WinMain函数应退出应用程序,并且返回传递给WM_QUIT消息的wParam参数的值。如果由于调用PostQuitMessage函数而接收到WM_QUIT消息,此时WM_QUIT消息的wParam的值即是PostQuiMessage函数的nExitCode的值。nExitCode一般为0。

  ***************/

  }

  LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

  {

  HWND hButton;

  HWND hEdit;

  HDC hdc; //Handle Device Context

  HWND hbtnUpdate;//修改阳光

  PAINTSTRUCT ps;

  RECT rect;

  LPTSTR result[128]; //结果

  switch (uMsg)

  {

  case WM_PAINT:

  hdc = BeginPaint(hWnd, &ps);

  GetClientRect(hWnd, &rect);

  DrawText(hdc, TEXT("叫我涵涵"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

  EndPaint(hWnd, &ps);

  break;

  case WM_CREATE:

  hEdit = (HWND)CreateWindow(TEXT("edit"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT ,

  120, 0,150, 20, hWnd, (HMENU)111, appInstance, NULL);

  hButton = (HWND)CreateWindow(TEXT("Button"), //Button是预定义 窗体类

  TEXT("打开游戏进程"),

  WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,

  10, 10, 100, 50,

  hWnd,

  (HMENU)110, //(重点)这里设置按钮id,但是 原本是设置菜单的 所以需要HMENU

  appInstance,

  NULL);

  //修改阳光

  hbtnUpdate = (HWND)CreateWindow(TEXT("Button"), //Button是预定义 窗体类

  TEXT("修改阳光"),

  WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,

  120, 40, 150, 40,

  hWnd,

  (HMENU)112, //(重点)这里设置按钮id,但是 原本是设置菜单的 所以需要HMENU

  appInstance,

  NULL);

  break;

  /*******************

  * 当用户点击菜单、按钮、下拉列表框等控件时候,

  *会触发WM_COMMAND.LOWORD(wParam) 是控件或菜单或加速键的ID

  *如果LOWORD(wParam) 是控件ID,HIWORD(wParam)是notification code,

  *比如BN_CLICKED, BN_DBLCLK等,标志用户对控件的操作,双击,单击

  *lparam 是子窗体句柄

  *********************/

  case WM_COMMAND:

  //按钮

  if (LOWORD(wParam) == 112 && HIWORD(wParam) == BN_CLICKED)

  {

  //根据父窗口句柄 以及 控件id, 获取 空间句柄,然后用GetWindowText获取 控件内的文本

  GetWindowText(GetDlgItem(hWnd, 111), result, 128);

  if (UpdateYG(_ttoi(result)) == 1)

  {

  MessageBox(hWnd, TEXT("修改成功"), TEXT("涵涵提示"), MB_OK);

  }

  else {

  MessageBox(hWnd, TEXT("修改失败"), TEXT("涵涵提示"), MB_OK);

  }

  }

  if (LOWORD(wParam) == 110 && HIWORD(wParam) == BN_CLICKED)

  {

  if(openGameJc()==1){

  MessageBox(hWnd, TEXT("开启游戏进程成功"), TEXT("提示"), MB_OK);

  }

  else {

  MessageBox(hWnd, TEXT("开启游戏进失败"), TEXT("提示"), MB_OK);

  }

  }

  break;

  case WM_DESTROY:

  PostQuitMessage(0);

  break;

  /********成功退出 ****

  ****************

  *用户通过点击关闭程序按钮后,消息队列增加一条消息WM_CLOSE,

  *然后程序从消息队列中取走WM_CLOSE,调用DestroyWindow(),

  *消息队列增加WM_DESTROY,应用程序再次取走,并调用PostQuitMessage(),

  *最终得到WM_QUIT而使消息循环退出,程序退出。

  ************/

  default:

  //我们不想关心的都用 默认处理方式

  return DefWindowProc(hWnd, uMsg, wParam, lParam);

  break;

  }

  return 0;

  }

  获取方式:

  1.在你手机的右上角有【关注】选项,或点击我的头像,点击关注!(关注我)

  2.关注后,手机客户端点击我的主页面,右上角有私信,请私信发我:编程

  电脑已经设置好了关键词自动回复,自动领取就好了!这几天上万个消息,真的回复不过来,所以回复的时候请注意关键词!

  其实做为一个开发者,有一个学习的氛围跟一个交流圈子特别重要这里请私信我“编程”不管你是小白还是大牛欢迎入住大家一起交流成长。小编会在里面不定期分享干货源码,包括我精心整理的一份c++零基础教程。欢迎各位感兴趣的的小伙伴。

  学习思路:

  学习资料:

  • 热门资讯
  • 最新资讯
  • 手游排行榜
  • 手游新品榜
  • 软件排行榜
  • 软件新品榜