Laughter is the Best Medicine

Iron Sword ※ Cracking Videogame Passwords S1e13 (Wizards & Warriors II)

Passwords. Hello again! We are back after a brief
unscheduled mid-season break. One would think, that live-streaming the
process of making a video – would make it easier
to make a video, but no,
it’s the opposite: it only threw me
off the track. Iron Sword is the sequel to
one of my favorite NES games: Wizards & Warriors. While the original arcade classic
did not have passwords; only a high-score list, the sequel does,
and in fact, it kicks you into
the password screen – almost as soon as
you start the game. Now as we established
in the making-of video, only sixteen different
letters are accepted. This list is almost the
same as in Solar Jetman, which we covered in
a previous episode. Each of these letters is
actually a hexadecimal digit – that just looks like a letter. For example, this password,
“GNHMNBKZBGTG”, corresponds to the hexadecimal
number 2837805F02C2. These digits, called nibbles, are then divided into groups
of two digits each, forming six bytes:
Bytes 0 through 5. Now the data in these
bytes is encrypted, as it has been in
almost every game – that we have covered so far. In Iron Sword, the encryption
looks like this. Basically, a ton of
xorring happening around. Nothing too exciting
or worth memorizing. Let’s see how to decrypt
this example password. First, bytes 0 and 3 are
both xorred with byte5. This produces values
EA and 9D respectively. Then, all five bytes are xorred
using a hardcoded table – that we will study later. This produces values
D7, FC, 7A, DB and 0B. Then, level number is extracted
from the xor of bytes 4, 0 and 1. If the value is greater than 3E,
the password is rejected. Here, the value is 20,
which is OK. Then, bytes 2 and 3 are xorred – with values from two
other lookup tables, using the level number as a key. Boy, they really did not want
anyone to find out by accident – how the password system works. Using hardcoded lookup tables
is an efficient way to do that. Finally, a checksum is calculated – from the xor of the low nibbles
of bytes 0, 1, 2, and 3, and the high nibbles
of bytes 0 and 1. The checksum must be zero. Which it is. The game uses the low
nibble of byte 3 – to store the intermediate
result for the checksum, and it becomes zero
in the process. As a product, we get these bytes:
D7, FC, FC and F0. We can ignore bytes 4 and 5, because byte 5 was only
used for encryption, and byte 4 only produced
the level number, which we already have. The rest of the bytes contain
various things in various bits: The weapon level,
the shield level, the armor level, the number of remaining uses
for a total of seven spells, the number of extra lives,
the number of keys, and an unknown two-bit bitmask. The values for the items
go like this, as indicated in the
table on the screen. There is nothing too
exciting about this table. There are some discrepancies – between how the values
are stored in the password – and how they are represented
in the game RAM, but it is pretty straightforward. There is one
“unknown” variable, which I have not figured
out what it does. It can have four
different values, but judging from
the disassembly. but it looks like
a two-bit bitmask. So let’s move on
to the encryption now. We already touched this a bit
when doing the decryption, but I think it warrants
some special study. First, the game chooses
an encryption key. For the purposes of
producing valid passwords, technically any arbitrary
byte would work, but the game generates it – by xorring the five
data bytes together. Actually, this is not
the first step; it’s done pretty
late in the process, but I wanted to get it out
from the way first. [coughs] Anyway, it begins from
calculating a four-bit checksum. The checksum is
placed in byte 3, which had its bottom part
zero, if you recall. Byte 4 is calculated by xorring
together the level number, and the first two bytes,
which contain stuff. Then bytes 2 and 3 are
xorred using tables, and all bytes are xorred
using another table. Then bytes 0 and 3 are xorred
with the encryption key, which is stored in byte 5. So about those tables: First, we have the
five-byte table. It contains the values
3D, CB, FA, 46, and 09. Here is the relevant
part of the data – from the disassembly
of the ROM. The table begins
at address FB8E. Can you find it? Here, let me make
it a bit bigger. There we go. The table stands out
nicely there. It’s a section of data
in the middle of some code. Just five bytes. Then we have
table1 and table2. These are actually stored in
an interleaved format in the ROM, such that both tables
begin from the same address, one byte apart, and each successive element
is two bytes away from the next. Such format is
common in NES games – because of performance reasons. It’s basically a single
table of byte pairs. So, the table begins
at address FB6A. Let’s see if we can
find it in the disassembly. Where is FB6A? FB6A is up here… But something is wrong. This is code, not data. Surely I misread something? No, the starting address
definitely is FB6A. The data really is located here. They just chose a random
part of the code, and reused that code as data. Designwise, this is
the craziest thing – that I have seen
NES games do, and I was totally flabbergasted
when I found this out. I streamed it live; you can actually
find it on my channel. This data not only repurposes
program code as data, but it even overlaps
two other data arrays. That’s right, the first xorring table
that we studied – is actually part of the
second and third table as well. In the bottom of the screen
there is another data table – that is used for
some unknown purpose, and that table is also a part
of this encryption table. This kind of design would
be totally fine – if it was used for
something insignificant, like the random number
generator in the game, but this is used as a part
of the user interface: It is used to encrypt
the passwords of the game. If they decided later to release
another revision of the game, as many companies do, they could not
change this code, because changing the code
would invalidate – all passwords that players
have written down. And that makes this the
wonkiest password design – that I have seen so far, even beating Bomberman
and Solar Jetman – with their potential for arbitrary code execution
exploits. So naturally I also
wrote an encoder-decoder, or CODEC, for this password system as well. This was done in PHP, because it happens to be
a scripting language – that I am quite fluent with. Again, you can watch
the livestream – to find out how I approached
reverse engineering this scheme. I am Bisqwit. In the next episode we will study
a game with a password scheme – that is so unorthodox, that it is difficult to
even write them down. See you then!

