I probably should have read the manual
(right, who does that?) before now. But better late than never. The
manual on pages on 4 and 5 talks about how 0x7F is the code to unlock
the door – not a function call but basically a hardware interrupt
that accomplishes the same thing. Additionally there is mention of
0x7D and 0x7E which set a byte in memory if the entered password
matches. Look for those to come into play at some point. We actually
already saw these in Cusco, although that knowledge wasn't fully
necessary at that point.
As in a Cusco, there is still an
instruction (after the password has been checked and after the “wrong
password” message is displayed) that adds 10 to the stack pointer.
So the stack pointer jumps forward x10 to address 3cc6, and the next
instruction is to return to the value held at the address 3cc6. The
assumption is apparently that you have not entered a password longer
than x10 bytes and put your own value in that address. But as the
saying goes: when you assume you make an 'ass' out of 'u' and 'me'..
So we can put what we want in 3cc6
because nothing prevents us from entering a longer password than 16
characters – that is nothing prevents us from overflowing the
buffer. Last time we did this we put the starting address of the
“unlock door” function. This time however there is no unlock door
function, but there is ample room to put code that we write in
assembly.
So first we want to get control of the
instruction pointer. Put the address at that point to the area of the
buffer that we have overflowed, that is point the instruction pointer
at the code we are overflowing into the buffer. This is called
injecting code.
So what do we want to do? As you may
recall from Cusco, hardware interrupt x7e when placed in the SR
(stack register) and called with the interrupt trap causes the
password to be checked. Hardware interrupt x7d sets a password in
memory indicating that the password was correct, and x7f straight up
unlocks the door.
Let's do the following:
Point the instruction pointer at memory
we control.
Get x7f into the SR **
Call the interrupt trap.
We can look at the existing
instructions in the code to cobble the bits and pieces together –
or if you want a project you can learn this version of assembly and
roll your own. But the basic
structure of the code we can use is as follows
3e40
007f mv #x7f00, r14
0f4e mv
r14, r15
024f mv
r15, sr
32d0
0080 bis (highbit), sr **
b012
1000 call 0x10
**Note: the manual says x7F opens the
door, but on my version of the game they had an extra part in there
that set the high bit to 1 yielding xFF as the value required to
unlock the door. The only way you figured this out was by looking at
the code within <INT>
453e: 32d0 0080 bis #0x8000, sr
so while you were examining
<conditional_unlock> where it loads x7e onto the stack and
calls <INT> you can see as you step through it that x7e gets
loaded into the SR (from r15) and they flip the high bit on and
then call the trap.
You can trim down the code above if you
work through it – I don't want to take all the fun out – but a
successful entry based on the code above can look like:
41414242434344444545464647474848c83c3e40007f0f4e024f32d00080b0121000
No comments:
Post a Comment