上分宝:值得大家信赖的下载网站!
时间: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++零基础教程。欢迎各位感兴趣的的小伙伴。
学习思路:
学习资料:
上海市初中学生综合素质评价登录入口
宝可梦属性克制表2024最新,18种属性克制关系
王者荣耀排位巅峰赛荣耀战力加分公式规则2024
魔塔50层攻略隐藏道具图解,魔塔50层详细图文攻略
美国zoom动物仙踪林详情介绍
重装机兵攻略隐藏物品图文详解,战车具体位置
推荐几款超污的手游游戏,6个很污的养成类游戏
希尔薇攻略
原神主c排行2023,4.2目前各系最强主c角色排名
action对魔忍
动作游戏
2233盒子
其他游戏
oppo助手2.0
其他游戏
touchitrikka
益智休闲
qq飞车测试服
赛车竞速
青云纪事
角色扮演
泰拉tmodloader
其他游戏
菜菜音乐盒
其他游戏
迷你世界老版本0.44.2版本
模拟经营
极乐园
聊天交友
湖北农村商业银行
金融理财
51品茶
交友约会
极乐园paradise
聊天交友
丝目
社交聊天
七点工具箱
工具应用
酷狗输入法(搜狗输入法)
常用工具
shopee东南亚跨境电商
境外购物
日本大阪usj
生活实用