《植物大战僵尸》 辅助编写3—— 修改植物血量

从上文我们可以知道,69F2C0 地址是植物卡片信息数组的起始地址。

这里我尝试修改了土豆的属性,将其变为1。但土豆没有立刻被僵尸吃掉,时间还是和之前的差不多。


那么信息应该就和没改过的6720496有关,观察这个数字和它前面的67205XX数字,感觉这个应该是指针,数组里面的类的大小应该是18字节。 重新启动几次游戏后发现这个也是静态地址【实际上这个地址是plantName,植物的名字】

class PlantInfo{
    int sunCost;
    int CD; // every 100 means 1 second
    int ???;
    int ShootInterval; // 攻击间隔 every 100 means 1 second  设置为50好像是最小值
    void* extraInfoPointer; //指向额外的信息,0x12字节 = 18字节
    int ???;
    int ???;
    int ???;
    int ???;
}

粗看了一下这个额外的信息,感觉看不出什么,先从攻速入手。

给这个地址下个访问断点,发现0045DCE0地址的代码访问了ShootInterval [eax+1C]字段。这个时候eax的值是69F2B0,而不是之前观察到的69F2C0 。一定是哪里出了问题。

0045DCE0 |  mov edx,dword ptr ds:[eax+1C]   | 获取植物的攻击间隔

重新观察内存。发现从69F2B0开始以9个int为差值,呈现 0 ,1 ,2 ,3 ,4的规律。这应该就是植物的Id。所以植物信息的基地址其实是69F2B0而不是69F2C0 。

所以植物的类应该是下面这个样子【我说为什么调了半天有些字段没效果。。。】

class PlantCard{
    int plantId;
    int ???; //好像是没用的
    int skinId/animationId; // 动画的效果 皮肤
    int ???;
    int sunCost;
    int CD; // every 100 means 1 second
    bool CanSpwanBullet; //能否发射子弹  如果可以,会去访问子弹的资源,所以如果本身是不可以的,你将其改成可以,那么会访问未分配的地址,会生成一个segment fault
    int ShootInterval; // every 100 means 1 second  设置为50好像是最小值
    char* pPlantName; //指向额外的信息->植物的名字,0x12字节 = 18字节

}

然后再调试了一下,发现最后一个字段是指针,指向植物的名字。。。。

通过攻击间隔寻找 PlantSceneObject信息

给攻击间隔的地址下访问断点,可以发现在0045DCE0指令处会访问。这里ebx感觉是场上的植物对象PlantSceneObject 的基地址。

这里取几个ebx的值

ebx ; PlantSceneObject

0F47457C

0F4746C8

0F474814
观察差值,可以发现PlantSceneObject 大小是0x14C.而且应该是malloc动态分配的。

在 CE里面 设置数据对齐大小为0x14C,获得场上植物的信息。可以看到这里有8行数据,对应场上8个豌豆射手。

那么怎么才能知道哪几个字节是植物的血量? 放一个新的植物到场上,然后用CE搜索这个植物的0x14C结构体内的数据,先搜未变更的值。过滤掉一部分字段。等僵尸造成伤害后,再搜索变更的值,筛选出3个字段,然后观察。发现偏移为0x40-0x41为植物的血量,类型为ushort。

此时场上植物的类型PlantSceneObj为

class PlantSceneObj{
	unsigned short HP; // 植物当前血量 0x40-0x41
	bool canSpawnBullet; // 由45DCF2地址的代码得出  0x48
	
}

得到这个信息之后,我们回去找对应ebx+40赋值的代码,给0x40偏移的字段打上写断点。发现下面的代码赋予了初始值


土豆会在这里再次赋值

被僵尸咬的时候,下面0052FCF0地址的代码会扣掉4点血。因此如果想要植物永远不死,只要设置一个奇数的生命值就行。

posted @ 2023-02-08 00:21  dewxin  阅读(615)  评论(0编辑  收藏  举报