无法使用外部工具打开压缩流

逆向工程 。网 解压
2021-06-15 17:15:39

我正在尝试对游戏保存文件的文件格式进行逆向工程。该游戏是用 Unity 编写的,因此是 .NET,因此可以使用 RedGate Reflector 查看近似代码。

现在我知道格式是一个标题,然后是一个压缩的地图数据流,它是用 ICSharpZipLib 创建的。

标头由两个字符串组成,前缀是一个字节及其长度。第一个字符串只是一个格式说明符,第二个是版本标识符。在这些字符串之后,有一个字节表示内容是否被压缩(但它被硬编码到游戏中以始终压缩)。

<byte flen> <byte[flen] format> <byte vlen> <byte[vlen] version> <byte compress> <data>

游戏读取文件如下:

  1. 打开文件进行读取,BinaryReader围绕流创建一个
  2. 读取格式说明符 ReadString
  3. 使用ReadString and读取版本,int.Parse如果是旧存档则警告玩家
  4. 用于ReadBoolean检查它是否是压缩文件
    • 如果为真,则将文件流包装在一个 InflaterInputStream
  5. 将文件内容读入字符串,传递给其他函数

我的麻烦是阅读内容,我编写了一个简单的 C# 程序来模仿游戏的行为,使用完全相同的库版本,但我得到了一个“意外的 EOF”。编辑文件以删除未压缩的标头并使用其他命令行膨胀实用程序打开它也会导致该错误。该文件保证有效,因为游戏可以毫无问题地打开它。

下面是两个示例文件。有问题的游戏叫做 Atmosphir,可以在这里下载

https://mega.nz/#!f5QFHJ6T!55LvsPFaaAp7Y-ZS3GbLPHg8Ohh-p-5M0AR_Hb7jd1c

https://mega.nz/#!C5xxEapL!ZZ9Tg2kjQetr9KXmfBn5rBc5c5BZ1UUXeqSLJvfJiyQ

1个回答

也许您的代码试图读取比压缩标头中指定的更多的记录?

我下面的代码工作正常(\Atmosphir\Atmosphir_Data\Atmosphir_Data\Managed\ICSharpCode.SharpZipLib.dll作为参考):

using System;
using System.IO;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;

namespace Atmo
{
    class Program
    {
        static void Main(string[] args)
        {
            StreamReader sr = new StreamReader("cc16.atmo");
            BinaryReader br = new BinaryReader(sr.BaseStream);
            Console.WriteLine("Format: " + br.ReadString());
            Console.WriteLine("Version: " + br.ReadString());
            Console.WriteLine("Compressed: " + br.ReadBoolean());
            br = new BinaryReader(new InflaterInputStream(sr.BaseStream));
            int total = br.ReadInt32();
            for (int i = 0; i < total; i++)
            {
                Console.WriteLine(br.ReadString());
            }
        }
    }
}

输出:

Format: AtmoMap
Version: 5
Compressed: True
mi_flag_finish
mi_block_color_white
mi_wood_sticks
mi_block_color_green
mi_block_bricks_1q_cylinder_straight
mi_block_bricks
mi_block_bricks_1q_pipe
mi_ladder_creeper_green
mi_gravity_area_uniform
mi_sandcastle_corner
mi_sandcastle_connection
mi_condition_trigger
mi_skybox_realistic
mi_skybox_adventure
mi_info_sticker
mi_condition_count
mi_skybox_halloween_nightsky
mi_skybox_afternoon
mi_condition_area
mi_bark_slice_platform
mi_waypoint
mi_block_color_blue
mi_block_bricks_white_ledge
mi_ladder_hanging
mi_moving_platform_disc
mi_block_bricks_lightbrown
mi_block_candy_vanilla_cake
mi_candy_floor_orange
mi_sandcastle_tower_top
mi_sandcastle_tower
mi_block_bricks_white
mi_torch
mi_block_bricks_white_2b_diagonal
mi_floor_green
mi_block_monkey
mi_block_bricks_half
mi_bridge_hanging
mi_block_bricks_lightbrown_2b_diagonal
mi_flag_checkpoint
mi_muka_boss
mi_death_skull
mi_muka_shaman
mi_muka_axe_warrior
mi_muka_scout
mi_muka_crypt_keeper
mi_candy_gumdrops_yellow
mi_block_candy_gingerbread_glazed_yellow
mi_candy_gumdrops_green
mi_candy_sugartree_red
mi_candy_sugartree_yellow
mi_candy_floor_violet
mi_candy_sugartree_blue
mi_candy_floor_red
mi_block_candy_gingerbread
mi_block_candy_gingerbread_glazed_pink
mi_candy_gumdrops_red
mi_candy_floor_blue
mi_floor_muka
mi_floor_caved
mi_muka_sticks
mi_block_wooden_bark
mi_torchwall_steel
mi_totem
mi_floor_river_grass
mi_plant
mi_block_crate
mi_flag_start
mi_floor_sand
mi_gate_skull
mi_muka_tent_open
mi_stonehead
mi_muka_openbox
mi_block_bricks_stone
mi_mutation_ammo
mi_fence_straight
mi_2d_force_area
mi_block_monkey_broken
mi_block_bricks_white_floor
mi_block_sand
mi_block_color_black
mi_block_color_yellow
mi_block_color_lightbrown
mi_block_color_lightgreen
mi_block_color_red
mi_block_color_purple
mi_block_candy_gingerbread_sprinkled
mi_block_magma2
mi_block_color_brown
mi_river_water
mi_stones
mi_big_flowers
mi_river_reed
mi_block_sanddirt
mi_block_river_earth