MicroCorruption: Santa Cruz

Nice! Here is a lock. This is the manual:

  • Passwords that are too long are rejected.

There is not much clues from the manual.

The main function just calls the login function:

  • Authentication requires a username and password input. The prompt states that these inputs should be between 8 and 16 chars. :D

  • Bytes 0x0, 0x8 and 0x10 are set into the addresses at r4 - (0x6, 0x19,0x18) respectively. This will probably make sense soon.

  • The getsn function for getting the username:

    • length of input buffer: held at r14 -> 0x63(99) characters. :D
    • address to the input buffer: held at r15 -> 0x2404.
  • Call to strcpy() for username input to address 0x43a2(this gets evident while running the program.)

  • The getsn function for getting the password:

    • length of input buffer: held at r14 -> 0x63(99) characters.
    • address to the input buffer: held at r15 -> 0x2404.
  • Call to strcpy() for username input to address 0x43b5(this gets evident while running the program.)

The address where the password input is copied to by the strcpy() is interesting. It is only 0x43b5 - 0x43a2 = 0x13(19) bytes apart.

What this means is: for a username input > 19, the extra bytes get overriden by the password copy. This aaalso means that it is possible to write well beyond the password content copy if there’s is any constraint on the password input buffer. :D

Smells and definitely quacks like a clue!!

You run a test run to get a feel on the program. Since the provisioned length of the input buffer is greater than the prompted one:

The program proceeds…

there is a cmpoperation done between the length of the copied username input and the value at r4(0x43cc) - 0x18 = 0x43b4: this was originally set to 0x10.

This value gets overwritten by the 19th username input byte: 0x61(remember that the strcpy dest address for username input is 0x43a2 from earlier).

Since r15(0x61) > r11(0x18), no carry flag is set.(For more on this, refer to previous notes. The program continues.

  • there is another cmp operation between length of copied username input and value at r4(0x43cc) - 0x19 = 0x43b3: this was originally set to 0x8. This value is now 0x61(the 18th byte of username input).
    • The program advances only when the carry flag is set. This means, r15 value has to be less than r11.
    • The 18th byte of the username has to be less than the length!

You run a test to bypass this:

The authentication check fails, but the program proceeds:

Can the return address be modified?

  • Probably, but first, there is a tst.b that happens before.
    • The byte at address -0x6(r4) = 0x43c6 has to be zero for the program to proceed to fetch the return address to jump to.
    • This byte being checked is the 18th byte of the password input. You can have the password terminate with zero byte on the 18th byte.

You rerun a test with these steps:

  • The return address is at 0x43c8. If you can find a way to modify this, you can jump to the call to unlock_door at address 0x463a.

      1. Cannot use password input for this; because of strcpy(). The zero byte will terminate the copy and the bytes after will not be copied.

      1. You can use the username input for this. If you recall from earlier: it is possible to write well beyond the password content copy and the extra bytes get overriden by the password copy.

    Basically, have a username input extend enough to modify the return value.

You give this a try with the following input:

username:

password:

This is what you observe:

Another one down!

Onwards and Algiers. _0/

MicroCorruption: Jakarta

MicroCorruption: Novosibirsk

comments powered by Disqus