Matt Stevenson

· 10 min read

Simple Beginnings

Super Ultra Hackerman 3000.

Random memories from when I was a kid keep popping into my head lately. Must be an age thing.

This one’s about messing with Xbox 360 saves. I’d have been 11 or 12. Looking back, it’s also where I picked up a surprising amount of what I do for a living now, without having a clue I was learning any of it.

I loved that console. By the end of that generation my Microsoft account reckoned I’d owned six of them, which sounds mad until you remember the Red Ring of Death was a thing. Me and my dad did the towel trick more than once. If you’ve never heard of it, you wrapped a dead Xbox in a towel, let it basically cook itself, and hoped whatever had come loose inside would stick back down long enough to get a few more days out of it. Stupid idea. Worked sometimes, though.

Three red quadrants and one dark, around a perfectly happy green button. Every 360 owner knew exactly what that meant.

That was the generation that got me properly into games.

I remember bringing Call of Duty 4: Modern Warfare home after begging my parents in Abbeycentre. I definitely shouldn’t have been playing it at that age, but parents were a bit more lenient back then (or just had no idea what was in it), and I turned out fine.

Mostly.

Then Call of Duty: World at War came out in 2008 and that was it for me. I was obsessed with anything WWII at the time. Saving Private Ryan, documentaries, the lot. A Call of Duty set in WWII was more or less made with me in mind.

At school a few of us used to compare how far we’d got in the campaign. Then one day the guy furthest ahead said he’d finished it and there was a zombies mode at the end.

Nobody believed him. Turns out he was telling the truth.

Red chalk tallies, round by round. By the time they turned into numbers, things were getting serious.

Zombies felt like something you weren’t supposed to find. It was dark, properly difficult and nothing like the rest of the game, and before long it was all anybody talked about. We played it most nights until somebody’s parents pulled the plug and sent them to bed. Fair enough, there was school in the morning.

Infinite ammo

I was already fairly handy on a computer for a kid. But I think this was the first time I looked at a game and wondered if I could make it do stuff it wasn’t meant to.

The first tutorial I followed wasn’t anything fancy. It was infinite ammo for the campaign.

Copy the save onto a USB stick, plug it into the family laptop, pull savegame.svg out, open it in a hex editor. Then go hunting for this:

player_sustainAmmo 1

That was it. A single 1. Turn it on and the game stops taking bullets off you when you shoot. Infinite ammo was just a switch.

Put the save back on the Xbox, load it up, and… it worked. I couldn’t believe it.

And player_sustainAmmo wasn’t something I’d added. It was one of the game’s own developer variables (dvars), a setting Treyarch had built in for themselves, and the save just had it written down. I wasn’t really hacking in infinite ammo. I’d found a switch that was already there and left it on.

savegame.svgplayer_sustainAmmo 1
→
every time you fireif sustainAmmo is off:
  take a bullet
The behaviour was already in the game. The save just told it which way the switch was set.

What I was actually looking at

I had no clue what I was doing at the time, which is kind of the best part looking back.

A hex editor shows you a file as raw bytes. Hex on one side, and whatever those bytes are as text on the other. So player_sustainAmmo 1 looked something like this:

70p6Cl61a79y65e72r5F_73s75u73s74t61a69i6En41A6Dm6Dm6Fo20␠311
Twenty bytes. The one I cared about is the last: 31, the character "1".

Every pair is one byte. 70 is a p, 31 is the character 1. The editor was showing me the same data twice and I thought the numbers on the left were some sort of secret code.

Doing it myself

The infinite ammo switch was somebody else’s find, though. I’d just followed the steps. What I really wanted was to find something on my own.

So I went after the ammo counter itself. Note how much ammo I had, say 36, save, and pull the save onto the laptop. 36 in hex is 24 (I had to look that up online), so I’d search the file for 24. Loads of hits, obviously. Then back on the Xbox, fire a few rounds until I was down to 31, save again, look up 31 (1F) and search the new file for that.

Most of those 24s were still sitting exactly where they’d been. One of them had turned into a 1F. That was it. That was the ammo.

