Microcorruption challenge I

Some days ago, I found a link to Matasano’s Microcorruption Challenge. This is a set of challenges focused mainly on Reversing and Exploiting of embedded devices.
Something I found really cool about this challenge was that, even if it’s a RE challenge, you don’t need to set up a special environment or use special tools. Everything is in the browser!!!.
Each challenge simulates a different lock controlled by an embedded device. Each of these locks has a different vulnerability you have to find in order to pass each of the challenges. They provide you with a disassembler and a debugger. They also give you a small manual where they roughly explain the instructions of the lock.
This is my first contact with embedded devices, so I apologize in advance for the possible mistakes and wrong assumptions.
For the first challenge, all you have to do is follow a tutorial where they explain you how to use the debugger, the commands, etc. so I am going to skip it.

New Orleans (10 points).

Lockitall                                            LOCKIT PRO r a.01
______________________________________________________________________

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


OVERVIEW

    - This is the first LockIT Pro Lock.
    - This lock is not attached to any hardware security module.


DETAILS

    The LockIT Pro a.01  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 01.

    


(c) 2013 LOCKITALL                                            Page 1/1

Taking a quick look at the disassembly, we can see the following routines:

0010 <__trap_interrupt>
4400 <__init_stack>
4404 <__low_level_init>
440e <__do_copy_data>
4424 <__do_clear_bss>
4438 <main>
4474 <__stop_progExec__>
447a <__ctors_end>
44b2 <get_password>
44bc <check_password>
44d6 <unlock_door>
44e2 <__do_nothing>
4530 <INT>
4548 <putchar>
4560 <getchar>
4584 <getsn>
4594 <puts>
45c0 <_unexpected_>

If we look at the main function, we can see that first, the program calls to the routine create_password, then it asks for the user’s password (get_password), then it checks if the password is correct with the function check_password. Finally, it decides if it unlocks the door or not, depending on the result of check_password.
I found two ways of solving this.
The first one was by setting a breakpoint in the function check_password and checking what it does.
If we stop at the first comparison in the code, we can see that it is comparing the value stored in the address indicated by r13 with the value in 0x2400(r14).

44bc <check_password>;
44bc:  0e43           clr	r14
44be:  0d4f           mov	r15, r13
44c0:  0d5e           add	r14, r13
44c2:  ee9d 0024      cmp.b	@r13, 0x2400(r14)
44c6:  0520           jne	#0x44d2 <check_password+0x16>
44c8:  1e53           inc	r14
44ca:  3e92           cmp	#0x8, r14
44cc:  f823           jne	#0x44be <check_password+0x2>
44ce:  1f43           mov	#0x1, r15
44d0:  3041           ret
44d2:  0f43           clr	r15
44d4:  3041           ret

Let’s take a peek at the registers:
mcI1
These values indicate that the instruction cmp.b @r13, 0x2400(r14) compares the first byte pointed by r13 (“.b” indicates that the size of the operands is a byte) with the first byte in the memory address 0x2400. So we should check what we have there.
mcI2
In r13, we have the string “ojete”, which is the string I introduced when I was prompted for the password. Since “ojete” is a string, it finishes with 00. This indicates the end of the string.
In 0x2400, we have some bytes that are being compared to our string, so we can assume that there is a string there too. If we take the characters until the end of the string (00), we have “34 5c 52 2e 6c 70 7d”. If we then introduce this string, the lock will be open:
345c522e6c707d
I introduced the string as hexadecimal values because I thought the character 2e was not printable. But I checked it and I realized it was just a “.”, so I thought I could also introduce:
4R.1p}
But for some reason, it crashes.
The second way I found to solve this challenge was by checking the string generated by the function create_password, which is the one in the offset 0x2400.

Sidney (15 points)

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

In this challenge, there is no create_password function, so let’s have a look at the check_password function again:

