Visual-based stand-alone game plug-in

Preface

Hello! This is my first time using the welcome page displayed by Markdown editor. Next, we will use Microsoft Visual C++ 6.0 to write a plug-in for the classic game "Plants V.S. Zombies" to realize the function of changing the underlying data of the game. The function implementation is simple, but the benefits brought later are huge. I hope viewers will understand the subtleties and be informal. Yu Shu. This chapter covers the following:

  1. Regarding the use of **spy++** that comes with visual tools.
  2. About obtaining Windows error codes and querying their causes.
  3. For the acquisition method and calculation process of base address and offset.

Knowledge points

This project uses several knowledge points. In order to facilitate future inquiry and use, I have listed the knowledge points. The following is an introduction to the knowledge points used in this project.

About the use of spy++

spy++, as a tool that comes with visual studio, can easily obtain the handle, title and class name of the selected window.

Meaning: In this project, cooperate with the method in windows.h to obtain the window handle, so that the program can lock the window and prepare for the next operation.

Instructions:

  1. Click tools——>spy++ to enter the tool window
    Insert image description here
  2. Click on the telescope and drag the finder tool to the specified window
    Insert image description here
    So we get the window handle, title, and class name. Prepare for the next program writing.

About getting and querying windows errors

An error may be encountered while the program is running. At this time, we can use the GetLastError() method that comes with Windows to obtain the error code, and use the Error lookup in tools to find the cause.

For example:

printf("获取一级偏移地址失败,错误代码:%d\n",GetLastError());

Insert image description here
Insert image description here
This Error lookup can only find the cause of the problem, but does not provide a solution.

How to obtain the base address and calculate the steps

Taking "Plants vs. Zombies" as an example, data storage often requires several offsets from the base address to obtain the final address. So how to get the base address of a certain data? A mature programmer must know how to borrow an existing tool-Cheat Engine.

  1. Open and run Cheat Engine, search and obtain the address of "Sunshine" (for specific methods, please refer to Baidu, I will not go into details here). The address at this time is the address after multiple offsets. We call it the final address here. I found it. The address is 233A9848 (the address is hexadecimal).
  2. To obtain the first-level offset and address, and to obtain the second-level offset and address, please refer directly to the address below. (too many and too much trouble)
  3. Add a note: the content of the base address is a static address, static address + first-level offset = first-level offset address; first-level offset address + second-level offset = second-level offset address (this is the first Start getting the final address). But when using CE to search, we search in reverse. We first find the final address, then the second-level offset address, then the first level, and then the initial address. The initial address exists at the green base address.

Note: Different versions of the same game may have different base addresses and offsets. It is recommended to refer to the link below to obtain your own data.

Reference from: https://www.cnblogs.com/gd-luojialin/p/7789569.html
Recommended videos:http://www.iqiyi.com/w_19rt636lht.html?fromvsogou=1

Sample code

#include<stdio.h>
#include<Windows.h>
#include<String.h>

int main()
{
    
    
	
	//1.运行游戏,通过spy++获取窗口信息
	HWND hGameWnd = FindWindow("MainWindow","Plants vs. Zombies 1.2.0.1073 RELEASE");
	if(hGameWnd == NULL){
    
    
		printf("没有运行游戏");
		getchar(); 
		return 0;
	}
	//2.根据窗口句柄获取进程PID,Process ID
	DWORD dwPID = 0;
	GetWindowThreadProcessId(hGameWnd,&dwPID);
	if(dwPID == 0){
    
    
		printf("获取进程PID失败,错误代码:%d\n",GetLastError());
		return 0;
	}

	//3.根据PID获取进程句柄
	HANDLE hProcess =  OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwPID);
	if (hProcess == NULL){
    
    
		printf("打开进程失败,错误代码:%d\n",GetLastError());
		return 0;
	}
	//4.从指定的进程内存区域去读取数据
	DWORD dwSunshineBaseAddress = 0x7578F8;
	DWORD dwSunshineAddressValue = 0;
	DWORD dwSize = 0;
	if(FALSE == ReadProcessMemory(
		hProcess,                      //哪一个进程
		(LPVOID)dwSunshineBaseAddress, //要读取的进程(基地址)
		&dwSunshineAddressValue,       //接收进程数据
		sizeof(DWORD),                 //要修改的字节数
		&dwSize                        //实际修改的字节数
		)){
    
    
		printf("获取静态地址失败,错误代码:%d\n",GetLastError());
			return 0;
	}
	else printf("静态地址为:%x\n",dwSunshineAddressValue);//静态地址(16进制)
	//5.获取一级偏移地址
	DWORD dwSunshineOffsetFirst = 0x868;//一级偏移量
    DWORD dwSunshineOffsetValue = 0;                  //一级偏移地址的容器
	if(FALSE == ReadProcessMemory(
		hProcess,             
		(LPVOID)(dwSunshineOffsetFirst+dwSunshineAddressValue),//一级偏移地址的计算
		&dwSunshineOffsetValue,//一级偏移地址的赋值
		sizeof(DWORD),
		&dwSize
		)){
    
    
		printf("获取一级偏移地址失败,错误代码:%d\n",GetLastError());
			return 0;
	}
	else printf("一级偏移地址:%x\n",dwSunshineOffsetValue);//一级偏移地址(16进制)
	//6.获取二级偏移地址
	DWORD dwSunshineOffsetSecond = 0x5578;           //二级偏移量
    DWORD dwSunshine = 0;                            //二级级偏移地址(最终地址)的容器
	if(FALSE == ReadProcessMemory(
		hProcess,              
		(LPVOID)(dwSunshineOffsetSecond+dwSunshineOffsetValue),//二级偏移地址的计算
		&dwSunshine,
		sizeof(DWORD),
		&dwSize
		)){
    
    
		printf("获取二级偏移地址失败,错误代码:%d\n",GetLastError());
			return 0;
	}
	else printf("二级偏移地址:%x\n",dwSunshine);//二级偏移地址(16进制)
	printf("阳光值为%d",dwSunshine);

	int NowSunshine=0;        //想得到的阳光值
	printf("请输入想要修改的阳光值:");
	scanf("%d",&NowSunshine);
	//修改阳光值
	WriteProcessMemory(
		hProcess,             
		(LPVOID)(dwSunshineOffsetSecond+dwSunshineOffsetValue),
		&NowSunshine,
		sizeof(DWORD),
		&dwSize
		);



	return 0;
}

renderings

Insert image description here
Insert image description here

Summarize

In "Plants V.S. Zombies", you can modify the number of gold coins and the number of sunshine by modifying the base address and two offsets. You can also modify other basic data of this game and the data of other stand-alone games. This method is suitable for use in places with strong uniformity such as companies or schools. Compared with opening CE to modify data every time, this method is more convenient and simple to operate and more convenient to disseminate. Everyone who has played it says it’s good

Guess you like

Origin blog.csdn.net/Norton_Paige/article/details/108284994