详解C语言实现植物大战僵尸阳光9999

文章目录

    • 效果展示
    • 工具:
    • 要求(建议)
    • 一、CE部分:
    • 二、核心代码部分
    • 三、润色

效果展示

详解C语言实现植物大战僵尸阳光9999_第1张图片
详解C语言实现植物大战僵尸阳光9999_第2张图片

另外点击还会有"德玛西亚!"音效

工具:

核心代码:Devcpp足够;
对话框界面和资源文件的添加:CodeBlocks
资源编辑器:ResEdit
格式转换工具:格式工厂、Spy++
必备工具:CheatEngine

要求(建议)

1.打过CheatEngineTutorial第8关“多级指针”,
2.会修改静态地址下的数据

================================================================================================

一、CE部分:

打开CE,打开植物大战僵尸


精确数值搜索找到阳光地址(这都是基本操作,我就不说了),
详解C语言实现植物大战僵尸阳光9999_第3张图片
把阳光数值地址加到下方列表,并找出是什么修改了这个地址
详解C语言实现植物大战僵尸阳光9999_第4张图片

详解C语言实现植物大战僵尸阳光9999_第5张图片
记下第一个偏移量:0x5560
搜索框搜索EAX的数值,也就是CE提醒你的数值:0x176599C8。
详解C语言实现植物大战僵尸阳光9999_第6张图片
出来一大堆对吧,多点几次再次次扫描,把数值不停地变的地址排除掉。
详解C语言实现植物大战僵尸阳光9999_第7张图片
还剩下这么多地址,最初到这里我就头疼了,到底找哪个?后来看了一个比较有经验的人的说法,CE会把比较靠谱的几个数据地址给你放在最前面,而且一些前缀相同的、重复的地址大概率不是。
按照这位大佬的经验指导,我选择前4个地址,把他们全部加到下方列表,依次点找出是是谁访问了这个地址
详解C语言实现植物大战僵尸阳光9999_第8张图片

详解C语言实现植物大战僵尸阳光9999_第9张图片
这是可能1的情况,只有push、pop,没有我们期待的 [寄存器]之类的,而且阳光变化的时候,这里并没有变化,果断排除

为了让大家更透彻,我就把错误的一个一个排掉,其实可能2就是我们要找的一级指针。

来看可能3:
详解C语言实现植物大战僵尸阳光9999_第10张图片

可能3前两个数据一打开,计数就一直在变,很让人怀疑不是和阳光数据有关的。
而第三个数据,我原本发现每次点一个阳光有会加1,刚开始真是个大坑,浪费我好久世界。
后来我发现,其实你在游戏框里每点一次鼠标,不过点什么,第三个数据计数都会加一,所以我判断这只是一个检测鼠标事件的代码。
可能3排除!

来看可能4:
详解C语言实现植物大战僵尸阳光9999_第11张图片
这还用思考吗?阳光变动,这个地址一点反应都没有。
果断排除!
下来看可能2,也就是真正的指针。
详解C语言实现植物大战僵尸阳光9999_第12张图片

可能2的代码是真的多,这真让人讨厌,而且数据非常诡异,好多计数在游戏一启动就不停地上涨,而且下方不断有新的代码跳出来。
不过别慌,我们慢慢仔细地观察。
发现:
1.游戏启动的时候检测可能3,游戏会变得很卡。
------我猜测这可能是可能3这里有很多和游戏运作有关东西,比如冷却时间、僵尸产生什么什么的。
2.过一段时间后,可能3处的逐渐平稳了,不会再有新的代码跳出来了。
------这是我们希望看到的,代码越少越容易缩小范围
3.仔细观察数据,有几行数据会随着你的操作加1,
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210613192111620.png详解C语言实现植物大战僵尸阳光9999_第13张图片
这里分析一下,随着时间累积,上面那些计数不停变的数据,最后计数会远远大于其他地址,很可能和我们的阳光无关,当你捡起了二三十次阳光后,那些变化很小的个位数也可以排除了。
所以我们的目标就是那些和操作次数比较接近的代码,看看图中76这个数字,这个数字就是之前提到过的那种,每当在游戏界面点击一次鼠标,它就会加一,所以排除。

