植物大战僵尸外挂原理和代码编写(附源码会指针即可)

-1.植物大战僵尸讲解

植物大战僵尸修改器制作–从入门到入土-软件逆向-看雪-安全社区|安全招聘|kanxue.com

植物大战僵尸逆向解析
今天主要的目的就是讲解一下外挂的基本实现原理

  1. 实现阳光值无限
  2. 修改游戏逻辑
  3. 用c++编写游戏外挂

1.程序的前置知识:

  1. 程序的基本概念
    其实所有的exe,本质来说都是一个文本文件
    无论是浏览器还是QQ,微信等等,电脑和手机同理
    本质来说都是一个文本文件
    类比来说就是一个写满数据的txt文本!

  2. Cheat Engine一款exe程序文本读取器
    既然程序是一个文本,那我们就需要一个文本读取器来帮我们阅读这个文本,因为exe是不断在运行代码的,所有也可以说它是一个动态文本
    而Cheat Engine就可以帮我们读取!

Cheat Engine及可以是笔也是眼睛!

2.实战寻找阳光变量的所在位置

通过Cheat Engine找到阳光变量的位置,并且尝试对他进行修改!
成功修改!
将该变量存储下来,并且重新开始一个游戏
发现这个阳光值不可以修改了,需要再次寻找阳光的地址!
这个问题留到最后编写外挂的时候讲解!

请添加图片描述

3.汇编的前置知识

这里我们又要补充一个概念:程序的本质的本质是什么?
之前我们说"其实所有的exe,本质来说都是一个文本文件"
那”文本文件txt“的本质又是什么呢???
其实”文本文件txt,电脑里的图片,exe“的本质都是0和1,组成的数据矩阵
本质来说就是0和1
知道了什么是代码什么是汇编

在学习汇编前我们需要知道什么是汇编!!!
机器码-》汇编语言-》高级语言

三条基本的汇编指令:
add A,B
sub A,B
mov A, B

4.实战修该游戏代码逻辑

  1. 修该种植阳光的代码
  2. 修改收集阳光的代码

5.实战编写植物大战僵尸外挂

请添加图片描述

6A9EC0 0x768 0x5560
请添加图片描述

0.单局修改阳光数值

使用cheatengine打开植物大战僵尸
请添加图片描述
阳光初始值为50,进行第一次搜索,左边的结果有577个!
请添加图片描述
改变阳光的值继续搜索!
将阳光的值消耗掉,阳光值变为0
再次搜索查看之前的搜索结果是否有值被改变成0,发现有两个!继续
请添加图片描述
再次收集阳光,数量变成25,再次搜索结果
发现只有一个变量存在!!可以确定这就是目标!
请添加图片描述
尝试修改阳光的值为999!
手动修改成功!
请添加图片描述
虽然这里的阳光地址可以修改阳光值,但如果这局游戏结束,再次使用这个地址修改阳光就会失效!
这是由于该地址不是基址会随程序的变化而变化,所以当重启游戏的时候,该地址就会失效需要寻找新的解决方案!

1.全局修改阳光数值

根据[[0.单局修改阳光数值]]获取到的变量地址进行分析,用来推导出阳光变量的基址
选中变量右击查看是什么地方访问了这个地址!
请添加图片描述

点击完"找出是什么访问了这个地址"后,就会弹出相应的汇编指令,与计数
其中计数会不断变化,按下esc可以暂停计数!
发现共有两条汇编指令在访问阳光的数值!
请添加图片描述

是一个地址加上偏移的值存储了阳光的值:

0041BAB5 - 03 82 60550000  - add eax,[edx+00005560]
00489825 - 8B 86 60550000  - mov eax,[esi+00005560]

可以得出此时edx或eax的值+0x00005560位置存储的就是阳光的值!

可以获取到edx或eax的值来继续追寻阳光变量的基址!
请添加图片描述

右击指令查看详细信息,可以找到eax的值0x1076DE98

这个可能与阳光的基址有关,将该值继续使用0x1076DE98搜索

请添加图片描述

搜索结果有52个,但其中并没有基址所以阳光的基地址可能是二级偏移继续寻找

这个可能与阳光的基址有关,将该值继续使用0x1076DE98搜索
请添加图片描述
搜索结果有52个,但其中并没有基址所以阳光的基地址可能是二级偏移继续寻找

怀疑这些地址是关键,由于阳光是会被不断访问数值的所以监测一下这些数值被谁访问过!
请添加图片描述
都一一看过后
请添加图片描述
发现这个地址最可疑0257B0D8,他这里的0x768,记录一下EDI=0257A970请添加图片描述

去内存里搜索看0257A970是不是存储在固定基址里的!’
果然成功找到固定的基址:
请添加图片描述

