For this challenge we’re handed a file with an extension of .86p. Not exactly a common extension and the file is only 2kb, so lets open it in a hex editor:
Immediately we can see some strings that look interesting, but the first and most important is “TI86”. So maybe we’re dealing with a TI86 assembly program? Let’s try to find an emulator where we can run this.
Wabbitemu comes to the rescue here (https://wabbit.codeplex.com/). Wabbitemu will allow us to run TI calculator assembly programs. Since this program is for a TI86 calculator, we install the TI86 ROM for the calculator. We can then load the program by opening OGMob.86p and running the following series of keys:
2^nd^ -> CUSTOM -> Asm( -> ENTER -> PRGM -> NAMES -> OGMob -> )
This creates the line, Asm(OGMob), which is how you execute assembly programs on a TI86 calculator. When we execute the program, we get the following info:
Playing around with this by hitting some keys, it looks like the display changes based on key presses, but no matter what we keep getting back to a screen that says “FAILURE”. At this point, we need to start looking at this in a disassembler. Looking around for resources on reversing a TI86 binary, there’s a decent blog post here: https://www.omnimaga.org/asm-language/ida-pro/.
However, loading at the suggested addresses here doesn’t work, but playing around in the Wabbitemu debugger shows us that the binary needs to be loaded at 0xD6FD. We can figure this out simply from trial and error, getting the bytes to match up with what is showing up in our debugger.
Once this is loaded correctly, we can finally take a look at things in graph mode. The main graph of the program looks like this:
However, we have a lot of function calls that don’t seem to go anywhere in IDA, though they point to places in the debugger. So if we google the addresses with TI86, we find this link about the constants: https://github.com/abbrev/ti-86-asm/blob/master/stranded/ti86asm.inc. So it turns out that all of these are internal functions in calculator. By creating a new segment and storing our constants there, we can nicely label our IDB so that we can see what it’s doing:
So now we can finally put the pieces together and we see a lot of sequences that look like _getkey, compare, conditional branch. Finally, we’re seeing the logic of what we saw before with entering keys and then seeing “FAILURE”. Presumably, if we enter the right key combination, we’ll get the key for the challenge.
If we walk through the logic for the _getKey calls, and use the site we referenced earlier for our key constants, we get the following sequence:
ENTER CLEAR ( 8 6 7 - 5 3 0 9 )
When we enter these in the right order, this is what our screen shows:
Which is the key:
As we were walking through those key presses, there is a large body of code that executes, and the screen changes every other key press. If we look at the data that code is referencing, we find it all pointing to constants and then using those constants to draw onto the screen. Each constant seems to be made up of 8 bytes based on the gaps:
Nothing really comes up if we look at these as just letters or numbers, for example, hwere is the first two of the 8 byte constants:
But, if we look at these in binary, something much more interesting pops up:
Though not immediately obvious, if you step back from this, or convert it to white/black space, this does in fact have the key for the challenge in it. The first two constants above contain the binary representation of an 8bit by 8bit sprite of the letters PAN. If we do this with all the constants, we’ll get the full key from there.