赞
踩
最近出来的PVZ杂交版又掀起一波热潮,在各大短视频平台也有一席之地,借助工具Cheat Engine,写了个简单的植物大战僵尸杂交版破解程序,话不多说,我们来看如何实现的。
工具:Cheat Engine、visual studio (MFC支持)、植物大战僵尸杂交版
通过CE寻找基地址的工作可以参考其他人的博客:
通过CE寻找游戏基址1
通过CE寻找游戏基址2
这里直接给出对应内容:【基址+偏移】
阳光值:0x006A9EC0 + 0x00000768 + 0x00005560
银币值:0x006A9EC0 + 0x0000082C + 0x00000208
金币值:0x006A9EC0 + 0x0000082C + 0x0000020C
钻石值:0x006A9EC0 + 0x0000082C + 0x00000210
冷却值:0x006A9EC0 + 0x00000768 + 0x00000144 +{
0x00000070, 0x000000C0, 0x00000110, 0x00000160,
0x000001B0, 0x00000200, 0x00000250, 0x000002A0,
0x000002F0, 0x00000340, 0x00000390, 0x000003E0,
0x00000430, 0x00000480, 0x000004D0, 0x00000520
对应卡牌栏目第几章卡牌,索引就是几,实际上卡牌不会超过14张,只要给出14个就行了,找到前几个偏移量之后可以按照规律往后推测。
}
使用MFC应用程序,选择基于对话框选项
1、依此双击按钮、单选框,studio会自动建立信号与函数的映射。
2、Dlg.h中添加成员变量:
public:
UINT sunvalue; //阳光
UINT money_a; //银币
UINT money_b; //金币
UINT money_c; //钻石
int check1; //锁定阳光 check 的状态
int check2; //无冷却 check 的状态
3、Dlg.cpp中进行内容绑定:
void CPVZCrackerDlg::DoDataExchange(CDataExchange* pDX){
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT1, sunvalue); //将edit1的内容与sunvalue绑定,以下同理
DDX_Text(pDX, IDC_EDIT2, money_a);
DDX_Text(pDX, IDC_EDIT3, money_b);
DDX_Text(pDX, IDC_EDIT4, money_c);
DDX_Check(pDX, CHECK1, check1);
DDX_Check(pDX, CHECK2, check2);
}
4、如何让check选择时,实现阳光锁定和刷新冷却呢?
可以在check勾选时,开启定时器,每隔0.5s进行模拟点击刷新事件来达到效果
因此需要引入定时器模块,给出相关博客(主要参考2)
MFC中如何使用定时器:1
MFC中如何使用定时器:2
创建出void XXXXXDlg::OnTimer(UINT_PTR nIDEvent)。
当勾选状态时,打开计时器,未勾选状态时,关闭计时器即可
5、经过上面的操作后,Dlg.h内容大致如下:
// PVZCrackerDlg.h: 头文件 // #pragma once // CPVZCrackerDlg 对话框 class CPVZCrackerDlg : public CDialogEx { // 构造 public: CPVZCrackerDlg(CWnd* pParent = nullptr); // 标准构造函数 UINT sunvalue; //阳光 UINT money_a; //银币 UINT money_b; //金币 UINT money_c; //钻石 int check1; //锁定阳光 check 的状态 int check2; //无冷却 check 的状态 // 对话框数据 #ifdef AFX_DESIGN_TIME enum { IDD = IDD_PVZCRACKER_DIALOG }; #endif protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: HICON m_hIcon; // 生成的消息映射函数 virtual BOOL OnInitDialog(); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() public: afx_msg void OnBnClickedButton1(); afx_msg void OnBnClickedButton2(); afx_msg void OnBnClickedButton3(); afx_msg void OnBnClickedButton4(); afx_msg void OnBnClickedButton5(); afx_msg void OnBnClickedCheck1(); afx_msg void OnBnClickedCheck2(); afx_msg void OnTimer(UINT_PTR nIDEvent); int TIM_X ; afx_msg void OnClose(); };
void CPVZCrackerDlg::OnBnClickedButton1(){ // 修改阳光 UpdateData(TRUE); //先进行数据更新 HWND PVZ; //获取窗口句柄 PVZ = ::FindWindow(L"MAINWINDOW", L"植物大战僵尸杂交版v2.0");//这里需要对应游戏窗口名。 DWORD pid = 0; GetWindowThreadProcessId(PVZ, &pid); //获取进程id HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);//打开进程,获取所有权 SIZE_T ipread = 0; //下面要用的参数,实际上往往忽略,但不写又不行 DWORD base = 0x006A9EC0; //数据基地址偏移量等由CE给出。 DWORD offset1 = 0x00000768; DWORD offset2 = 0x00005560; //[A]->B 表示将A地址里的值拿到B中,不加[]代表立即数下文同理,如有错误欢迎指正 //[base]->sunbase DWORD sunbase = 0; ReadProcessMemory(handle, LPCVOID(base), &sunbase, sizeof(DWORD), &ipread); //[sunbase+offset1]->sunoffset1 DWORD sunoffset1 = 0; ReadProcessMemory(handle, LPCVOID(sunbase + offset1), &sunoffset1, sizeof(DWORD), &ipread); //sunvalue -> [sunoffset1+offset2] DWORD svalue = sunvalue; WriteProcessMemory(handle, LPVOID(sunoffset1 + offset2), &svalue, sizeof(DWORD), &ipread); }
void CPVZCrackerDlg::OnBnClickedButton2(){ // TODO: 在此添加控件通知处理程序代码 // 修改银币 UpdateData(TRUE); HWND PVZ; PVZ = ::FindWindow(L"MAINWINDOW", L"植物大战僵尸杂交版v2.0"); DWORD pid = 0; GetWindowThreadProcessId(PVZ, &pid); HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); SIZE_T ipread = 0; //下面要用的参数 DWORD base = 0x006A9EC0; //数据基地址偏移量等由CE给出。 DWORD offset1 = 0x0000082C; DWORD offset2 = 0x00000208; //[base]->moneybase DWORD moneybase = 0; ReadProcessMemory(handle, LPCVOID(base), &moneybase, sizeof(DWORD), &ipread); //[moneybase+offset1]->moneyoffset1 DWORD moneyoffset1 = 0; ReadProcessMemory(handle, LPCVOID(moneybase + offset1), &moneyoffset1, sizeof(DWORD), &ipread); //money_a -> [moneyoffset1+offset2] DWORD svalue = money_a; WriteProcessMemory(handle, LPVOID(moneyoffset1 + offset2), &svalue, sizeof(DWORD), &ipread); }
void CPVZCrackerDlg::OnBnClickedButton3(){ // TODO: 在此添加控件通知处理程序代码 // 修改金币 UpdateData(TRUE); HWND PVZ; PVZ = ::FindWindow(L"MAINWINDOW", L"植物大战僵尸杂交版v2.0"); DWORD pid = 0; GetWindowThreadProcessId(PVZ, &pid); HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); SIZE_T ipread = 0; //下面要用的参数 DWORD base = 0x006A9EC0; //数据基地址偏移量等由CE给出。 DWORD offset1 = 0x0000082C; DWORD offset2 = 0x0000020C; //[base]->moneybase DWORD moneybase = 0; ReadProcessMemory(handle, LPCVOID(base), &moneybase, sizeof(DWORD), &ipread); //[moneybase+offset1]->moneyoffset1 DWORD moneyoffset1 = 0; ReadProcessMemory(handle, LPCVOID(moneybase + offset1), &moneyoffset1, sizeof(DWORD), &ipread); //money_b -> [moneyoffset1+offset2] DWORD svalue = money_b; WriteProcessMemory(handle, LPVOID(moneyoffset1 + offset2), &svalue, sizeof(DWORD), &ipread); }
void CPVZCrackerDlg::OnBnClickedButton4(){ // TODO: 在此添加控件通知处理程序代码 // 修改钻石 UpdateData(TRUE); HWND PVZ; PVZ = ::FindWindow(L"MAINWINDOW", L"植物大战僵尸杂交版v2.0"); DWORD pid = 0; GetWindowThreadProcessId(PVZ, &pid); HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); SIZE_T ipread = 0; //下面要用的参数 DWORD base = 0x006A9EC0; //数据基地址偏移量等由CE给出。 DWORD offset1 = 0x0000082C; DWORD offset2 = 0x00000210; //[base]->moneybase DWORD moneybase = 0; ReadProcessMemory(handle, LPCVOID(base), &moneybase, sizeof(DWORD), &ipread); //[moneybase+offset1]->moneyoffset1 DWORD moneyoffset1 = 0; ReadProcessMemory(handle, LPCVOID(moneybase + offset1), &moneyoffset1, sizeof(DWORD), &ipread); //money_a -> [moneyoffset1+offset2] DWORD svalue = money_c; WriteProcessMemory(handle, LPVOID(moneyoffset1 + offset2), &svalue, sizeof(DWORD), &ipread); }
void CPVZCrackerDlg::OnBnClickedButton5(){ // 修改冷却 UpdateData(TRUE); HWND PVZ; PVZ = ::FindWindow(L"MAINWINDOW", L"植物大战僵尸杂交版v2.0"); DWORD pid = 0; GetWindowThreadProcessId(PVZ, &pid); HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); SIZE_T ipread = 0; //下面要用的参数 DWORD base = 0x006A9EC0; //数据基地址偏移量等由CE给出。 DWORD offset1 = 0x00000768; DWORD offset2 = 0x00000144; DWORD offset3[16] = { 0x00000070, 0x000000C0, 0x00000110, 0x00000160, 0x000001B0, 0x00000200, 0x00000250, 0x000002A0, 0x000002F0, 0x00000340, 0x00000390, 0x000003E0, 0x00000430, 0x00000480, 0x000004D0, 0x00000520 }; //[base]->freshbase DWORD freshbase = 0; ReadProcessMemory(handle, LPCVOID(base), &freshbase, sizeof(DWORD), &ipread); //[freshbase+offset1]->freshoffset1 DWORD freshoffset1 = 0; ReadProcessMemory(handle, LPCVOID(freshbase + offset1), &freshoffset1, sizeof(DWORD), &ipread); //[freshoffset1+offset2]->freshoffset2 DWORD freshoffset2 = 0; ReadProcessMemory(handle, LPVOID(freshoffset1 + offset2), &freshoffset2, sizeof(DWORD), &ipread); //1 ->[freshoffset2+offset3] DWORD freshvalue = 1; //1代表冷却完毕 其他代表正在冷却 for (int i = 0; i < 16; ++i) WriteProcessMemory(handle, LPVOID(freshoffset2 + offset3[i]), &freshvalue, sizeof(DWORD), &ipread); }
void CPVZCrackerDlg::OnBnClickedCheck1(){ // TODO: 在此添加控件通知处理程序代码 CButton* pBtn = (CButton*)GetDlgItem(CHECK1); int checked = pBtn->GetCheck(); //获取check状态 //实际上可以直接check1 switch (checked){ case 1: { SetTimer(1, 500, NULL); //设置500ms为周期的定时器,标签为1,并开启 break; } case 0: { KillTimer(1); //关闭标签为1的定时器 break; } default: break; } }
void CPVZCrackerDlg::OnBnClickedCheck2(){ // TODO: 在此添加控件通知处理程序代码 CButton* pBtn = (CButton*)GetDlgItem(CHECK2); int checked = pBtn->GetCheck(); switch (checked) { case 1: { SetTimer(2, 500, NULL); break; } case 0: { KillTimer(2); break; } default: break; } }
void CPVZCrackerDlg::OnTimer(UINT_PTR nIDEvent) { // TODO: 在此添加消息处理程序代码和/或调用默认值 switch (nIDEvent){ case 1: OnBnClickedButton1(); break; case 2: OnBnClickedButton5(); break; default: break; } CDialogEx::OnTimer(nIDEvent); } void CPVZCrackerDlg::OnClose() { // TODO: 在此添加消息处理程序代码和/或调用默认值 KillTimer(1); KillTimer(2); CDialogEx::OnClose(); }
// PVZCrackerDlg.cpp: 实现文件 #include "pch.h" #include "framework.h" #include "PVZCracker.h" #include "PVZCrackerDlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CPVZCrackerDlg 对话框 CPVZCrackerDlg::CPVZCrackerDlg(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_PVZCRACKER_DIALOG, pParent){ m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); check1 = 0; check2 = 0; sunvalue = 5000; money_a = 10000; money_b = 10000; money_c = 10000; TIM_X = 0; } void CPVZCrackerDlg::DoDataExchange(CDataExchange* pDX){ CDialogEx::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDIT1, sunvalue); //将edit1的内容与sunvalue绑定,以下同理 DDX_Text(pDX, IDC_EDIT2, money_a); DDX_Text(pDX, IDC_EDIT3, money_b); DDX_Text(pDX, IDC_EDIT4, money_c); DDX_Check(pDX, CHECK1, check1); DDX_Check(pDX, CHECK2, check2); } BEGIN_MESSAGE_MAP(CPVZCrackerDlg, CDialogEx) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BUTTON1, &CPVZCrackerDlg::OnBnClickedButton1) ON_BN_CLICKED(IDC_BUTTON2, &CPVZCrackerDlg::OnBnClickedButton2) ON_BN_CLICKED(IDC_BUTTON3, &CPVZCrackerDlg::OnBnClickedButton3) ON_BN_CLICKED(IDC_BUTTON4, &CPVZCrackerDlg::OnBnClickedButton4) ON_BN_CLICKED(IDC_BUTTON5, &CPVZCrackerDlg::OnBnClickedButton5) ON_BN_CLICKED(CHECK1, &CPVZCrackerDlg::OnBnClickedCheck1) ON_BN_CLICKED(CHECK2, &CPVZCrackerDlg::OnBnClickedCheck2) ON_WM_TIMER() ON_WM_CLOSE() END_MESSAGE_MAP() // CPVZCrackerDlg 消息处理程序 BOOL CPVZCrackerDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 this->SetWindowTextW(L"植物大战僵尸杂交版破解 by 和八哥的环球探险"); return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } // 如果向对话框添加最小化按钮,则需要下面的代码来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,这将由框架自动完成。 void CPVZCrackerDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // 使图标在工作区矩形中居中 int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // 绘制图标 dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); } } //当用户拖动最小化窗口时系统调用此函数取得光标 //显示。 HCURSOR CPVZCrackerDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。