那么仔细观察下来,其实也没有其他数据了,图中只有25、16、16这三个代码了
我也没数自己到底点了多少次阳光,也许是快20次,也许是20多次,因为监测期间游戏太卡了,延迟很高,我不方便观察。
不过当我们点开这三行数据:
详解C语言实现植物大战僵尸阳光9999_第14张图片
其实都是一样的,所以这里就偷个懒不深究了,不过我猜测一下,可能一个是总的阳光,一个是天上掉落的或自己产出的阳光。
记录第二个偏移量:0x768

搜索框搜索这个EDX (ECX),
详解C语言实现植物大战僵尸阳光9999_第15张图片
终于看到了心动的绿色基址,这里已经无法判断哪一个是了,不过好在只有4个,全部加到下面框里,一个个的合成最终指针。(其实实践中发现四个基址都可以)

详解C语言实现植物大战僵尸阳光9999_第16张图片
然后点这个重新计算新的地址,得到基址,我这里是0X006AA00C
详解C语言实现植物大战僵尸阳光9999_第17张图片

详解C语言实现植物大战僵尸阳光9999_第18张图片

发现了什么?四个指针最后的基址一模一样,都是006AA00C
至于最后那个“以前找到的基址”,我是真的懵逼
这个是以前找到的基址0X0019FD2C,这次找的基址不一样,但是居然也拿来用,不同的基址写出来的程序都能运行,我是真的懵逼!

CE部分到此结束,这里需要的就是我们找到的那三个数据:
offset1=0x768
offset2=0x5560
base_addr=0x6AA00C

二、核心代码部分

#include 
#include 

int main(void)
{
	DWORD base=0x0019FD2C;
	//DWORD base=0x006AA00C;
	DWORD offset1=0x768,offset2=0x5560;
	DWORD temp_addr=0;
	HWND WindHandle;
	DWORD pid;
	HANDLE ProcessHandle;
	LPVOID toChangeAddr=NULL;
	int PrevValue;
	int toWriteValue=9999;
	WindHandle=FindWindow("MainWindow","植物大战僵尸汉化版");
	if(!WindHandle)
	{
		printf("游戏未启动!");
		exit(0);
	}
	GetWindowThreadProcessId(WindHandle,&pid);
	ProcessHandle=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
	
	ReadProcessMemory(ProcessHandle,(LPVOID)base,&temp_addr,sizeof(DWORD),NULL);
	//printf("%X\n",temp_addr);
	ReadProcessMemory(ProcessHandle,(LPVOID)(temp_addr+offset1),&temp_addr,sizeof(DWORD),NULL);
	//printf("%X\n",temp_addr);
	toChangeAddr=(LPVOID)(temp_addr+offset2);
	//printf("%X\n",toChangeAddr);
	
	//ReadProcessMemory(ProcessHandle,toChangeAddr,&PrevValue,sizeof(DWORD),0);
	//printf("%d",PrevValue);
	WriteProcessMemory(ProcessHandle,toChangeAddr,&toWriteValue,sizeof(DWORD),NULL);
	system("pause");
	
}

WinAPI都是看名字就懂什么意思了,MSDN一查、参数一填就好了。
FinwWindow里的两个参数,参数一是窗口类名,参数二是窗口名,这个为了确保正确,还是拿Spy++打开看了一下:

详解C语言实现植物大战僵尸阳光9999_第19张图片
详解C语言实现植物大战僵尸阳光9999_第20张图片
类名MainWindow,窗口标题真就是“植物大战僵尸汉化版”。

三、润色

之所以多这么一个部分,主要是想把自己平时的一些操作系统地总结一下
所以这里会很啰嗦,也是为了给自己看。

对话框
DevCpp也可以搞对话框,不过DevCpp的资源调用不太会,暂时没把握,所以CodeBlocks,而且CodeBlocks可以配置资源编辑器ResEdit。

为什么不用VS2019,因为不想过于依赖外物,会阻碍自己成长,而且VS会有一些莫名奇妙的错误,代码量不多划不来用。

#include 
#include 
#include 
#pragma comment(lib,"winmm.lib")
#include "resource.h"
#include 

