blog/02-microcorruption

02 Microcorruption - Sydney

From New Orleans to Sydney, let’s take a look at the lock there.

Manual
Lockitall                                            LOCKIT PRO r a.02
______________________________________________________________________

              User Manual: Lockitall LockIT Pro, rev a.02
______________________________________________________________________


OVERVIEW

    - We have revised the software in revision 02.
    - This lock is not attached to any hardware security module.

DETAILS

    The LockIT Pro a.02  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---upon receiving
    the LockIT Pro, a new password must be set by connecting it to the
    LockIT Pro  App and  entering a password  when prompted,  and then
    restarting the LockIT Pro using the red button on the back.

    This is Hardware  Version A.  It contains  the Bluetooth connector
    built in, and one available port  to which the LockIT Pro Deadbolt
    should be connected.

    This is  Software Revision 02.  We have received reports  that the
    prior  version of  the  lock was  bypassable  without knowing  the
    password. We have fixed this and removed the password from memory.


(c) 2013 LOCKITALL                                            Page 1/1

Again the lock is not connected to any external modules, so we can assume that the passcode to open the lock will be in the code. Let’s do as before and look at main

Enumeration

Main

As before we focus on the function calls in main

int main(int argc, char **argv, char **envp);
0x4438      add   #0xff9c, sp
0x443c      mov   #0x44b4, r15
0x4440      call  #puts
0x4444      mov   sp, r15
0x4446      call  #get_password
0x444a      mov   sp, r15
0x444c      call  #check_password
0x4450      tst   r15
│       ╭─< 0x4452      jnz   $+0x000c
│       │   0x4454      mov   #0x44d4, r15
│       │   0x4458      call  #puts
│      ╭──< 0x445c      jmp   $+0x0014
│      │╰─> 0x445e      mov   #0x44f1, r15
│      │    0x4462      call  #puts
│      │    0x4466      push  #0x007f
│      │    0x446a      call  #INT
│      │    0x446e      incd  sp
│      ╰──> 0x4470      clr   r15
0x4472      add   #0x0064, sp
  1. puts - we know this one, just print a string to the screen
  2. get_password - this one is also familiar, guess it takes the password as input
  3. check_password - assume we check the inputted password here
  4. INT - No unlock_door?

There is no unlock_door function, but now there is a INT call. Recall from the manual that there was some information about this INTerrupt. Let’s take a look at it.

INT

In the manual, chapter 4 we can see a prototype in C of this interrupt function

INT

In main before the call to INT we see that 0x007f pushed to the stack as the argument for INT, looking up what this value triggers, we see the following:

0x7F

The unlock_door function from the previous lock has been removed and a call directly to INT is used instead. Looking at the previous locks unlock_door we actually see that this function does the same as main does now, with calling INT with 0x7F as the argument

check_password

So the goal here is to get main to call the INT function. Currently, the most interesting thing is the check_password function

╭ check_password();
0x448a      cmp   #0x6c58, 0x0(r15)
│       ╭─< 0x4490      jnz   $+0x001c
│       │   0x4492      cmp   #0x6571, 0x2(r15)
│      ╭──< 0x4498      jnz   $+0x0014
│      ││   0x449a      cmp   #0x7669, 0x4(r15)
│     ╭───< 0x44a0      jnz   $+0x000c
│     │││   0x44a2      mov   #1, r14
│     │││   0x44a4      cmp   #0x5b60, 0x6(r15)
│    ╭────< 0x44aa      jeq   $+0x0004
│    │╰╰╰─> 0x44ac      clr   r14
│    ╰────> 0x44ae      mov   r14, r15
0x44b0      ret

A bunch of compare instructions, this could indicate that we match the inputted password with some “hard-coded” valid password. There is a bit of a pattern, the 3 pairs of two lines, we compare two bytes from the address pointed to by R15, and then we do a jump if those two bytes are not the same. The other pairs offset the address from R15.

Then the value 0x01 is moved into R14, where after two more bytes are compared.

If the last compare is not the same, we do not jump, and we then clear R14 again, which we then move into R15 and return

╭ check_password();
0x448a      cmp   #0x6c58, 0x0(r15)
0x4492      cmp   #0x6571, 0x2(r15)
0x449a      cmp   #0x7669, 0x4(r15)
0x44a4      cmp   #0x5b60, 0x6(r15)

If we look only at the compare instructions and the value the compare with, we get a hint that this could be the password.

NOTE here that MSP430 is little endian, this mean that the data we see in the compare instructions are reversed order, so the first 0x6C58 is actually 0x58 0x6C, knowing this we can create a list of bytes that we think is the password. 0x58 0x6C 0x71 0x65 0x69 0x76 0x60 0x5B, all these bytes also fall in the ASCII range of values, so let’s translate that to a string Xlqeiv`[ lets try it out

Door unlocked

/microcorruption/