save 1 · ammo 36001A240007243C0024
save 2 · ammo 31001A2400071F3C0024
24 = 361F = 31every 24 that didn't change was a red herring
Two saves, one difference. The bytes around it are made up; the method is the real bit.

From there it should have been easy. Look up what 999999 is in hex (0F 42 3F), type it over the top, put the save back on the Xbox and load in.

It wasn’t. The number I typed in wasn’t always the number I got back, and every so often the save just wouldn’t load at all. It took a fair few goes, and a fair few trips back to the laptop, before an edit actually stuck. But when it did, I hadn’t followed anyone’s tutorial. I’d found it myself, and I’ve been chasing that feeling ever since.

where the ammo isroombiggest value
in memory, as an int4 bytes2,147,483,647 · 7F FF FF FF
sent to your HUD, as a short2 bytes32,767 · 7F FF
2 bytes, maxed out7FFF= 32,767
add one8000= −32,768
999999, squeezed0F423F= 16,959
Stored as an int, sent as a short. Go one past 32,767 and it wraps to the most negative number there is; send 999999 and only its last two bytes make it.
big-endian0F423F= 999,999
little-endian3F420F= 999,999
read the wrong way3F420F= 4,145,679
The same number, two byte orders. Mix them up and 999,999 quietly becomes four million.

None of that was going through my head at 12. What I did pick up without knowing it was the loop. Change something in the file, load the game, see what happens, go back and change it again when it inevitably didn’t work.

edit the saveload the gamesee what happenswork out why
Round and round. Every bug I've fixed since has gone through this loop.

I’d call that debugging now. At the time I just thought I was getting one over on Treyarch.

Modded saves

Then I found the forums, and people posting their own custom World at War saves. These were a different level. Someone had worked out that the game would read config strings out of a save and run commands it already knew about, so you could chain them together:

bind BUTTON_BACK vstr mod2
mod2 = god; give ray_gun

bind hooks a button up to something, vstr runs another string by name, and the game already had commands for god mode, noclip and giving yourself guns. Stack enough of those together and you’ve got a mod menu. No new code anywhere, just a load of strings and button bindings set up carefully enough to feel like a menu.

Back button→bind→vstr mod2→god; give ray_gun→god modeRay Gun
One button press, two levels of indirection, two of the game's own commands.

Didn’t matter to me how it worked. It was magic. I’d jump into a zombies lobby, play it straight for a few rounds, then hit Back and pull out a Ray Gun or walk through a wall. Keeping a straight face was the hard part.

The one annoying part was getting the Xbox to actually load the thing. Once you’d edited a save the console knew something was up, so it had to be rehashed and resigned before it’d take it. I did it in the same order every single time:

edit→rehash→resign→USB→Xbox

rehashThe save carried fingerprints of its own contents. Change a byte and they no longer match, so they had to be worked out again.

resignThen the package's signature had to be redone, so the console would accept it as genuine.

forget oneThe console refuses the save, and it's back to the laptop.

Same order, every single time.

Looking back

It’s funny how much was going on in there when I think about it now. The save had a proper format, values lived at fixed spots you could hunt down, and the console wouldn’t touch a file unless its hash and signature checked out. I was doing all of it to get infinite ammo in a game I shouldn’t have been playing in the first place.

What I was doingWhat it's called now
The towel trickA hotfix that hides the root cause
Flipping player_sustainAmmoFeature flags and config
Reading hex next to textBinary formats and character encoding
Hunting the ammo with two savesSearch, diffing and elimination
Numbers that came back wrongData types, overflow and byte order
Edit, load, look, repeatThe debugging feedback loop
Chaining bind and vstrIndirection and scripting
Rehash, then resignHashing and digital signatures
Nobody told me any of these words. I just kept poking at a save file.

Nearly twenty years later I ended up hex editing a Borderlands save, and it felt exactly the same. The tools are better and I know a bit more about what I’m looking at, but it’s the same buzz.

I write software for a living now, and I love pretty much anything to do with it. I can’t say for sure this is where that started. But whenever I think about how I got into it all, a USB stick, the family laptop and a hex editor are some of the first things that come to mind.

Good memory, anyway. Sorry, Treyarch.