HINSTANCE hInst;
int toWriteValue=9999;
BOOL CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{

    DWORD base=0x0019FD2C;
	DWORD offset1=0x768,offset2=0x5560;
	DWORD temp_addr=0;
	HWND WindHandle;
	DWORD pid;
	HANDLE ProcessHandle;
	LPVOID toChangeAddr=NULL;
	int PrevValue;
	int toWriteValue=9999;
	WindHandle=FindWindow("MainWindow","植物大战僵尸汉化版");
	GetWindowThreadProcessId(WindHandle,&pid);
	ProcessHandle=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);

	ReadProcessMemory(ProcessHandle,(LPVOID)base,&temp_addr,sizeof(DWORD),NULL);
	ReadProcessMemory(ProcessHandle,(LPVOID)(temp_addr+offset1),&temp_addr,sizeof(DWORD),NULL);
	toChangeAddr=(LPVOID)(temp_addr+offset2);
    switch(uMsg)
    {
    case WM_INITDIALOG:
    {
    }
    return TRUE;

    case WM_CLOSE:
    {
        EndDialog(hwndDlg, 0);
    }
    return TRUE;

    case WM_COMMAND:
    {
        switch(LOWORD(wParam))
        {
        case IDOK:
            WriteProcessMemory(ProcessHandle,toChangeAddr,&toWriteValue,sizeof(DWORD),NULL);
            PlaySoundA((LPCSTR)IDR_WAVE1,GetModuleHandle(NULL),SND_RESOURCE|SND_ASYNC);
        }
    }
    return TRUE;
    }
    return FALSE;
}


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    hInst=hInstance;
    InitCommonControls();
    if(!FindWindow("MainWindow","植物大战僵尸汉化版"))
    {
            MessageBeep(MB_ICONHAND);
        return MessageBox(NULL,"游戏未启动!","错误:",MB_OK);
    }

    return DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, (DLGPROC)DlgMain);
}

对话框代码不用自己写,直接新建项目,DialogBased自动生成模板,把之前的核心代码放在合适位置即可

另外猜测会有人遇到的问题:
1.undefined refernce impXXX
2.会有控制台出现。
对于1,请看我的另一篇博客 部分undefined reference to `__imp_XXXX‘错误解决方案
对于2,是因为你的生成目标是Debug选项,改成Release就会有控制台跳出来了。

资源文件
加图标:
在记事本里写上:MAINICON ICON “Icon_1.ico”
然后重命名为XXX.rc,点击项目—>添加文件,把XXX.rc加进去,然后把图标“icon_1.ico”放进去,编译即可。

.wav文件的嵌入:
这个要用资源编辑器添加,因为资源文件有自己的语法,如果前后定义不兼容会编译失败,就是通过也不能正常运行。所以尽量用同一个工具。
我比较推荐ResEdit,很靠谱,只有1M多,就是界面有点丑。
占位符:“CodeBlocks配置ResEdit”,有空再写一篇
CodeBlocks对话框项目会自动生成一个对话框,在ResEdit中把它去掉,然后用ResEdit重新添加一个对话框,不然会失败,我猜测是编译器和资源编辑器对资源文件的语法不同,总之要做到统一。
详解C语言实现植物大战僵尸阳光9999_第21张图片

详解C语言实现植物大战僵尸阳光9999_第22张图片

个性图标
这个我是直接在线艺术字生成,然后截图下来
详解C语言实现植物大战僵尸阳光9999_第23张图片
然后格式工厂转格式成.ico就OK了
详解C语言实现植物大战僵尸阳光9999_第24张图片
我不是男同,只是觉得这个图标比较有亮点。

2021/6/14更新:
植物冷却的基址已经找到了,等有空再写下一篇博客,最近考试有点多。
冷却基址是真的不好找,看了两篇其他博客,都找的是变动地址,这不能满足我们制作外挂的要求。
简单说下,冷却基址直接搜——反正在我的版本是搜不到地址的,要找到可疑汇编代码后去内存里看。我觉得原因可能是数据和代码写到一个内存块了,然后直接搜会不被当数值而排除,也许吧,我也不太懂。
(如果没记错,植物冷却基址和这次的阳光基址是一样的。)

你可能感兴趣的:(小项目,C语言,c语言,api,游戏)