Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

Initial research for hacking savegame files for Snoopy vs. the Red Baron

This is the story of my meanderings to learn how to hexedit the savegame file for PC game Snoopy vs. The Red Baron.

The game has a short campaign (<20 hours of gameplay) where you unlock more weapons, earn money to buy those unlocked weapons and upgrades, and defeat the final boss.

The game appears to use a video-game-console-style savegame file, in a binary format. After some very basic hexediting with vim and :%!xxd (and :%!xxd -r before returning it) it became fairly obvious where the username/profile names were kept, along with some basic things like current money balance, and progress on certain levels.

I eventually learned that no changes I made would work, because the game would think the file is corrupt. The first four bytes are a checksum, and I spent about 10 hours total researching the checksum.

I started by estimating how many bytes are in the checked payload. The sum is 4 bytes, and the file is always 15,444 bytes, so I started with the assumption that the checked data is everything else but the payload, including the 0x0a at the end.

I tried writing some little functions in python, and I even found an implementation of Fletcher's checksum for python, but none of those worked. I even noted that the money of a player is stored in little-endian format, so I spent a bunch of time reformatting the output of every type of algo I tried. I don't really know how little-endian works, other than "1234 5678" would end up as "3412 7856" or maybe "7856 3412". sigh

Since I couldn't guess the checksum, I then decided to investigate the binary file, named srb.exe. I've heard of Ghidra, and even had come across an article recently about using it in wine. I probably found it on Ycombinator's Hacker News.

I realized that ghidra would be in Kali Linux, which is close enough to Devuan that I just needed to manually install the kali keyring dpkg, and then add the right repository and then apt-get install ghidra: Seamless!

I got ghidra and gdb running, and was able to sort of hook up ghidra to the remote gdb thing running wine running srb.exe. I found a loose spot in the binary where I could put a stub for the getpid-linux-i386 function, offset 0x401042. I couldn't get breakpoints to work, so I gave up on the debugger. I spent hours in the codebrowser, and I poked around the few ReadFile and WriteFile kernel calls (which is the first time in my life that I've looked up Windows programming references, excluding powershell which isn't the same). Ghidra is really cool! I could see how somebody who knows what he's doing could do so much more with it. It almost made me appreciate having to install java on my system for it.

I gave ollydbg a try, after undoing the minor damage its dependent package kali-defaults wreaked on my system files. I didn't understand ollydbg as much as I did ghidra (which was still only like a 2% understanding for that one), and also the game would always crash when I ran it in the ollydbg debugger.

As a side note, I spent a lot of time changing in winecfg to emulate a virtual desktop, so I could have the game up while hacking the savegame file. The game itself has a handy option to reload the savegame file, so I could make any changes, replace "Profile 1.sav" (hardcoded, which is easy to see in the binary), and tell it to reload. Upon which, of course, it would say the file was corrupted and it would have to delete it. The game, being a flying sim, struggled with when my mouse hit the edge of my real screen, because I must have forgotten to bind the mouse to the virtual-desktop-bound. So in between hacking the savegame file, I'd play a little, for which I needed full screen again. I'm guessing there's a winetricks command that simplifies that, but whatever.

So, after enjoying reading decompiled assembly, which would just name variables like "puVar12" and "param_3_00", and renaming a few of those, and still not finding what I was looking for, I switched back to researching the checksums.

Of course I have copies of the one 15kb-sized file, at various points in my progress of the gameplay. I was wondering if I just needed to brute-force the stuff. I felt it was going to be a crc32, because isn't that the most basic checksum (command cksum) around?

I learned about a sourceforge-hosted project (which used to be cool), and since the project was from the same timeframe as when SF was cool, there was a chance: CRC RevEng. I spent maybe an hour investigating this tool, but I think I was missing some key info, like a "polynomial," as well as I think it couldn't handle the 15kb payload. All the samples in the example were given on the command line as short string literals and not filenames. I briefly checked if the bashism < <( cat "Profile 1.sav") would work. It did not.

So I found a few other tools in a discussion on the Reverse Engineering Stack Exchange. I looked at hashdb but that focuses on malware checksums. So the second tool, delsum seemed very interesting. I don't know if I'd be able to compile rust, but thankfully a binary release exists.

And there this story should end. (Because I was successful, with delsum.) Tune in next time for more information about hexediting the savegame, and the checksum involved.

Comments