Hacking Finding .SAV checksum to allow for editing saves.

NatK98

Member
OP
Newcomer
Joined
Feb 28, 2023
Messages
6
Trophies
0
Age
26
XP
56
Country
Australia
hello, so as the title implies, i need some help finding out how checksums work in NDS games, or at the very least, this one.


I have exported a few saves from the Transformers: AUTOBOTS game, developed by vicarios visions, whilst changing only one value in the settings (Music volume from 7 to 8) to have a look at them and i know for sure there's a checksum because the save comes up as corrupt in-game if i adjust any values without adjusting the checksum.

i'm new to this scene, so i'd appreciate any and all help when it comes to how to figure this out.

in the attached .SAV files, i changed the music volume from 7 to 8 then to 9 in game.
AUTOBOTS.0 is the 7, AUTOBOTS.1 is the 8 and AUTOBOTS.2 is 9 volume.


I should add that this save contains two files, one profile name is NATHAN and the second is THTKKKK (You can thank my cat for that)
it's just how the game works. Even making a new game, it still has those two spots, they are just called "New Game" instead.

these saves were all exported using TWL save tool.

I just can't find any information on how one would be able to edit NDS saves, because of these checksums. Any help would be greatly appreciated.

https://file.io/yX2Mj566sJ3y
 
Last edited by NatK98,

FAST6191

Techromancer
Editorial Team
Joined
Nov 21, 2005
Messages
36,798
Trophies
3
XP
28,403
Country
United Kingdom
There is no BIOS/firmware level checksum, and no SDK provided one (at least not one used often) which means the DS is probably the last of the "whatever the dev decided to cook up that day" approaches, with the added bonus of there being just about enough CPU power underneath it all to occasionally do something quite involved (though this is rare outside of things like the browser where you need proper hashing).

Your job is to figure out three things as the would be save hacker, though there is a cowboy method that works for some things people want to do.

1) Figure out where the hash is.
2) Figure out what is hashed.
3) Figure out what method the hash uses.

1) Is usually a matter of getting multiple hopefully similar saves and comparing them. A decent hash/checksum method (which is not necessarily what you will encounter) will change the result radically when even a bit of data is changed and thus your changing volume example should have the volume that changed, maybe any game time also on the back of it and the hash being the things that change.
Typically it will be at the start of the end of the section it deals with.
2) You can't hash the hash if you want to predict things (though a bit further down the line you might encounter HMAC) so the hash will tend to be aside from the data it governs. Normally this will be the start of the section (or end of it) for the hash and the rest is what it sorts.
3) Fun fun fun. For the most part you are going to have to get down and dirty with assembly code for this one. Maybe you get lucky and it is some obvious bytesum or stock implementation of a known method (CRC, MD5, SHA1, https://www.pelock.com/products/hash-calculator or whatever is on your chosen hash calculator) but you are more likely going to have to watch it happen, figure out what it is doing and implement that.

I used the word section above very deliberately. Games with multiple save slots then have sections, and games with backups/wear levelling (pokemon being one of the more notorious) where saves alternate between sections as both a roll back backup and means of stopping the same section being written to all the time being the two main issues. Multiple save slots is usually fairly basic and either hash-data-hash-data-hash-data or some obvious break there. Backups can be harder as there will also have to be an indicator as to what is the current slot being used, and by its very nature will trouble the compare two files approach. Some save the game twice to force it back to the original region (it is handheld games not a bank's account holder list so you are not going to get more than that), others figure out the format breakdown (you will want to eventually for the save editor anyway) and then work on the individual save sections/instances.

Cowboy method. The hash method could be a combination of some master coder doing all the crack and trying to obfuscate the method but ultimately in games it tends to boil down to [get data], [do hash], [compare computed result to hash read in save], IF match then goto continue game ELSE roll back save/say save corrupt/.... (though in ARM assembly it will probably look more like a compare (CMP) and some flavour of branch and most likely BNE/branch if not equal). Change this branch to always take the good one and you will both have dodged the save and better still next time it saves you will have a valid save again. With most DS games having the binary in memory you can also distribute it with a cheat such that anybody wanting to use a modded save then either has to use the cheat, or send it through an emulator with it enabled the one time and then restore. Not ideal but will get it done. In your case if you are getting your feet wet in coding doing this will allow you to get familiar with the save format and once you are more established in all this return to tackle the hashing method.
It is not a bad intro to tracing either ( https://www.romhacking.net/documents/361/ ). You know the save data (sometimes things are compressed or calculated from data held within it but pick some other part that is not), you know about when it loads into memory (typically either when loading a save, when "press start to continue" is pressed or when first booting and showing developer title cards). Thus you can find where the save data lands in memory after it is read (assuming you don't outright just watch the read commands happen http://problemkaputt.de/gbatek.htm#dscartridgebackup ), and maybe even the hash data itself (sometimes it is separate to the whole data). Finding the compare command there to start disabling things is not so very much further, and you would also be doing much of this if you were going to watch the save hash being generated so as to replicate it on something else (in an ideal world you would understand what it is doing, makes for some far quicker code as well, you would however not be the first to treat it as a black box and replicate all the steps/the non obvious steps* without actually understanding what it is doing).

*most consoles/assembly language setups can't load arbitrary amounts of data from one location to another, consequently it might load it a few bytes at a time until it is done. No need to replicate that if it is an obvious FOR or WHILE loop and you instead can tell your high level language to just grab the whole section at once. At that point you then figure out what maths, boolean logic or such it is doing to generate the checksum/hash, or go for the replicate the black box approach.
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
    K3Nv2 @ K3Nv2: Stop trying to make on my cakes