之前已经使用HxD Hex Editor工具成功修改游戏存档, 具体步骤请参考:https://blog.csdn.net/weixin_50669669/article/details/120984999, 本文将使用java代码替换工具,实现同样的修改功能。一、前言
在上次用 HxD Hex Editor 工具实现游戏修改后,考虑了以下问题:
- 用 HxD Hex Editor 工具修改需要下载该工具,还得自己进行进制计算等问题,实属有些麻烦!
- 可不可以开发出一种像市面上一样的修改器(下载后,即可修改使用),供大家使用呢?
- 该游戏的存档数据可以轻易得到并且修改,从而推断很多游戏的存档都可以得到并修改,那么有没有什么办法可以阻止这一切的发生呢?
下面我们将带着这些问题进行逐个探讨
注:由于本人才疏学浅,目前阶段无法实现所想实现的问题,本文只是对其的思考和一些个人看法。当我能力足够时会将其解决、完善。
二、部分实现过程 1、开发环境 Java版本:JDK1.8
使用工具:IntelliJ IDEA
-
读取数据:由于该游戏的数据文件存储在本地的存储位置是已知的;
C:ProgramDataPopCap GamesPlantsVsZombiesuserdatauser1.dat
所以首先要读取user1.dat中的数据。
-
修改数据:由之前尝试可知,通过修改user1.dat中第一行的数据即可以获得想要的结果。
-
写入数据:将修改后的数据重新写入到user1.dat中。
-
IO流的使用 (获取并输出所要改动的数据)
字节: (输入)inputsterm (输出)outputstream
字符: reader writer
In:把文件读入进来
Out:把自己的东西写入文件里边去。
Reader:把东西读出来;
Witer:把东西写进去。
字节流 (FileInputStream)
字节输入流:读入文件到内存中进行使用,是先到磁盘里去把文件读入到内存中,然后进行使用,就可以加载了。 -
进制的转换
由于获取的数据为十六进制数据,而修改关卡用户输入的为十进制,故需要进制的转换
所涉及知识可参考下述文章: IO流(文件的读写):https://blog.csdn.net/dkwjava/article/details/88858486 https://blog.csdn.net/qq_31360175/article/details/49407005 https://baike.baidu.com/item/IO/5918 https://baijiahao.baidu.com/s?id=1667654018904536818&wfr=spider&for=pc
- 定义全局变量userIndex,用来存放.dat文件下读取出来的数据(数组)
- 定义全局变量fileName,声明.dat所在的本地路径。
static ArrayListuserIndex=new ArrayList<>(); static String fileName="C:\ProgramData\PopCap Games\PlantsVsZombies\userdata\user1.dat";
- 读取user1.dat中第一行的数据
// 从二进制文件中读取数据(在输出到控制台时十六进制数据自动转成十进制)
public static void readData(){
try
{
FileInputStream fis= new FileInputStream(fileName);
BufferedInputStream br = new BufferedInputStream(fis);
int record = -1;
while((record = br.read()) != -1)
{
userIndex.add(record);
}
System.out.println("从文档中读取第一行数据显示(十进制):");
for(int i=0; i<16; i++){
System.out.print(userIndex.get(i) + " ");
}
System.out.println();
}
catch(Exception e)
{
System.out.print(e.toString());
}
}
-
用if-else循环语句来实现数据修改
游戏关数的修改
if (type.equals("1")){ System.out.println("请输入您要改的关卡:(例;2-6)"); Scanner input=new Scanner(System.in); String level=input.nextLine(); int firstLevel=Integer.valueOf(level.substring(0,1)); int lastLevel=Integer.valueOf(level.substring(2,3)); if (firstLevel < 1 || firstLevel > 5 || lastLevel < 1 || lastLevel > 10){ System.out.println("Error"); System.out.println("没有此关卡,请重新输入"); }else { //跳转的关卡为 p-q 转化为关卡数为:(p-1)*10+q int addLevel = (firstLevel - 1) * 10 + lastLevel; //修改数据:关卡数在第一行04位置,即数组中下标为4 userIndex.set(4, addLevel); } }金币修改
在.dat文件中,金币数量是由08,09,0a,0b是存储位,包含8个十六进制位,因此需要将不够位数的在前面补齐。此思路用for循环,循环次数是(8-十六进制数的length)。例如"989680->00989680"。补齐之后以两位为单位,分别按低位->高位的顺序替换08->0b的值。例如"80,96,98,00"分别替换"08,09,0a,0b"位的值。
else if (type.equals("2")){ System.out.println("请输入您要改的金币数量:"); Scanner input=new Scanner(System.in); String money=input.nextLine(); //需要加到的金钱 int needMoney=Integer.valueOf(money)/10; String HexMoney=Integer.toHexString(needMoney); //在十六进制数前面补0到8位(金币数量是由08,09,0a,0b是存储位) String zero=new String(); for (int i=0;i<8-HexMoney.length();i++){ zero+="0"; } HexMoney=zero+HexMoney;//补全的十六进制 //最后两位,对应第一行08位置,进行替换 int data08=Integer.valueOf(HexMoney.substring(HexMoney.length()-2)); userIndex.set(8, Integer.parseInt(String.valueOf(data08),16)); //倒数第3,4位,对应第一行09位置,进行替换 int data09=Integer.valueOf(HexMoney.substring(4,6)); userIndex.set(9, Integer.parseInt(String.valueOf(data09),16)); //正数第3,4位,对应第一行0a位置,进行替换 int data0a=Integer.valueOf(HexMoney.substring(2,4)); userIndex.set(10, Integer.parseInt(String.valueOf(data0a),16)); //正数第1,2位,对应第一行0a位置,进行替换 int data0b=Integer.valueOf(HexMoney.substring(0,2)); userIndex.set(11, Integer.parseInt(String.valueOf(data0b),16)); }else if(type.equals("3")){ //修改数据:关卡数在第一行0c位置,即数组中下标为12 userIndex.set(12,1); }解锁所有模式
将0c位的数改为01即可
else if(type.equals("3")){ //修改数据:关卡数在第一行0c位置,即数组中下标为12 userIndex.set(12,1); } -
将修改后的数据写入user1.dat中
// 将数组以二进制写入文件中
public static void writeData() throws IOException {
FileOutputStream fileWriter=new FileOutputStream(fileName,false);
for (int singleData:userIndex) {
fileWriter.write(singleData);
}
//写入文件
fileWriter.close();
}
三、代码缺陷
-
未能实现无限循环功能,即未点击退出修改,则可一直通过修改界面修改
-
未能实现金币达到上限功能(由 HxD Hex Editor 可知该游戏金币有上限)
-
未能实现其他功能的修改 如:太阳值、植物攻击力等
-
未能实现功能的封装,修改起来比较麻烦
-
未能将其做成软件化,修改时需要Java环境
推荐一些做的较好的文章链接(有些缺陷功能已经实现) CSDN实训 - 通过Java修改游戏存档 :https://blog.csdn.net/qq_48455576/article/details/121002191 修改植物大战僵尸游戏存档(Java实现版):https://blog.csdn.net/m0_50207094/article/details/121006091 Java外挂开发之内存修改器(类似CE):https://blog.csdn.net/qq969422014/article/details/53544071
-
风控与渗透方面
由此可见,通过以上几个简单步骤,就完了对游戏的破解和篡改。对破解者而言,这只是分分钟的事情,而对于游戏开发者,却是多少个加班和心血被付诸东流的惨剧。开发不易,提供应用安全性,需要防患于未然。撰写代码规则、进行漏洞检测或使用第三方加密保护都是避免被破解的方法。
-
总结
由于本人能力有限,本篇有很多内容均为借鉴与整理他人文章而创作,将来当我知识储备量达到一定程度后我会完善该项目,请大家谅解!



