Save File Structure - NUCLEAR-BOMB/dig-or-die-mods GitHub Wiki

Save File Structure

The project root contains a dod-save.hexpat file written in Pattern Language used by ImHex. This pattern provides an incomplete reverse-engineering of Dig Or Die's save file format.

Important

Save files uses LZF compression (implementation can be found here. You must to decompress the save before viewing/modifying and recompress after edits.

A command-line tool for compression/decompression is included in this repository.

Note

It is hard/impossible to fully parse the save file due to:

  • Requiring game specific context (world size, monster unit IDs, etc.).
  • Some sections uses C#'s BinaryFormatter which would been very hard to implement in hexpat language. Currently the pattern skips sections that requires listed above stuff.

Structure Summary

  1. Header

    • Magic: "SAVE FILE"
    • Version (float), Build ID (s32), Game Name (String).
    • Ends: "Header"
  2. Game Params Data

    • Serialized by BinaryFormatter data (skipped).
    • Ends: "Game Params Data"
  3. Items Data

    • Item names, active pickups (ID + position).
    • Ends: "Items Data"
  4. Players

    • Per-player: Steam ID, name, position, inventory (items + hotbar), skin data (Build >= 495).
    • Ends: "Players"
  5. Environments (Build >= 815)

    • Recent event names.
    • Ends: "Environments"
  6. World Data

    • A very big chuck of serialized grid cells (skipped due to size).
    • Ends: "World Data"
  7. Units Data

    • Monsters/NPCs (position, health) + kill stats.
    • Ends: "Units Data"
  8. Vars Data

    • Serialized by BinaryFormatter data (skipped).
    • Ends: "Vars Data"

For more detailed explanation, examine dod-save.hexpat directly, it's not really hard to understand. Refer to the Pattern Language Documentation as needed.

Vulnerabilities

1. Insecure Deserialization

The game uses C#'s deprecated and insecure BinaryFormatter to serialize/deserialize some sections of save file. There's also exists ysoserial.net, a tool for creating a deserialization payload to exploit unsafe .NET object deserialization.

Hypothetically you could inject a payload into Dig Or Die's save file, and on opening that file in the game execute some malicious (or not) code. Sadly (or happily), the standard libraries that the game comes (mscorlib.dll) doesn't have the types and fields on which ysoserial.net payloads rely on (or at least the ones I checked). They just cut of from binary.

If there's still some way to do this, I think it would be an interesting idea to create a save file which will dynamically load the plugins in the game without any BepInEx. It would make using custom plugins so much easier. But yeah, there's opposite side, you've to firstly check to save file for the presence of malware.

2. Array Length Exploits

The game's save file parser doesn't validate array lengths. You can just modify the save file and set some array length to very large value to out-of-memory crash the game by opening a save.

⚠️ **GitHub.com Fallback** ⚠️