Thursday, December 11, 2014

Microcorruption - Johannesburg


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