59 thoughts on “Iron Sword ※ Cracking Videogame Passwords S1e13 (Wizards & Warriors II)

  1. The assembler function from the game code shown at the top of screen at 5:39 is wastefully written. Who can correctly identify the three instructions that accomplish absolutely nothing?

  2. Ah… It's been a while.

    This… Continues my horror and fascination with the absolutely bizarre ways these passwords function. XD

    This one seems to have a larger pool of 'invalid' data than most, but again, large chunks of the password still seem to map in a surprisingly direct manner onto the data the game is actually saving…

    Wonder of wonders huh.

    I suppose a password system has a bunch of design constraints.
    -It has to be reasonably secure against random guesses and brute force attacks.
    -It has to store all the data the game needs to restore itself to a reasonable state
    -it has to be as brief as possible.

    That last point follows from the fact that people have to write down these codes and enter them into a password entry system through the tedious method of using a 4 button gamepad.

    So… That rules out storing 2 kilobytes of save data…

    And in fact, given that the longest passwords I've ever recalled personally seeing are about 20 characters long, we can infer an absolute upper bound of 140 bits of storage, with the vast majority of systems being 70 bits or less, since actual use of full 128 character Ascii codes is very rare, and base 64 or hexadecimal seems to be more common.

    Of course, perhaps there ARE codes longer than 20 characters, but if there are…
    Well, 20 characters is already pretty tedious.

    Thinking about it, trying to encode the equivalent of a save file for a game's state in less than 70 bits is quite a feat in and of itself for a nontrivial game.
    Of course, a lot of NES games took a shortcut by saving only part of the state of the game…
    But still…
    SNES and Mega Drive games must be even worse, since the average complexity is higher. (though password systems are rarer I guess.)

    Let me think, if you had to store a game on the order of complexity of A link to the Past…

    You've got to deal with the presence or absence of something like 20 regular items (this is off memory, so it could be somewhat wrong), the presence or absence of 4 bottles, and potentially what their content might be, (though to my knowledge there's only 5 things that can be in a bottle.), the heart pieces and containers collected (you need to know not just how many, but also which ones were collected). Since there are 3 light world dungeons, and 7 dark world ones, and you can finish the dungeon without explicitly collecting the heart, we've got 10 full hearts, and 7×4 heart pieces.
    The dungeon itself would have to store a flag for whether it's been completed, and you'd need at least 4 more for stuff to do with hyrule castle.
    Then there's a few random state items related to getting to various dungeons, such as the monkey for the first dark world one, or the boss in Blind's hideout.
    Then there's items that have 'levels', but probably also still require that you track the individual levels, like the titan's mitt, the swords, the shields, the armour upgrades, and the magic upgrade. The armour upgrade and one of the shields is a dungeon item, but you can lose your shield and rebuy it, as well as find a second level shield in the world, so that's even more to keep track of. There's the rupees carried, chests opened, magic level, maximum and actual number of bombs and arrows…
    So, we have about 58 bits for basic items and heart pieces.
    the bottles could be stored as 3 bits each which would account both for whether you have the given bottle, and what it contains. (12 bits)
    Dungeon completion states would be about 10 bits for main dungeons.
    At least 4 for hyrule castle, and one for whether you've opened ganon's tower.
    (15 bits – 85 so far)
    storing up to 999 rupees requires 10 bits. Bombs and arrows top out at roughly 70 each, which means at least 7 bits for storing how many are required, and at a bare minimum, the 'maximum' has to account for at least how many unit of 5 upgrades there are from the base amount. which seems to be about 40 over the base, or 8 upgrades. (that makes 3 bits for each)
    This would be another 30 bits (115 so far)
    Then there's silver arrows, the upgraded boomerang, the 2 upgraded armour types, the gloves, magic upgrade and swords. Since you'd have to track where they came from too, you'd need one bit each. That's 10 more bits (125 so far)
    The mushroom, and whether the witch will sell you certain things also needs to be tracked, so that's at least 2 more bits. (127 so far)
    Shields not only require knowing which shield you have (none or one of 3 types), but also where you got various shields from that exist in the world. Not sure how many that is, but that's at least 2 bits for the shield type, and probably at least 3 or 4 bits for various locations ingame that may have contained a shield. (6 bits, 133 so far)
    You'd have to keep track of whether you've got an object/character following you.
    This can include Zelda, the thief in the forest, the guy in the desert, the monkey, the sealed chest, the old man in the mountains, the girl in blind's dungeon, and the superbomb (if I'm not forgetting anyone), Since you'd also need 'nothing' to be a possible value, that means at least 4 bits required. (137 so far)

    Then there's chests that contain things but can only be opened once. Any with an item are already accounted for, but those that contain supplies (bombs, arrows, hearts, rupees, fairies, etc) would need to be tracked.
    Can't say how many of these there are, but it's a few. Probably 30-40 if not more.
    So let's say 50.
    Same with bombable walls, since once you bomb them they stay open. That could easily be as many, so now you've got another 100 bits or so. (237 so far)

    Round up for anything random I may have forgotten and a game like that would be storing at least 250 bits.
    Using a typical 64 character encoding, you'd need a minimum of a 42 character password to store something like that.
    And that's without any checksums or other values hidden in the code to improve 'security'.
    A hex encoding bumps that up to nearly 63 characters…

    Starts to get pretty unreasonable at that kind of length.
    Of course, it's a moot point when you've got a way of saving data (then again, when your save ram is 1-2 kilobits, this is still pretty tight. – if you have 3 save files of 250 bits, and concerns about data integrity lead you to store your data twice, which quite a few games evidently seem to do with SRAM based saves – then you're quickly going to fill up a 2 kilobit SRAM…), but it does suggest why these codes are so frugal with their encoding.

    Weird stuff to think about in some ways…

  3. Using the code as password encrypt/ decrypt data may have protected against certain piracy/ bootleg measures by invalidating password usage.

  4. Am I the only one subscribing and watching all these videoes, eventhough he could be talking Mandarin for all it mattered. I don't understand a thing, but I love his voice 🙂 My new favorite word is : Two bit bitmask

  5. 0:46 – So are A, C, E, and F valid or not? 😕
    1:27 – Xord and Xorcory. Techno-fantasy game idea? 🤔 (Xords and Xandals made me think of the arena in Hillsfar .)

  6. It confused me, at first… but, after my brain caught up, I appreciated the sharp-and-sudden start of this video. It kind of mirrors what you said about the game, itself!

  7. If they use code as part of the lookup table, then can it still be considered a lookup table? Or maybe some kind of self-referring algorithm? That is some kind of demoscene wizardry.

  8. I hope one day can understand everything in one of your vídeos! Im working hard to make it happen!

  9. "a password scheme that is so un-orthodox that is difficult to even write them down…"
    me: Captain Tsubasa for the Famicom comes to mind.

  10. Hiya. I wrote the game (and Solar Jetman too). Congratulations on your reverse engineering, particularly given that I lost the source about 20 years ago. I wouldn't fret about passwords becoming incompatible if a second Rom version comes out. It was considered vanishingly unlikely that anyone would buy two copies of a game, and yet more unlikely that they would care if their passwords didn't retain compatibility.

    Finally (and please forgive me if you make this point elsewhere), in later NES games vowels were forbidden in passwords in case anyone accidentally saw a swear word. I confess that I made that suggestion to them at a developer conference because they were promoting the idea of an encrypted dictionary of sweary stuff to check against, and this seemed a bit silly to me.

  11. Hey @bisqwit
    Remeber those old pc booter games?
    They were rather complex

    Skipping the "booting" part, do you think you can do somethink like this nowadays?

  12. Hey, Bisqwit , I thought you may get a few laughs out of this video, I know I did.  It's a short documentary on the REAL Wild West, hosted by Gary Cooper, I believe his name is.  Funny at various parts, for instance, the Indians called the railroad, "Plenty wagon, no horse!"   According to the video the Wild West only existed for about 40 years, contrary to many of the urban legends.

Leave a Reply

Your email address will not be published. Required fields are marked *