448a <check_password>
448a:  bf90 425b 0000 cmp	#0x5b42, 0x0(r15)
4490:  0d20           jnz	$+0x1c
4492:  bf90 4461 0200 cmp	#0x6144, 0x2(r15)
4498:  0920           jnz	$+0x14
449a:  bf90 435d 0400 cmp	#0x5d43, 0x4(r15)
44a0:  0520           jne	#0x44ac <check_password+0x22>
44a2:  1e43           mov	#0x1, r14
44a4:  bf90 7038 0600 cmp	#0x3870, 0x6(r15)
44aa:  0124           jeq	#0x44ae <check_password+0x24>
44ac:  0e43           clr	r14
44ae:  0f4e           mov	r14, r15
44b0:  3041           ret

In 448a, the function compares r15 to the value 0x5b42. If they are not equal, it will jump to 44ac, i.e. the end of the function. Consequently, we will need to have the value 0x5b42 in the beginning of r15. If we check the rest of the cmp instructions, we will see that first, we want 0x5b42, followed by 0x6144, then 0x5d43, and, finally, 0x3870.
Concatenating these values, and converting the result into ASCII, we get the following string: “[BaD]C8p”. It looks good! Let’s give it a try…
mcI3
Oh, wait!! LE WILD ENDIANESS TROLL APPEARS!! So if we invert the order of each pair of characters ([B ->B[ ; aD -> Da ; etc.) , we have the solution:
B[DaC]p8

Hanoi (20 points)

Lockitall                                            LOCKIT PRO r b.01
______________________________________________________________________

              User Manual: Lockitall LockIT Pro, rev b.01              
______________________________________________________________________


OVERVIEW

    - This lock is attached the the LockIT Pro HSM-1.
    - We have updated  the lock firmware  to connect with the hardware
      security module.


DETAILS

    The LockIT Pro b.01  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-1.   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 1 stores  the login password,
    ensuring users  can not access  the password through  other means.
    The LockIT Pro  can send the LockIT Pro HSM-1  a password, and the
    HSM will  return if the password  is correct by setting  a flag in
    memory.
    
    This is Hardware  Version B.  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-1 should  be
    connected to port 2.

    This is Software Revision 01,  allowing it to communicate with the
    LockIT Pro HSM-1

    


(c) 2013 LOCKITALL                                            Page 1/1

In this lock, main calls to login. The function login has most of the logic of the lock. It first prompts for a password containing 8 to 16 characters.
mcI4
Then, it tests if the password is valid by communicating with the HSM1.
We can see it when function test_password_valid calls to INT:

4454 <test_password_valid>
4454:  0412           push	r4
4456:  0441           mov	sp, r4
4458:  2453           incd	r4
445a:  2183           decd	sp
445c:  c443 fcff      mov.b	#0x0, -0x4(r4)
4460:  3e40 fcff      mov	#0xfffc, r14
4464:  0e54           add	r4, r14
4466:  0e12           push	r14
4468:  0f12           push	r15
446a:  3012 7d00      push	#0x7d
446e:  b012 7a45      call	#0x457a <INT>
4472:  5f44 fcff      mov.b	-0x4(r4), r15
4476:  8f11           sxt	r15
4478:  3152           add	#0x8, sp
447a:  3441           pop	r4
447c:  3041           ret

The manual provided in the challenge shows the following:

INT
Declaration:
void INT(int arg, …);
Trigger interrupt given by arg, passing additional arguments.
Range:
The value of arg must be within the range of 0 to 0x7F (inclusive).

The last argument pushed to the stack is 0x7d. So it is calling INT(0x7d,...). Again, looking at the manual:

INT 0x7D.
Interface with the HSM-1. Set a flag in memory if the password passed in is
correct.
Takes two arguments. The first argument is the password to test, the
second is the location of a flag to overwrite if the password is correct.

This means that we can’t have access to the password and we will need to figure out a different way to trick the lock.
Let’s take a closer look at the login function.

4520 <login>
4520:  c243 1024      mov.b	#0x0, &0x2410
4524:  3f40 7e44      mov	#0x447e "Enter the password to continue.", r15
4528:  b012 de45      call	#0x45de <puts>
452c:  3f40 9e44      mov	#0x449e "Remember: passwords are between 8 and 16 characters.", r15
4530:  b012 de45      call	#0x45de <puts>
4534:  3e40 1c00      mov	#0x1c, r14
4538:  3f40 0024      mov	#0x2400, r15
453c:  b012 ce45      call	#0x45ce <getsn>
4540:  3f40 0024      mov	#0x2400, r15
4544:  b012 5444      call	#0x4454 <test_password_valid>
4548:  0f93           tst	r15
454a:  0324           jz	$+0x8
454c:  f240 5700 1024 mov.b	#0x57, &0x2410
4552:  3f40 d344      mov	#0x44d3 "Testing if password is valid.", r15
4556:  b012 de45      call	#0x45de <puts>
455a:  f290 8800 1024 cmp.b	#0x88, &0x2410
4560:  0720           jne	#0x4570 <login+0x50>
4562:  3f40 f144      mov	#0x44f1 "Access granted.", r15
4566:  b012 de45      call	#0x45de <puts>
456a:  b012 4844      call	#0x4448 <unlock_door>
456e:  3041           ret
4570:  3f40 0145      mov	#0x4501 "That password is not correct.", r15
4574:  b012 de45      call	#0x45de <puts>
4578:  3041           ret

Inside the function, we can easily find our “bad boy” and our “good boy”:

4562:  3f40 f144      mov	#0x44f1 "Access granted.", r15 //GOOD BOY
4566:  b012 de45      call	#0x45de <puts>
456a:  b012 4844      call	#0x4448 <unlock_door>
456e:  3041           ret
4570:  3f40 0145      mov	#0x4501 "That password is not correct.", r15 //BAD BOY
4574:  b012 de45      call	#0x45de <puts>

So, how can we reach the good boy instead of the bad boy? Let’s zoom out a bit.

455a:  f290 8800 1024 cmp.b	#0x88, &0x2410
4560:  0720           jne	#0x4570 <login+0x50>
4562:  3f40 f144      mov	#0x44f1 "Access granted.", r15
4566:  b012 de45      call	#0x45de <puts>
456a:  b012 4844      call	#0x4448 <unlock_door>
456e:  3041           ret
4570:  3f40 0145      mov	#0x4501 "That password is not correct.", r15
4574:  b012 de45      call	#0x45de <puts>
4578:  3041           ret

The lines highlighted above compare the value 0x88 with whatever is stored in the offset 0x2410. If they are equal, we will arrive to our good boy. Is there any way we can affect the value stored in that offset? First, let’s take a look at the memory around that position:
mcI5
We have the position we want to override right after the string we have introduced. It’s a pity we only have 16 characters for the password. Otherwise, maybe we could… Oh wait! What is that getsn function?

4534:  3e40 1c00      mov	#0x1c, r14
4538:  3f40 0024      mov	#0x2400, r15
453c:  b012 ce45      call	#0x45ce <getsn>

It seems like it receives the address of our buffer and a value. The manual says:

gets
Declaration:
void gets(char* buf, unsigned int length);
Copies at most length (including the terminating null byte) bytes from
the input device into buf.
Range:
The buffer buf must contain at least length bytes of space

Although it’s not the same function, I will assume the way they work is similar. If this is true, we could write up to 0x1c characters. Since 0x1c is 28 in decimal, we’d have 28 characters, which would allow us to override the value in 0x2410.
Let’s try with 16 “a” followed by 0x88.
mcI6
It seems like we have overridden it! Let’s continue with the execution, and… Door unlocked!!
Solution:
6161616161616161616161616161616188
Describing my process to solve these challenges helps me understand better what I am doing. Since I am really enjoying myself with these, I will try to post some more soon!

References

[1] MSP430 instruction set

2 comments

  1. XA3AAP · September 2, 2014

    Hello buddy,
    I did all of these levels. But I stuck in the level which has encryption and HSM-1 module. I tried the level which has encrypted password and the level which had connected HSM-1. In my opinion, in the Cusco level we should reset the password, because we cant see the HSM-1 module. Did you do that one? please share with me if you have any idea to beat this level

    • xgusix · September 2, 2014

      Hey, you have the answer for Cusco in the second part of this post: http://xgusix.com/blog/microcorruption-challenge-ii-2/

      TLDR: Cusco is not a Reverse Engineering challenge, it’s a buffer overflow exploitation challenge, and that what you have to look for 🙂