编写外挂的代码:


#include <iostream>
#include <windows.h>
#include <thread>
#include "conio.h"
#define Ver Ver2.0
using namespace std;
DWORD DPid{ 0 };

//菜单函数 每次输入完指令都会调用它 重新打印下菜单
void menu() {
    cout << "***********************" << endl;
    cout << "**** 1、修改阳光值 ****" << endl;
    cout << "**** 2、锁定阳光值 ****" << endl;
    cout << "**** 0、退出本程序 ****" << endl;
    cout << "***********************" << endl;
    cout << "请输入相关指令:" << endl;
}

//修改阳光值
void yG(DWORD pid) {
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DPid);
    if (hProcess == NULL)
    {
        printf("你当前尚未进入关卡!请进入游戏关卡:自动获取阳光");
    }
    DWORD YGJZ{ 0x6A9EC0 }; //静态基址
    DWORD YGJZValue{ 0 };
    DWORD nSize{ 0 };
    BOOL ok = ReadProcessMemory(hProcess, (LPVOID)YGJZ, &YGJZValue, sizeof(DWORD), &nSize);
    DWORD YGjz2{ 0x768 }; //一级偏移
    DWORD YGjz2Value{ 0 };
    BOOL ok2 = ReadProcessMemory(hProcess, (LPVOID)(YGJZValue + YGjz2), &YGjz2Value, sizeof(DWORD), &nSize);
    DWORD YGJZ3{ 0x5560 }; //二级偏移
    DWORD YGJZ3Value{ 0 };
    BOOL OK3 = ReadProcessMemory(hProcess, (LPVOID)(YGjz2Value + YGJZ3), &YGJZ3Value, sizeof(DWORD), &nSize);
    cout << "当前阳光值:[ " << YGJZ3Value << " ] \n请输入要修改的阳光值:\n";  //最终及地址
    int edit;
    cin >> edit;
    BOOL wri = WriteProcessMemory(hProcess, (LPVOID)(YGjz2Value + YGJZ3), &edit, sizeof(edit), &nSize);
    if (wri == true)
    {
        cout << "写入成功!" << endl;
    }
}
//锁定阳光值
void setsun(DWORD pid) {
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DPid);
    if (hProcess == NULL)
    {
        printf("你当前尚未进入关卡!请进入游戏关卡:自动获取阳光");
    }
    DWORD YGJZ{ 0x6A9EC0 }; //静态基址
    DWORD YGJZValue{ 0 };
    DWORD nSize{ 0 };
    BOOL ok = ReadProcessMemory(hProcess, (LPVOID)YGJZ, &YGJZValue, sizeof(DWORD), &nSize);
    DWORD YGjz2{ 0x768 }; //一级偏移
    DWORD YGjz2Value{ 0 };
    BOOL ok2 = ReadProcessMemory(hProcess, (LPVOID)(YGJZValue + YGjz2), &YGjz2Value, sizeof(DWORD), &nSize);
    DWORD YGJZ3{ 0x5560 }; //二级偏移
    DWORD YGJZ3Value{ 0 };
    BOOL OK3 = ReadProcessMemory(hProcess, (LPVOID)(YGjz2Value + YGJZ3), &YGJZ3Value, sizeof(DWORD), &nSize);
    cout << "当前阳光值:[ " << YGJZ3Value << " ] \n请输入要你要锁定的阳光值:\n";  //最终及地址
    int edit;
    cin >> edit;
    while (true)
    {
        if (_kbhit()) // 如果有按键被按下
        {
            if (_getch() == 'q') //如果按下了q键则跳出循环
            {
                break;
            }

        }
        Sleep(500);
        BOOL wri = WriteProcessMemory(hProcess, (LPVOID)(YGjz2Value + YGJZ3), &edit, sizeof(edit), &nSize);
    }
    
}


int main()
{
    system("mode con cols=32 lines=18  ");//设置控制台大小

    system("color a");                      //设置控制台字体颜色
    SetConsoleTitle(L"ZomKill Ver2.0");   //设置控制台标题
    int z;

    HWND hGame = FindWindow(L"MainWindow", L"植物大战僵尸中文版");
    int select;
    while (true)
    {
        if (hGame == NULL)
        {
            cout << "游戏未运行,请打开游戏再运行本辅助\n" << endl;
            return 0;
        }
        else
        {
            GetWindowThreadProcessId(hGame, &DPid); //拿出进程ID
            cout << "+++++++++++++++++++++++++++++\n当前游戏进程ID:" << DPid << endl;
        }
        menu();
        cin >> select;
        switch (select)
        {
        case 1:
            yG(DPid);
            break;
        case 2:
            setsun(DPid);
            break;
        default:
            break;
        }
        system("pause");
        system("cls");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值