C#读写二进制文件,可以修改部分单机游戏存档。学以致用

以单机游戏【仙剑奇侠传三】为例,使用的版本是方块游戏1.04版。打开仙剑奇侠传三游戏“新的开始”,等待剧情过后,景天单人自由活动时,保存到第一个存档。将在仙剑三主目录的save文件夹下生成一个二进制存档文件。个人测试电脑存档文件路径为“H:\CubeLibrary\apps\1000039\save\pal00.arc”。为了防止修改数据错误,我们先备份一个文件pal00bak.arc,用于测试使用

初始景天一级的精 88/88、气17/17、神29/29【数据代表当前数据和上限数据。比如:当前精88/精上限88】。

读取二进制文件,进行抓包,找出所有的 88,17,29数据

unity3d游戏 修改 unity游戏存档怎么修改_unity3d游戏 修改

我们发现有3组疑似数据,如上图所示。

将上面的精气神三组数据修改掉,为新的字节数组赋值。比如篡改精气神的值以依次为250、150、200。

保险一点,全部都修改掉。

buffer[1352] = 250;//精
                        buffer[1356] = 150;//气
                        buffer[1360] = 200;//神

                        buffer[1640] = 250;//精
                        buffer[1644] = 150;//气
                        buffer[1648] = 200;//神

                        buffer[1688] = 250;//精
                        buffer[1692] = 150;//气
                        buffer[1696] = 200;//神

新建控制台程序:ReadWriteBinaryFileDemo

相关的C#源程序如下:

using System;
using System.IO;

namespace ReadWriteBinaryFileDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                string fileName = @"H:\CubeLibrary\apps\1000039\save\pal00bak.arc";
                int fileSize = (int)new FileInfo(fileName).Length;
                Console.WriteLine($"仙剑三存档文件大小:{fileSize}字节");
                byte[] bufferWrite = new byte[fileSize];
                using (FileStream fileStream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                {
                    //以二进制方式读文件 
                    //创建一个二进制数据流读入器,和打开的文件关联
                    using (BinaryReader binaryReader = new BinaryReader(fileStream))
                    {
                        // 把文件指针重新定位到文件的开始 
                        binaryReader.BaseStream.Seek(0, SeekOrigin.Begin);
                        //读取所有数据
                        byte[] buffer = binaryReader.ReadBytes(fileSize);
                        binaryReader.Close();
                        //在刚保存一级的时候 景天【当前】精88 气17 神29。 景天【上限】精88 气17 神29
                        //我们使用抓包的方式 过滤出来。然后尝试修改
                        for (int i = 0; i < buffer.Length; i++)
                        {
                            if (buffer[i] == 88)
                            {
                                Console.WriteLine($"当前索引:{i},景天精{buffer[i]}");
                            }
                            else if (buffer[i] == 17)
                            {
                                Console.WriteLine($"当前索引:{i},景天气{buffer[i]}");
                            }
                            else if (buffer[i] == 29)
                            {
                                Console.WriteLine($"当前索引:{i},景天神{buffer[i]}");
                            }
                        }
                        //检索 精气神对应数据所在的包的附近40个字节
                        for (int i = 1352 - 8; i < 1352 + 32; i++)
                        {
                            Console.Write(buffer[i] + " ");
                        }
                        Console.WriteLine();
                        for (int i = 1640 - 8; i < 1640 + 32; i++)
                        {
                            Console.Write(buffer[i] + " ");
                        }
                        Console.WriteLine();
                        for (int i = 1688 - 8; i < 1688 + 32; i++)
                        {
                            Console.Write(buffer[i] + " ");
                        }

                        //这里篡改精气神的值以依次为250、150、200
                        buffer[1352] = 250;//精
                        buffer[1356] = 150;//气
                        buffer[1360] = 200;//神

                        buffer[1640] = 250;//精
                        buffer[1644] = 150;//气
                        buffer[1648] = 200;//神

                        buffer[1688] = 250;//精
                        buffer[1692] = 150;//气
                        buffer[1696] = 200;//神

                        //将篡改过的数据【新的精气神数据】 写入的新的字节数组中
                        Array.Copy(buffer, 0, bufferWrite, 0, fileSize);
                    }
                    fileStream.Close();
                }

                using (FileStream fileStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite))
                {
                    //以二进制方式写文件 
                    //创建一个二进制数据流写入器,和打开的文件关联
                    using (BinaryWriter binaryWriter = new BinaryWriter(fileStream))
                    {
                        binaryWriter.Write(bufferWrite);
                        binaryWriter.Flush();
                        binaryWriter.Close();
                    }
                    fileStream.Close();
                }
                Console.WriteLine($"重新写入文件成功...");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"读写文件时出现异常:{ex.Message}");
            }
            Console.ReadLine();
        }

    }
}
程序运行如图:

unity3d游戏 修改 unity游戏存档怎么修改_FileStream_02

我们将原来的存档文件pal00.arc重命名为pal00_raw.arc。将修改后的文件 pal00bak.arc 重命名为pal00.arc。

重新打开 仙剑奇侠传三 游戏,点击“旧的回忆”,读取存档一,点击右上角的人物头像,惊喜的发现 精气神变成250,150,200了。

unity3d游戏 修改 unity游戏存档怎么修改_数据_03

大功告成。

其他物品数量,金钱都可以修改二进制文件的某些值 即可。

比如精888=3*256+120,转化为两个字节为3,120。只要抓包找出连续数组元素的值为buffer[i]=3 && buffer[i+1]=120 即可。