Hello everyone! Let’s see if the sound works. So, the topic of today’s video… It has been a long time since the last episode
for the Cracking Videogame Passwords series. And I was planning to make the episode 13… Does this sound work,
can you hear it by the way? Good time to check it.
Tell me if you can hear it. For a long time, I was planning to
make episode 13 into a livestream. Thank you for telling me
that the sound works! I planned to make it a livestream,
and things have happened, and… Time has passed, but now
is a good time to make it. And the game I am going
to crack the passwords for, let’s see, it’s going
to be Iron Sword. Wizards and Warriors II. I don’t know how many of
you have played it in the past, Can I actually hear the sound? It’s rather quiet. Let’s see.
Can I do something about that. Hmm, playback… Okay, that should be
a little bit better. But not too loud. So this is a game with
quite short passwords. It’s twelve letters, and the set of letters
is quite short as well. I think this is… hold on.
Nine, nine, and eight… That’s umm,
did I calculate wrong? Yeah, it’s 26 letters.
Indeed, from A to Z. It actually uses all the letters, but obviously not all of them
are going to be meaningful. Let’s see how the game
actually works. Let’s take a sample
password of this game. To clarify, I have never
researched this game before. Now I pretty much just
have to die in the game, to get a default password. The game sounds are too loud?
Is this better? The game sounds should be
less high volume now. What I have to do here
is pretty much die, until I get the a password, so I see
how normal passwords look like. Or rather, the empty password.
Not default password. Can I actually die from
falling from heights? Not too easily… Just have to die,
it shouldn’t be too difficult… Is there turbo? Let me check if there is
a turbo button somewhere. No no, that doesn’t work… No! What happened? Okay that’s not too good. I hate the fact that- Oh yeah the video camera
seems to be stopped for some reason. Can I do something about that? Change that… Can I? Okay now it should work again. So let’s make it… Oh yeah. So the video camera works again. But to go on, I have to die here. So… Does anyone actually know
the quickest way to die in this game? I would think the quickest
way would be to fall from heights… But it does not seem to work like that. I hoped to use turbo here, but turbo does not work.
I pressed tab, but nothing happens. So just wait here. I guess the game will run
on the background? Let’s do some research
in the mean time. The game sounds
may still be too high, because I can’t hear
myself think. So let’s see. Iron Sword…
Passwords. No no no not maps,
but search. I’m not going to just use
someone’s research on passwords, but I want to see what kind of
data possibly is there for them. These are some passwords here. So in the passwords we have
stage, some equipment, the default password seems
to be quite simple, which suggests that there isn’t
much encryption going on. What is happening?
Why is Kuros not dying? Let’s try this. This should work better. Die, please. So anyway. We have
starting level, some equipment, and some kind of checksumming
probably, or not. Okay. Now let’s make
a savestate just in case. What happens if I don’t continue? If I don’t continue,
I don’t get a password. Too bad. Okay…?
Hmm… He has three lives, so… Do I have to do this three times? Well I don’t really need to do that. Because I have the
information right here. So now the next thing
would be… I could do it this way.
Just take these passwords, maybe these ones,
and then analyze- which letters do they use. Because the password
alphabet was 26 letters. And my guess is it doesn’t
use all 26 letters. It just uses 16.
That is my theory anyway. Let me do that. Actually don’t need to
make it a PHP file, just a text file is enough. So append these
all to a single text file… And then just delete
all the stuff from there, and…! Let’s delete newlines from that. And then, put all the letters
on distinct lines. See if that works. No, it doesn’t,
because I made a typo somewhere… Where, actually? Because I should have done that. Okay! So in the passwords
these letters are used. How many are those? They are… 16 letters,
just as I guessed. So there are sixteen different letters. Which I make those
Cracking Passwords videos, I use actually LibreOffice. The videos are basically
LibreOffice slides, like a PowerPoint,
but just a free tool. So I’m going to use my
Swords & Serpents slides as a background,
and just edit it a little bit. Wizards & Warriors II… I worry about the color scheme later. So we have 16 different letters…
Just that much is enough. And the letters are: Can I sort those? Sort them. It looks very
much like in Solar Jetman. All the consonants basically. So, B D F G, H J K L, M N P Q, R S…
Something is missing there. Let’s see. Ahmm… BDGH, JKLM, NPQR, NPQR, was it? NPQR… And, uh TWXZ. T, W, X, and Z. Was it correct now? JKLM… No, it wasn’t, because
something was there- that shouldn’t be.
F is not supposed to be there. Was it this? Kind of difficult to swap
between two windows. That should be the alphabet
that is used in this game. So immediately I could use
the same mechanism, that I used for… Let’s see
if I can find the right window. It should be maybe… No? My hotkeys are failing me. Ok I can discard that,
because I have it over there. Can I use this tool? Clever, and wizwar2. Actually that’s not
the tool that I want. I want to check this. So can I find BDGH?
No I can’t. This is just a hex editor. Actually not even a hex editor,
it’s just Joe, the same editor that I use
always, but I’m using, um… Ok hold on. So yeah, hex editor, and… If someone wants to be
a moderator there, who has a name that
I can recognize, also, English only. So if you write in Russian,
I’m just going to delete your messages. So, anyway… What was I saying? Yeah, maybe there are
moderators needed, so if someone wants to volunteer,
please be a reputable person… and I could check and think about that. So what I was actually doing, I was going to take a little look
inside the game ROM, to see if I can find
these BDGH letters inside the ROM. No no no no, these are going
little too quickly… I’m having trouble doing… “Remove moderator”, no So Ricardo can’t moderate, let’s see who else… Uhm. So what I was doing here. I was trying to find those letters. They are probably offseted somehow… Let’s work on the assumption
that “A” is like, 0 or 1. Let’s work by zero first. Actually I don’t need to assume,
because I can just check these tables… Assuming the game¸ yeah
it doesn’t actually work, because the game
uses VRAM, not VROM. So that’s a no-go. Can I find the translation
table, somewhere? Those are graphics,
so that’s a no-go… Of course if I could
find the font there, that would be helpful, but no. That may be some kind of data… I’m looking at these patterns
to recognize something… And, uh… That kind of looks like text,
but… no. Do I have a search tool
in this program? I actually don’t. Okay I had another tool. Which I used in the Gremlins video. How does it work and where is it? I think it was called “multigrep”. Oh yeah. So it’s actually in this path.
How does it work? It uses, the game ROM comes in stdin, and the parameter is going to be “BDGHJKLM”. So let’s see if I can find it there. So we found it in one position. It’s in position ‘that much’. Which is in hexadecimal, ‘that much’. Can I find it in the viewer? 1FB6A. 1FB6A. 1FB6A. 1FB6A. 1FB6A is… 1FB… It’s quite close to the end. I didn’t actually check the offset. What was the character set offset? The offset was… This much. So I actually need to add, I think… It should be like C, and that. Ohh… Ok that wasn’t what I was looking for. Because this is obviously just the… The layout for the screen
that is going to render, not the lookup table. Just checking.
Never mind that. The third approach that I usually… Yeah I actually use PHP quite
often on the commandline. It’s not a bad tool. The third option that I have
actually used- for the majority of those
Cracking Videogame Passwords videos, the operating system is Linux by the way, is use a disassembler. I have created this disassembler
called, uh… Called NESCOM. Free NES assembler. Even though the package
says “assembler”, and a linker and tools like that, it actually contains a disassembler,
that works really well. That I don’t really advertise that much, because it’s rather
complicated to use. But if I feed it the Wizards & Warriors 2
NES ROM, I get a pretty nice listing. So this, assuming everything works right,
which it doesn’t necessarily do… Because this game uses mapper 7. Well that should work? But let’s see. It always involves some kind
of manual processing. I have to fill some pointer
offsets myself. Let’s use the Swords & Serpents
ROM as a model. So what was the address
for that, it was 3… It should be… It starts from there. And NMI points to… And reset is… And IRQ is… Let’s try that. Did I do the parameters
in the right order? I used the multigrep tool, because the character offset
may be changed. Hold on, let me illustrate
and explain what I mean by that. Normally in ASCII, which is the basis for basically
every character set that is used in PCs, the characters work like this. You may have seen
these tables somewhere. Basically all characters have
a number corresponding to them. For example, “A” is always 65,
or in hexadecimal it is 41. And “B” and so on come after that. And “P” is 80 and so on, but in video games the font
doesn’t necessarily go that way. The characters can be anywhere. For example, “A” could be 160,
240, zero, or anything. If you just used the grep tool,
it assumes that when you type “A”, it really means this number 65. But when you are looking inside
game ROMs for NES etc., you cannot make the assumption. You need a tool that can actually
deal with character sets- that are shifted and offseted. That’s what multigrep does. And I actually used it in…
(searching) Gremlins, Bisqwit… Here, this video, Gremlins 2 video, I used it here, for the first time. I think I created it for this video.
No I didn’t. But I used it here. So if you want to know more,
check that video. But anyway, I was doing disassembly. So I’m going to spend some time
researching how this ROM works. Actually “A” is indeed 65.
64 is the “@” symbol. Let’s see if I can find anything relevant
here. This may take some time! One thing, that would
expediate a little bit, is to look up some prior research. I did check a little bit beforehand, and I know that people have been
hacking this game before. And on Romhacking.net there is— Not this game, but…
Can I find it by name “Iron Sword”? Iron Sword…
Romhacking.net… Hmm… Let’s just use the site directly.
Find… There should be a document. That doesn’t help because it takes
me back to Google search. Games. Find.
Hope this doesn’t take to Google. No it doesn’t. Okay, so there actually is not. There is no documentation
about this game. That actually was a dead end. RAM map. Let’s see again. Final Fantasy, Secret of Evermore, no. Maybe, no, one actually has studied this game. Wizards & Warriors II, RAM map. Nope. So that is a no-go. So I just have to analyze it myself. Can I actually find… No this game
probably does not use EOR. Because the encryption was so simple,
so it probably does not use EOR. So I may have to find something
that changes mappings… So, hmm. This should actually follow it…
But it does not. So I have to check and…
Does that work? Well, I do have a favorite
programming language. If you have watched my videos, you probably know already
what that language could be. And hint, it is not assembler. So this is basically the reset code. It does something
with the sound registers… Blanks all them out. So this is the reset code. That looks like code,
so I am going to enable that. Hmm-mm. But at this point it’s
going to take a long time, unless I get some kind of tool, with which to investigate
the ROM contents. And that would certainly be
easier to do in Windows – than in Linux, because, because to be honest,
Linux versions of NES emulators are crap. So I may actually need to do
some of that in Windows. Which really sucks, because
I have streaming set up in Linux… Hmmmmh. Hold on. I have to think. Think a little bit. Because I need some kind of tools – to see which memory regions
are being accessed when I do things. I don’t think Mednafen has…
Does it even support NES? It actually does. But I am not seeing
any kind of GUI there. I mean menus and stuff. Hold on. No…? F1? F1 does something. But I don’t see anything
debugging related. There is one more possibility. Because: A couple of months ago
I tested out Wine. I was surprised really
how well it works nowadays. I may be able to use Wine, in Linux. To… Hmm, bisqwit nes… I don’t have it here, so let’s see. Windows. Let’s download that. Windows-32 binary… Direct link… And download please. Extract that. And see whether it works. Wine. Yeah, this could work. Let’s try that again. So will it work?
I think it might. Oh yeah. So let’s just set my settings here… So I can actually do something useful. P, A, D, close.
Allow that. Change video settings…
Resize this a little bit… Like that much. And change hotkeys… Because that hotkey is doing
things that I don’t want it to do. That should be that. And savestate… Save state: S. And now I should be able to
make some… tracking. Allright. We have logging. Also: In addition to that logging… That is kind of loud actually. Hold on. This should be better. There is one more thing I want to do. That is actually what I was
looking for before. This is my password alphabet,
or maybe this one. One of them. So yeah, that was what I was
trying to do there. So when I pressed start… Why is my camera window
looking all kind of wonky? Okay now it looks better. Hmm. I was checking, the… Those are the controllers. I may need two windows here. That one is for my disassembly. And this one is, okay. So do I have that code already? Do I have it? No I don’t. So let’s see. I kinda hate these mapper 7 games, because they are so difficult to trace, because all the pages are the size
of the entire ROM memory area. When you have code like this, the very next instruction is not
actually loaded from here, but it is loaded from a totally
different ROM bank. So it actually continues from
this page in the beginning of the ROM. That same address. And that makes the code
quite hard to follow. Not sure whether you understand
what I am trying to say. Hmm… Hold on. Snap. Yes, that is the problem with… Does anything happen
when I saved that? the problem when you ask
people to volunteer for moderating. Something like that can happen. Okay so what I was actually doing. Let’s shut that down, and… That should work. So I am looking for that code,
which should be… Somewhere. I am hoping
it is in the first bank here. It should be in… here? Oh yes that does look promising. So that would be 2021. And that would be UpdateControllers…
I think so. Let’s try that once more again. Yeah, YouTube chat is not as
good tool as it should and could be. So. I am tracing the… Actually that doesn’t work,
why does it not work here? Because it should be here. And it jumps to…
a totally different address. That should be 3863. That is one of the NMI handlers. Handler zero. So it goes from here, and somehow it reads controllers
at some point. Does it? It should. Yeah, that looks okay. So where does it save the controller data? The controller data is saved into… Possibly these two addresses,
five and six… No, it actually changes. RAM $19 Controllers1… I think these four addresses
are reserved for controllers. “Next time you stream,
use Twitch instead of YouTube”. Well that could work
a little better, but I… …am thinking that programming
content is better suited for YouTube. So there it’s checking… I should probably check where
these RAM addresses are read. So which one of these does it actually check? Not that one. One that either. Not that one. Let me see that one again. So one of these is being
checked somewhere. So that is one…
interesting looking. Okay that one looks suspiciously
like updating the random seed. I am just going to mark that up. It rolls variables, mixes in controller data,
mixes something else, and this looks so much like
an entropy feeder to an RNG. So that is probably the
random number seed. RandomSeed. And the code that does it,
is UpdateRandomness or something. UpdateRandomSeed, probably. Update random. Oh yes. Or no! That’s actually wrong page. So no, that’s not where it is.
It is in another bank. Which bank is it? Let’s find it. Because it should begin
with that instruction. So let’s find it. Is it this bank? 6, 7, 8, A, B, C, D, E, F.
No, it is not this bank. Oh, yes it actually is. So it should be there: Bank 1. Update random seed. Oh yes. So that works. That is done. But I was actually checking
where it reads controller data. This is one of the possible places. It is doing something to check
the controllers… It would be a little bit easier if I had
some RAM addresses to go by. Actually, in that Windows tool,
let me check here. If I leave it on foreground,
and use this tool: I should be able to see
the cursor position here. Somewhere. When I move this cursor,
I should see… That is changing, but that
is the pixel position. So that might not be it yet. That is also changing
in sync with that. And this is a Y coordinate. And this too is Y coordinate. And this is that cursor over there,
which is blinking. I can see whenever it blinks
this RAM address is changing. Even that is not what I am looking for. Apologies if this text is too small
for you to read. I can’t change it. I am looking for any RAM address
that changes by one when I do this. Something changes here, but
that is just sprite data I think. Anything there? These also change, but
these could be sprite data… So no. It has to be one of these. So this indicates which
buttons I have pressed. And this is the current button
status. Okay. So current button status. Player one current buttons. And the next one seems to be
player one new buttons. And the others are probably
for player two. Umm, Cheat Engine is quite
for something else. It is for a totally different purpose. Okay so either one of these is
the cursor position for the password- letter. If I actually type this here,
where does it put the letters? Where does it put them? Reset that.
Which button resets the game? Hold on. I somehow made it slower. Argh. So do that again. It probably did not save any settings. And that is even worse. I don’t think it saved
any of my settings. Let me see.
I have to do that again. That is done.
And the hotkeys. Yeah, it did not save any of them.
Hurumph. Stupid programs! Video. Four. Four. And save settings!
Save config file. Now, make a save state
so when I backtrack, I can easier follow
what is being done. E, F, G, H, I Make save number two. And compare these two. I see some changes here! What else is changing? This area changes a lot,
but it’s highly irrelevant- because this is just a stack.
It is probably irrelevant. Sorry about the sound,
but I am comparing these two- Okay I found it. It’s here. So, A… It probably says the length
of the passwords here. If I add one more letter,
this should change to B. And yes, it did. Okay, so. Let’s see. So it begins from 1D. Password length.
And the password buffer. Password letter.
Let’s do just that. The point of what I am doing- is to locate all code that
deals with passwords. And once I have located
the password handling code, I can begin to understand it. But first I need to locate it. So what is the longest possible password? It is B, and C… Oh yeah, that should be
as much as it is. Can I find any code that uses
this array? No, I can’t. Can I find any code that
uses the array, in the listing that I accumulated
earlier? Can I find it? Yes, I can!
In here it is doing something. It is, umm… Clearing the password buffer. So, this code is clearing
the password buffer. So, E22A. RAM E22A, Clear password buffer. Let’s see if I can find the code. Should be… E22A.
Should be exactly here. Okay, the function begins from… Let’s see. Should be that. Let’s see what my code finds. PasswordLetter… Should be able to find more code. Over here it uploads the password
into the PPU, the graphics chip. Over here it clears the buffer. I am still missing something. And loading it. Okay. Okay here it checks
if the password length is 12 letters, it continues from here. What ever happens here. So, probably this function over here
validates the password. We are getting closer. 5567, probably validate password. Probably validate password. Didn’t find that.
Let me see that again. Why did it not find? No, because these should be
CertainlyCode, not RAM. Try that again. Validate password,
validate password… Okay it does something,
and then it does something. What is the first something? Hmm… This function is called from
quite many places. And it seems to clear rendering. Hide screen.
Let’s assume it hides the screen. Yes, animowany,
I just noticed that myself. Regarding the computer name “hariyu”, it just came to me.
I don’t know what it means, but it just came to me
so there is no reason further than that. So, 7FC0. That probably does something? Actually, I know what’s going on here. “Probably validate”… I think it has done a decision
at that point already. So, “nag about invalid password”. I think that’s how it goes. Plus is… Over… here… Let’s see. I can actually
check that really easy. So disable that. And put the…. Argh.
And put, can I pause this? I can. And then, put tracing on… Start logging. And then unpause. And, uh Okay that’s not what I wanted to do.
Let’s try that again. Start logging again. So unpause… Add one letter. Add another letter.
And get this error message. So if we find this place, we know we have found
the password validation. Because to print that message,
it actually… Hold on. Why can I not focus that screen? So it was. Which address was it? It was this one, I think.
No, it wasn’t. Password length is… Hold on. Password length is over there. CLC, ADC, no! Compare.
It is there. That’s where it checks. And if it differs… No? Let’s find that compare-to-twelve instead. The Linux distribution I am using is Debian. So compare to twelve. This is actually the wrong log. Pwd. Let’s try that again. So A, B, and C. That’s once. And actually… Which one is this? I need to do that again, because the log may actually
contain both instances, and it should not. So let’s add… Pause this.
Start logging. Unpause. And get this, and stop logging. And see the log again. So compare to twelve…
It is here. So rightly here it activates
password checking. And umm… Hmm. What is this delay here for? So anyway. It is in… That’s in another bank! Hmm. Well HTML is not
turing-complete I think. So that bank. It could have been here? Oh yes, it could be here,
so it’s probably in bank one. So it’s CheckPasswordLength. Go from there. CheckPasswordLength.
No, it’s the wrong bank! Hmm. Which bank is it actually? CheckPasswordLength.
Not that bank. CheckPasswordLength.
Not that bank either. Not there. Umm… This is a guessing game. Which is nasty with this mapper,
but I don’t see a way around that. Let me do that… CheckPasswordLength. Okay here we go. It’s in bank zero. So over here it does… Something! It looks like it could be doing something
with… Puts that there, and… I am going to presume
it prints some message. This number here could be
the password validation result. Let’s see. 633… SomethingRelatedToPasswordValidation. SomethingRelatedToPasswordValidation. Hello o m g. So it is loading that in all kinds of places. And I want to see what it–,
where it actually sets that value. So let me see. It loads it, and then checks it. That is not very helpful. Let me see that. Clearing, clearing. Okay then that is probably
not related to password validation, but maybe the game mode… SomethingRelatedToGameMode. So I was on the wrong track there. So that’s what I already checked. But this here… Oh yeah, I know now. If I do this, but… Put there… If I create a blank password.
I know this matches. So I am going to try this password,
and do another log. So, “valid”. Valid log. And unpause, and frame advance… Oh? How come? Wasn’t this supposed to be a valid password? Do I misremember it? Oh, it was not B, but Q. So let’s see that again. Can I unpause this please? Yes. So do that again. So it’s Q, and then K-K-K-K-K… And see there. Pause, start logging… Probably need to delete that first. Start logging… And unpause. And I got a valid password. Now let’s see how these two differ. I got a log doing an invalid password,
and log for doing a valid password. Let’s see how those two differ. The place was here. Both of them go here. These parts are equal. Hold on. Can I do a diff? Let’s see about a diff. This may not be as useful
as I hoped it would be. Let’s see in any case. They are not exactly equal, because they do things like
music code checking, but… Do they differ in parts…
Which one should I check? Probably address, this one. That one doesn’t check it.
And this one does. This is hardly useful. But that seems to differ here. In one of these, this is −1,
and in one of them it is 0. Let me work on a
hypothesis here. If I change the game, and force this RAM address
to be always… Not there. Can I find the hex view? Here. 633. If I change it like this…! Does it work? No, because the game changed it back. That didn’t work. I cannot do it in this
editor. I have to enter a cheat code instead. Hmm. Cheat…
Probably here. Address. Let’s see. And force it to that. Let’s see. Oh yes! So that is actually
password validation related. Actually it may not necessarily be
password validation related, because– Hold on let me see if I do this… Oh yeah, it always loads the same set. Yeah. Still doesn’t probably… Yeah, that may be the result
of the password validation, but it does not force the
calculation in a different way. So let’s see where the variable is changed. In my– In a valid password, in here, it sets password-is-valid. So right here it sets the flag
where it says: password is valid. Allright. I think we are getting somewhere. So this address, FB2A. FB2A. Can’t find it? FB2A… 1,2,3,5,… No, it’s not there. Can I find it in another bank? It’s not there. Actually in the first bank?
No, no. No… Possibly here.
It looks like that. So it’s in bank 4, I think. So that should be–
hold on. Like this. 71A. B2A. Let’s try that. PasswordAccepted. No, that didn’t work. Oh, I have a syntax error there! CertainlyCode! Let’s try that again. Hmmmm… PasswordAccepted. No?
Not there. Try again. No. Not there. Not there. Can I find it? PasswordAccepted?
No, not there. So, there? Not there. Which bank is it…! Not there. I hate this guessing game. Not there. Why can I not find it? What did I not check before? It’s not there. Oh yeah, thank you animo. Yeah, that would explain it. So let me see that again. Argh, and I should probably
check what I actually type. So not there. Oh yes, now it is found. So let’s see where the function begins. FB0C. It begins… B0C… Okay! FB07 is the code where it checks– ValidatePassword. Allright. What does it do there? What?? Seriously?? Does it actually use a lookup table here? It actually uses a lookup table here. FB5A… So it checks whether the password
letter is within a valid set. CertainlyData. ValidPasswordLetters. So now I can actually use that viewer, because now I know where the letters are. wizwar2.nes. Because now I know where they are. That should be 1FB5A. 1FB5A. Actually, wasn’t I there before? 1FB5A. And… Hmm. Hmm, hmm, hmm, hmm. How does it work? Begins with two… No, I am not in the right place. 1FB5A… So it should be here… And. Bingo.
There we have the character set. The character set is here. And! The password– The valid password letters. That is actually, CertainlyCode… TranslatePasswordLetter. So this list actually was correct. So what it does there is… I think it is calculating a checksum here. Let’s see… TXA… Hmm. What is happening here? Uhh…. What is happening here? What is this table? Even this is not… Even this is not the password extraction, but this is the password checksum,
or something like that… What is happening here? Hold on.
Let me make a simulation. Or at least, pseudo code. So if the password is like…
Test=… Let’s use that…
1,2,3,4,5,6,7,8,9,10, and 11. And
the table is that BDGH… JKLM, NPQR, actually… NPQR. NPQR. TWXZ. So for n is equal to… I am writing this in pseudo-code,
what the game is actually doing, so that I could better understand it. It translates the letter.
And, actually… How does it do that? It checks… BPL… Okay so it returns in A
the translated character. That’s simple enough. Yes. So str position, table test. Just making sure that I am
getting this right. php tmp php…
Oh yes, that’s doing absolutely right. So that’s that. And then. And this should actually
be X just for compatibility. So that’s what it does so far. And now I’m here. So tmpa=x. And Y is that much. And if X is odd,
then happens something. Else, happens something else. In the else branch happens… A is multiplied by 16. And in this branch… Hold on! Hold on, what is Y? Oh yeah, okay!
Now I see what it is doing. So it is actually– Oh yeah, it is converting
two 16-bit units into bytes. So it’s actually making six bytes
into this array. Okay we are clear so far. So the ini file… So that is actually not
validation of password, but… Validation of password… ConvertPasswordIntoBytes. And the password letters,
which were in this array, are being converted into bytes. Byte zero, byte two, … Into this array. And that is the first step. That is the first step. So when it exits this routine, what happens next? So status of
this RAM address indicates – whether there was some kind of problem
with the password alphabet. No, the 6502 can not do multiple
bit-shifts in one operation, so you pretty much have to
multiple of them in a row. That is a limitation there. Actually the same limitation
was in the original 8088 processor, except it could use a register here,
but that was how it worked. So anyway, where is this
function called from? It is called from…
over there… And, uh… What happens when this function returns? So, FB2F… After this function returns, something happens… It returns… Umm. Yeah, this was the failing branch. But the successful branch is here. So FB0C is where it actually… No? No no no, not there. Can I find it? In here… Oh yes. And after this, we go here. And what happens here
is… something. F9FA. Going by the presumption
that it is F9FE… DecodePasswordBytes. Let’s assume it is over there. DecodePasswordBytes.
Of course, yes. So, 1FBA0. What it does is… Byte0 is xorred with Byte5… Byte3 is xorred with Byte5… Byte5 becomes the xor of
every other byte. And after that comes
a xorring with a table. It xors, byte0 xor that much. 1, 2, 3, 4. CB FA, using that table. So it uses that table to… Actually I could probably give
that table a nice name. PasswordXorTable. So these are the operations it does. After that… Actually I should probably
make that a nice comment. So that should be in… It goes also there. And then. And then. I’m making notes here for myself
to understand what the code does. Let’s see if my comments worked. My comments, oh yes
they seem to work. And now, the next step is… If byte4 xor byte0 xor byte1
is greater than 62…? Really? 62, yes. Then… I presume that it says
that password is invalid. Yes, yes. Reject password. Okay! Then. Wow. This is way more complicated
than I thought! This is way more complicated
than I thought. So… At that point… Let me see what happens there. This table. Wat? What? What?! That cannot be right. Are you reading the same
thing I am reading here? It actually uses its own code,
program code, as data!! And encrypts the password
using its own program code! That’s the first time I ever see
some game doing that. No, I am not misreading the address. Ffh. That’s mental. Wow. Okay, so we have to use a table here. Well, we used a table here, so… might as well use another one. How many bytes do I need here? It uses, umm. So the number is maximally… It’s in that range. And then, I need a table… Starting from here,
that is 62 bytes long. By the way, this is probably
also code. Is it? Can it be? Okay that might not actually be code, yeah, that is quite something. Where was it? So it uses that, actually not even in that range,
because it doubles the value, so it is… hhah. FUN. Come on! First it uses the function
as a table as bytes, and then it jumps to the function. Thank you Metaldemon. So I am going to need a table.
Let’s see. How should I document that? And I thought this is going
to be a simple game – because it uses such a short password, with just four-bit digits. This is crazy. So. Byte2 is xorred with… Crazy table A times 2. And then Byte3 gets the same treatment. And then. What does the function actually do? So what that function actually does is… It returns Byte0 xor Byte1 xor Byte2 xor Byte0… Xor byte1 xor byte… Actually it does the same byte here twice, I think they made a mistake here! It should read here like this. They made a mistake. They do this twice in a row,
so it actually does nothing. So that’s what it actually does. That’s basically what happens here. Can you confirm? So it xors this byte, and this byte together.
This is totally irrelevant. So this xor this. These don’t do anything. And then take the high four bits, and xor them with the low bits from here. Actually this probably
should be byte2, not byte4. Yeah, they made a mistake here. No, I am not using tmux. I just use Joe, which
supports split-screening. Yeah, no non-English chats here! So. CrazyChecksumFunction. And, where it is called is… Crazy– seriously. Umm. So. Reject password if
CrazyChecksumFunction xor… One would think that – that would be quite enough
checksumming already…! But all of that is just validation. Okay now we are probably
getting into actual data. Yes, we are actually
getting into data. So… *hums*
So at this point it saves into – this variable, what ever it is… I am going to guess
it is the level number? I don’t know. It is going to be the, umm. Left, left, left. So it is the high three bits? Is it? Wait. Let me check. c76543210… So it rolls it once. We get this. Rolls it twice. Gets this. Rolls it three times, gets– okay. So it’s, Byte3… And then. At that point it is… I may actually at some point
make a video about why I use Joe, and which editors I have used so far, maybe at some point I have actually
told the story somewhere, but I can’t remember, so. Maybe I make a video about that. But let’s just shortly say that I use Joe, because I am pretty used to it. So that variable is going to be– two bits from there. And then. Wow. What is that? Oh well, widominiq, hacking with CMD implies running Windows, and I don’t really do Windows… So: Nope! Actually… Nope, I can not. So, remove that part… Check out what does this function do. So that function does… Humph. Hmm… what does it do? I see comparisons with 9… Something related to… something. Oh yeah, it is incrementing a counter here. And the counter is BCD format. Some kind of counter. OK. So if byte 2… Or if something else, then… You know… wait, what? Are you serious? It actually runs this really heavy function in a loop here. OK, I see that. That is all I need to comment here. So, okay, and then the next part… 1F… This variable equals byte 2 as before. And then here… This variable contains this byte. Like so. And then move on. The keyboard I use is a Fujitsu Siemens KBPC SX S/FIN. I should actually put some game music in the background. Because I happen to like this song. So byte 1 bits, over there. And then, rotate to the right… so it is, rotate to the right. And then, 7F… Well, this is chiptune, alright? So rotate even more, and then… That point is rotated by 6. Like so. OK, then… I don’t know what any of these variables here are, but I’m guessing we will find them later. The checksum… actually it seems to check pretty much everything… Well, I will analyze the checksum later in more detail, but for now, this is one bit from there… That variable is… over here. Wow. So A4, and into that it puts that, but store… And then… wow. It does something weird again. What does that function do? Oh yeah, it validates. OK, sure. So that would be 5. Yeah, sure. And after that, what happens now? Does some validation there… hmmm. I think it is done over there. OK, so that is as much as I need to check for now. I have not done Rust any more than I did in my Solar Jetman video. So these are the variables that it extracts from there. I can probably sort this out. Let’s see. Can I sort like this? Oh yes, I can. So this is the list of addresses here. Alright, now about the checksums. I need to make a little test here. The best way to test this would be to implement a program that pretty much replicates this action here, so… bytes… where is the… oh yeah, you are right about that. The wrong address there. It should be… That one is correct, so it should be… yes, yes. Now it is correct. Thank you for the correction, Gábor Zabojszky. So, bytes equals… actually maybe I do nibbles first. So there’s 12 nibbles. There’s this password. Like so. And then convert it into nibbles. So that should be $bytes[$n]=… hold on, how does it actually do that, into bytes? So it takes… the first one goes into upper and the second one goes to lower. OK. OK, now it’s in the bytes. And then replicate all this madness. I know there was a difference between the LSR and the ROR operations here but I did calculate those, and wherever it did matter I did take care of the carry flag there. So let’s see. What would be the easiest way to do this? Let’s try just like this. Really? Oh yeah, after it has done this it discards byte 5 and then… seriously? Just do that. Uh… let me see that. Oh yeah, it discards byte 5. So… 2, 3, and 4. And then I may need to do those crazy tables by… hmm. So that crazy table is there. table0 is … I may try to do this by… can I do unpacking in PHP by converting a string into bytes? Let’s see. And the first table was over here. Did it work? Is it correct? It is actually correct! First try! I am happy of myself here. And the CrazyChecksumFunction is in this address, FB6A, and it’s like… this much long. Byte 5 is that. And then bytes are being XOR’d with the first table. Now we are here. I have played Battle of Olympus, and I have actually studied its passwords also. And it may be a subject of a future episode of this series, but I haven’t really so much researched that. animowany, what do you mean? I am actually aware that it uses 6B here, so it’s just one byte offset there. But that doesn’t make a difference. This is multiplied by 2 here, and that is used as offset. But it doesn’t change the fact that it’s actually reading this function here. So in one of those instructions it uses these bytes here, and in the other one it uses these bytes here. And this one. I may have misclicked something there. But anyway, it still uses that code there. So it doesn’t change the fact. Let’s check so far. OK, I have an error here. Bytes, table… wait… how did it actually work? Oh, it’s offset by 1. OK. So far so good. So this is not greater than 62, so we are on the right track. And then… hold on… yeah. crazytable is this, plus… Oh yeah, but this one should be +1 so you are right about that, at least there. And $bytes is like so. And $crazy is $bytes XOR $bytes XOR $bytes… XOR $bytes XOR $bytes, shift down by 4… and take the low 4 bits. Crazy is that much, and byte 3 low is… $crazy and $bytes low bits. Are we correct? Yes, these two match. We are still correct. Now extract data. So, values are… Hello, sullyrox! Values are $bytes shift… over there.. 0, 0, 0, 3, 1, 1, 3, 1, 1, 2, 0. And that’s it. So… 5, 1, 3, 6, 6, 4, 4, 2, 0, 6, 0. And that is 7. That is 1. If… and that is… let’s do that again. Just in case. OK. So these are the values that it extracts from the blank password. Which is quite surprising, actually. Are these correct? Hmmm. Let’s see whether they are correct. Take that out, and then… trace. Wait, what? So this is actually… I was thinking the game was glitching there for a moment. But let me see, what is that password actually doing? OK, so this wasn’t some kind of default blank password. This is actually something meaningful. So, 10 keys… do I have 10 somewhere? No, I don’t have 10 anywhere. They have 10 here, yes I do have 10 here.
OK, score is 440. Do I have a 440 anywhere? No I don’t. But I just remembered I forgot to do some step here. So there’s one thing that I forgot to do… do this. The last one is that much. OK, so that is the key counter. “Number of keys.” 3 lives. Which one of these is 3? This is 3 and this is 3. Hmmm. Did I kill something? Yes, I did kill something. OK. That clarifies it. 9th area… first, second, third… max lives, 3. Air stage… begin with all armor…. In any case, I have a mechanism here to decode a password. Now I just need to find out what each of these variables here mean. And then when I have done that, I need to find a way to encode those passwords. Because this encryption here is so complicated. And really, that crazy table over there, that’s just something from another planet. I’ve never seen sum code use that kind of thing. That’s something that I would maybe think of, but I would never have guessed that there’s that kind of thing in production code. So, max keys 15. Let’s try that one which has 15 keys. Maybe this one. So the code is this. Do the verifications, these should match… yes. 15 keys, and max… pretty much. OK, so let’s do that Q thing again. So one of these is lives. 0 is lives, or maybe that one is. So either one of those is lives. Let’s see if I can find anything to differentiate between those two conditions. Let’s try this… no, nononono… this password. No, there’s too many things that are 3. Hmm. Where do I actually see how many lives I have? Is there any way to see it? What happens if I pause? I have these here… oh! You get the secret code like this! So… wow, I actually got a valid password by chance. No, I got a valid password because I have a cheat here activated. So I have to delete that. Let me see about that. If I pause and take this password, and see what does that do? TRL… ZPB… DDZK. OK, so the first one is lives. Because I start with… 3 lives, is it? OK, so these are lives, OK. Thank you, animo. I don’t have any spells. Hmm, where is a 0… well, pretty much everything is 0. So this is 3. What is that for? What could it be? I don’t have anything interesting here, so that’s not telling anything. Does that actually change my password? No it doesn’t. If I get a key here… I get a different password. Yes I do. But keys are not a mystery. So… this is unknown. And also… besides the lives, what else is 3 when I start the game? Can anyone tell me? Those are not saved in the password. No, they are not. Money is not saved in the password as well. This game is this one. Ironsword: Wizards & Warriors II. 3 attempts? Is 3 attempts the same thing as lives? No? Let’s see. If I consume one of those, what happens? Oh, I just lost a life there, so let me see. If I use this password now… ZBTR… BDD… and see how that works. So I have lost lives, but this is still 3. So let’s kill the guy again. Game over. Now check if it changed. It actually did change. Because my life is, again… let’s see, Z… PB… and Z. So what changed? Hold on. Lives changed, but this didn’t change, so that is not continues. Pointy shield? Do I have some kind of shield? So that is actually saved. I should probably put the RAM addresses here, so that makes things possibly a little bit easier than to check through the passwords every time. So this is at… I know the lives now, and I know the keys also. RAM addresses… ExtraLives… so, Lives… And then… 67, 68, 69, EF… those… and there… and keys. So those are the RAM addresses. If it is the level I am on, then why would it begin from 3? Hello, Malteser! What I am doing here is trying to discover how the passwords in Ironsword work. So let’s begin from here again. Hmm. 3 is attack? Could it be? Well I took the RAM addresses anyway, so let’s see if I can find anything that changes there. Don’t need cheats anymore, so it is like… there. So those are the addresses. If I can find anything that changes them… Over here I get FF for this one. Let’s see if I changed it. Oh yeah, that is my weapon. That is clearly my weapon. Look at that! Suddenly I have a… thing here. Even though I was inside a store, that didn’t seem to matter. So this is that address. Oh yes. So that is a weapon. And there are a couple of different weapons, so… 6 is the last weapon possible. So that should be a pretty big sword. And if I put a 7 there, the game should probably crash or do something unexpected. Oh yeah, the game crashes. So I am on the right track. So this is weapon. Then 68 is… oh yeah, the game is pretty confused now. So 68 is, umm… over here. If I put myself a nice little shield… nice. Am I imagining it, or did it also change my jumping power? Let me see. If I change that again… no, I’m just imagining it. But yeah. That seems to be, maybe not the shield but my… what is that called? What is “haarniska” in English? The metal suit. I can’t find the word right now. For the lack of a better word. So 69 is, uh, let’s see about that. 69 is… F, E, D, C, B, A, 9. So that is actually my shield. Shield. Armor! Of course, yes. Armor and shield. What is EF? Let’s see about EF. EF is… I don’t know. Huh. What is happening there? Do I see any changes there? I don’t know. Huh… I am not seeing any changes there. Could it be a difficulty level? EF, if I put there a 7F… Oh! I’m floating now. Hmm. So EF, that would… oh, I also got these somehow. I don’t have any spells, but… hmmmm. I’m not quite sure what’s happening there. OK… OK… heh. OK, so in conclusion, I couldn’t find what that variable does. At least not for sure. Did it change the boss or something like that? I don’t know why it got my hero floating there. So that is unknown, what that is for. Still unknown. How about these? So that is in… this region here. So let’s see. Oh yeah. That’s my list of spells, or something like that. Do I get the same one multiple times if I… no I don’t. I don’t understand. I don’t understand. Well maybe it’s actually a level and not just a list of… hmmmm. Let me see. If I put 1, 2, 3, 4, 5, and 6… and try this now. Ah yes, I get six things here. And if I use this once… I still have it. Can I use it again? One. And once more. One. Oh yeah, I lost it. So it’s the number of that item. So… number_of_item1. And these: 2, 3, 4, 5, 6. And that one is… whatever that is. I don’t know what that is. Hmm. Are there other items that I could possibly have? *whistle* OK, that was kind of unexpected. So I’m going to presume that is some kind of item as well. But I don’t know what this is. The editor I’m using here is JOE. Joe’s Own Editor. Can I see the help page now? Yeah, oh well.
It’s JOE anyway. So that is decoding. Now to simplify this encryption here, because this is… this is crazy. This is nothing short of crazy. So I should be able to simplify this… So I get… that is actually irrelevant. Is $bytes used anymore? It is not actually used anymore. Hold on. Why is this calculated if it’s never used? It is never used. This is calculated but it is never used. So… byte 5. Yeah, it is never used. So this is trash. Let me check. 3003. And now… nothing changes here, so yeah. That is a redundant instruction there. Anything else I can do here? Hmmm. Probably not. There wasn’t any checksum there. Hold on, let me see. Let me see the contents of the bytes. Bytes… no, I don’t think it is even used for a checksum there. Because those values just don’t make any sense. XorTable. And over here it doesn’t touch that value, so that is not used there. Hmm. So I don’t need that. Until proven otherwise, I don’t need that. Can I… yeah, this should match… OK, now I just have to do this all in reverse. So let’s see about doing this in reverse. So, bytes… and there was actually… Let’s mark the exceptions here so… 69… and lives… Random seed? That is a valid theory. But it’s not the case. It is not the case. So $bytes is… number_of_item7, plus… $values[‘armor’] multiplied by 2, plus $values[‘shield’] multiplied by 8, plus… $values[‘weapon’] multiplied by 32. $bytes is $values[‘number_of_item5’] plus… $values — what is the time, by the way? OK, the time is 1. $values[‘number_of_item4’] multiplied by 4, plus $values[‘number_of_item2’] multiplied by 16… and $values[‘number_of_item1’] multiplied by 64. Byte 2 is $values… oh. Yeah, keys. Keys plus $values[‘lives’] multiplied by 16, plus $values[‘number_of_item6’] multiplied by 64. $bytes is — the keyboard is Fujitsu Siemens. Some kind of Fujitsu. $values is… is… number_of_item3 times 16 plus… “unknown.” Times 64. And now, make the crazy things there. $crazy is that, and $bytes is added that value. And then… that seems pretty straightforward. And then that. Where does byte 4 come from? And then after that… Yeah, that is a good theory, but the unknown is just in range… it is a 2-bit value. It’s only 0, 1, 2, or 3. And there are quite many more levels. Is there? Yeah. So how does it actually work? Let me stop that, and check that again. php… that. Unknown is 3. And here, final area… oh, let’s check area number 6, first instance. Unknown is still 3. And that is missing. Hmmmm. OK, these interpretations may be wrong here. These may be like level numbers or something. But the list of spells did change there, so I’m not sure. I’m not sure. So at this point we are back to bytes, but we haven’t decided bytes 4 and 5 yet. So how are these calculated? Where does it get byte 4? Byte 4 is, um… Yeah, it is a possibility. I was also thinking about that. But if I go further, I should work by this theory. So byte 5 is XOR’d with that. Let’s just do this, and see if that results in a valid password. So… Those are good questions, people. So high nibble and then low nibble. Yes. So it is $charset… bytes… Let’s try this. Does this password work? Can I actually change the style? View, preferences, font color… Oh yeah, there we go. And a little bit bigger, please. Font color… there we go. So, try this password. I’m holding Tab here because this is so slow, this form here, on reaction; so it’s not nice to use otherwise. So I’m turboing the game. So let’s see if this password works. It does not!
So, first attempt: fail. Let’s make some quick verifications here. That should actually work. So my theory here is incomplete. No, I don’t drive a bus anymore. I’m a programmer again. Because the company where I was driving the bus downsized. So, password encoding: fail.