Save File Structure - NUCLEAR-BOMB/dig-or-die-mods GitHub Wiki
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.
-
Header
- Magic:
"SAVE FILE"
- Version (
float
), Build ID (s32
), Game Name (String
). - Ends:
"Header"
- Magic:
-
Game Params Data
- Serialized by
BinaryFormatter
data (skipped). - Ends:
"Game Params Data"
- Serialized by
-
Items Data
- Item names, active pickups (ID + position).
- Ends:
"Items Data"
-
Players
- Per-player: Steam ID, name, position, inventory (items + hotbar), skin data (Build >= 495).
- Ends:
"Players"
-
Environments (Build >= 815)
- Recent event names.
- Ends:
"Environments"
-
World Data
- A very big chuck of serialized grid cells (skipped due to size).
- Ends:
"World Data"
-
Units Data
- Monsters/NPCs (position, health) + kill stats.
- Ends:
"Units Data"
-
Vars Data
- Serialized by
BinaryFormatter
data (skipped). - Ends:
"Vars Data"
- Serialized by
For more detailed explanation, examine dod-save.hexpat
directly, it's not really hard to understand. Refer to the Pattern Language Documentation as needed.
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.
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.