MicroCorruption: Jakarta

There’s a manual:

  • Passwords that are too long are rejected. There is additional mechanisms to verify password length.
  • The lock is attached to LockIT Pro HSM-1.

The main function just calls login.

login function is quite long:

  • Authentication requires a username and password input. The prompt states that these inputs together may not be more than 32 characters. :D

  • The gets function for getting the username:

    • length of input buffer: held at r14 -> 0xff(255) characters. Mmmh, interesting considering the rule provided earlier.
    • address to the input buffer: held at r15 -> 0x2402.
  • There is a length check on the username input:

r15 = 0x2402
for *r15 != 0{
	r15++
}

r11 = r15
r11 -= 0x2402 ; this gives the length of the username input.

cmp.b(0x21, r11) ; this compares if the input is less than 0x21(33) characters.
		; checks the carry flag. jnc implies the input length less than 0x21.

  • Call to strcpy(). The username input copied to 0x3ff2.(this is the address the stack pointer points to).
  • The gets function for getting password:
    • length of input buffer: at r14 -> 0x1f(31) - r11(length of username input) & 0x1ff characters. Capped at 31 characters. (This is maximum input, in case username was empty.)
    • address to input buffer: at r15 -> 0x2402.

An interesting discovery on calculating the length of input passed to getsn on the password input.

If the username input is maximum length, a buffer underflow occurs! :D

  • Call to strcpy(). The password input copied to 0x3ff2 + length of username input.
  • Another length check is done. This once checks the total length of username + the password inputs. Address to the copied content is passed for a call to test_username_and_password_valid.
  • A byte set at r15 is checked if zero and this determines the call to unlock_door.

Time to get down and dirty!

You run a test input with the maximum username input and follow the progression:

This will cause an underflow as you observed earlier;

Sweet! You can now have long password input. However, there is still a barrier that you need to bypass: the cmp.b #0x21, r15. The total length of username + password is checked to ensure it is not more than 0x21.

Looking at cmp.b instruction from the user guide: this operation compares the last byte of the source operand from the destination operand.

You just need to ensure that the last byte of r15(the total length of user + pass) is less than 0x21. The minimum value for this would be 0x100(256) chars. Since the username length is already 0x20, the password length needs to be 0x100 - 0x20 = 0xe0(224) characters.

Authentication fails as expected(this was a test run). You notice though, that the return address is now overwritten by the copied content.

Can almost see the victory now…

You need to modify the 5th and 6th byte of the password input to the call to unlock_door address at 0x461c. You try a 32 char username input and this password input:

You cracked it! :D

Santa Cruz is your oyster now.

Snappy on Travis

MicroCorruption: Santa Cruz

comments powered by Disqus