Under the microscope: Medal of Honor: Underground (PlayStation)
Mounting a meet-in-the-middle attack against a PlayStation game's passcode obfuscation system
If you go to the Options screen in Medal of Honor: Underground, the 2000 game from DreamWorks Interactive for PlayStation, you’ll find a Passwords item. Select it, and you’ll be presented with a skeuomorphic entry form:
ASCII versions of the letters you type can be found in memory at address 800845f4 (in the NTSC-U version, at least). That location is continually being read by the function at 80049df8, which has some logic that looks like this in Ghidra’s decompiler:
That 0x4c11db7 constant betrays what this function’s purpose is: it’s the CRC-32 polynomial. So the game is computing a checksum based on the password you enter.
Why do this? To keep the list of valid passwords secret. The first Medal of Honor game didn’t do this, which means you can just read its cheat codes out of the game game data:
Hmm, where have I seen this kind of thing before? Ah, yes: Ecco the Dolphin: Defender of the Future used the same scheme. In that article I described using brute force enumeration to find checksums for cheat effects.
Ecco used six-letter cheat strings, so checking every possible arrangement of letters was feasible. This game uses 10-letter cheat strings, so it’s not – 26^10 (141 trillion) is way too many checks to do.
Let’s try a different approach. CRCs are calculated one byte at a time. For each byte, the update logic looks like this:

CRC_TABLE can be found hereThis operation can be reversed. Since the right shift operation clears the top byte, any bits that are set in that byte come from the XOR operation. Because there are only 256 possible top bytes (and all bytes are represented in the table), we can map each of them to the CRC_TABLE index that produces them. The reverse operation then looks like this:
With both the forward and reverse directions implemented, we can use a meet-in-the-middle attack. First, we’ll pre-calculate all 26^5 possible 5-character prefixes and their checksums:
And then for all 26^5 possible 5-character suffixes, we’ll run our reverse operation five times on each of the target checksums:
If we wind up with a value that goes with one of the prefixes, we’ve found a checksum collision:
This approach generates passwords with values that match these targets, but they’re not the ones you’ll find on the cheat sites. There are 26^10 strings, but only 2^32 checksums. So each checksum is associated with around 32,000 different input strings.
For example, the cheat sites have RICOCHET for checksum target 0xe6fda924. But the code above gives RHHYFAAAKT. The game happily accepts either of them.
The function at 8004c260 is comparing the checksum for your password to the ones in the table at 80084608. The table has 15 different entries. I looked at various cheat sites and found that 11 of the targets are known, which means I’ve got four novel cheat effects:
XFTBHAAATT: This enables the “Swell Multiplayer” effect. Players drop items that alter gameplay when they’re defeated.
UMECWAAAGH: This enables “No Reload Mode.”
UYGDDAAAJU: This enables “Civil War Mode.” Enemies can damage each other during gameplay.
GTUZZAAARF: This enables “Unlimited Ammo.”
Entering these sets bits in the 32-bit field at 80039d0c. That field is read by the Secret Codes screen, which allows you to enable their associated effects:
The full script is available on GitHub.
Outro
Thanks for reading Rings of Saturn. I’ll be back with more retro game reverse engineering articles like this soon – subscribe to get the next one as soon as it’s available.
In the meantime, check out the archive for many more explorations like this one.










