I noticed that again at the end of
<login> on line 0x458C they insist on adding to the stack
pointer address and returning from there. The weakness continues to
be that there is an address stored just outside of the buffer range
that the program uses to return to, and as before that if you
overwrite that address you can take control. This is likely to be our
way in.
For the sake of looking at other
things, I also checked <test_password_valid>. There is some
fiddling with sr, r15 and a call to 7d to check pw. If pw had been
successful there would have been some value put into r15 and then
sign extended and rechecked in login. But it never is so that's a
false lead.
The manual indicates that they are not
allowing passwords that are 'too large'. A simple test of our
previous winning entry shows that indeed there is some kind of error
checking for an input that is 'too large' – as our previous winning
entry is rejected.
They still use <strcpy> so they
limit our use of 0x00 (null delimiter). However if we enter a
password that is too long it is still stored in a temporary location
prior to being copied onto the stack. Of course when the copy
happens, anything after the null delimiter is not included. So again
we have that limitation.
You have to read the code a little on
this one to find the key:
4578: f190 6a00 1100 cmp.b #0x6a, 0x11(sp)
The program presets address location
0x43fd to 6a, it then checks after the wrong password to see if that
memory address still has 0x6a. The assumption is that a password that
is too long will have overwritten that memory location with some
other value.
It doesn't actually check to make sure
that you limited your input to 16 characters, anywhere.
So our requirements for spoofing input
restriction are:
- no 0x00 (except as ending input if desired)
- memory address 0x43fd must remain as (or be overwritten to) 0x6a
As long as we meet those requirements,
our entire 'password' will be considered as valid input. Notice how
the actual requirements differ significantly from the written
requirements. Given those two constraints we are now free to inject
our shell code. As before the stack pointer is moved to just past the
buffer space and the code returns whatever address is provided in
address 0x43fe.
Our shell code will be very similar to
the previous code, no need to reinvent the wheel, although we will
need to make some minor adjustments to account for a different length
(given the additional requirement) and also out call address needs to
be changed to 0x45a4 because “call 0x0010” is in a different
place because the code in this version is different that the code
from the prevoius version (so things now have slightly different line
numbers).
3f40fffe1f53024fb012a44541414141416aec43
I made the leader board in June of 2014
under a pseudonym with that bit of machine language code, although I am not using my blog handle in this
particular game (I'm playing the game with my son).
However, we could have been lazy too. Conveniently,
they provided us with a function called “<unlock_door>”,
maybe we just call that directly instead and fill the password with
the filler they want.
6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a4644
No comments:
Post a Comment