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
puts
- we know this one, just print a string to the screenget_password
- this one is also familiar, guess it takes the password as inputcheck_password
- assume we check the inputted password hereINT
- Nounlock_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 INT
errupt. Let’s take a look at it.
INT
In the manual, chapter 4 we can see a prototype in C of this interrupt function
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:
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