使用python编写帝国时代2修改器

之前的文章有介绍了《使用python编写游戏修改器》
最近怀旧一下,在玩《帝国时代2》,然后就尝试着再写一个修改器试试。

查找内存地址

首先用 Cheat Engine 来修改资源,以及查找资源的内存地址。注意这里的数据都要使用浮点数类型。
如图找到的食物内存地址是 0F2B93B0
age2_ce01

通过逐步分析得到以下指标的内存地址为:
木材地址 = 食物地址 + 4
石头地址 = 食物地址 + 8
黄金地址 = 食物地址 + 12
黄金地址 = 食物地址 + 12
人口上限地址 = 食物地址 + 16
当前人口地址 = 食物地址 + 44

如果想要实际无限人口,只需要修改 人口上限 和 当前人口 这两个数据即可。
这些地址都找到之后,然后就开始写代码,使用 Python 调用 WriteProcessMemory 来修改游戏的内存。
然而在打完这一局之后开启新的游戏时却发现这些地址全都变了。
每次开启新的游戏时都需要重新查找一遍地址内存,这个就有点麻烦了。

查找游戏基址

通过分析发现这些地址都全是动态地址,每次游戏时都不一样。根据仅记得的一点汇编知识知道,这些动态地址是通过基址加偏移地址得到的。所以现在一劳永逸的方法是找到基址地址。而基址是静态的。然后接下来逐步进行分析。

首先刚刚食物地址是0F2B93B0。游戏程序如果要从这个地址获取食物数据,那么就得在某个地方储存这个地址值。这里我们就先将这个地址称为食物地址指针。接着用 CE 查找一下 0F2B93B0 这个值,然后就找到了食物地址指针地址为 206221B8。如图:
age2_ce02
注意这里要用 16 进制的方式来查找这个地址值。如果用 C 语言代码的描述相当于:

1
2
3
int food_point = 0x206221B8       // 食物地址指针
int food_address = *food_point; // 食物地址指针 指向食物地址 0x0F2B93B0
int food = *food_point; // 从食物地址 0x0F2B93B0 得到食物的值

经过测试发现这个食物地址指针地址也是动态的。没办法了,只能继续往下找。现在来看看都有谁访问了这个地址。如图:
age2_ce03
age2_ce04
这里我们又得到了一个地址: 20622110 。再来看看是哪里记录了这个地址呢。如图:
age2_ce05
这里我们又找到了 007A5FEC 这个地址,运气不错。在 CE 中显示为绿色,表示它是一个静态地址。这表示它就是我们要找的基址了。

总结

现在来总结一下。使用 C 语言代码描述如下:

1
2
3
4
int base_addr = 0x007A5FEC;             // 游戏基址
int food_point = *base_addr + 0xA8; // 基址记录的值0x20622110 + 偏移地址0xA8 = 食物地址指针
int food_address = *food_point; // 得到食物地址
int food = *food_address; // 从食物地址 0x0F2B93B0 得到食物的值

最终修改的结果如图:
age2_ce06

上面修改器的完整源代码,如有需要可通过以下链接获取:
https://github.com/wusuopu/cheat_engine_age2