May 01, 2019

Microcorruption - Tutorial

I’ve been playing the Microcorruption CTF since last few weeks & now I’m going to brag about it. Before starting, let me tell you that it is an embedded security ctf & its challenges are based on MSP430 microcontroller. Also keep in mind that the architecture we’ll be working on is 16-bit & I assume that you are not a noob & have some experience with assembly & pwning. So let’s start.


THE CHALLENGE

This is how the whole interface looks like.

The first level to solve is the TUTORIAL level where you’ll be shown how the whole thing works. So don’t skip it. It’ll introduce you to all the commands necessary for debugging. You can also use help command in debugger console to print out all the releveant commands.

> help

Valid commands:
  Help - show this message
  Solve - solve the level on the real lock
  Reset - reset the state of the debugger
  (C)ontinue - run until next breakpoint
  (S)tep [count] - step [count] instructions
  step Over / (N)ext - step until out or pc is next instruction
  step Out / (F)inish - step until the function returns
  (B)reak [expr] - set a breakpoint at address
  (U)nbreak [expr] - remove a breakpoint
  (R)ead [expr] [c] - read [c] bytes starting at [expr]
  track [reg] - track the given register in memory
  untrack [reg] - removes the tracking of the given register
  (L)et [reg]/[addr] = [expr] - write to register or memory
  Breakpoints - show a list of breakpoints
  Insncount - count number of CPU cycles executed
  Manual - show the manual for this page

Scripting commands:
  #define name [commands] - alias "name" to run [commands].
  command;command - run first command, then second comamnd.

List of types:
  [reg] := 'r' followed by a number 0-15
  [addr] := base-16 integer or label name (e.g., 'main')
  [expr] := [reg] or [addr] or
            [expr]+[expr] or [expr]-[expr]

You’ll also need the LockIT Pro Manual & Assembler for solving the challenges.

I won’t be talking about the debugger commands & their purpose but I’ll be mentioning the assembler mnemonics & their purpose wherever necessary.

Now let’s proceed to solve the first level.
I always start with examining the main function.

4438 <main>
4438:  3150 9cff      add	#0xff9c, sp
443c:  3f40 a844      mov	#0x44a8 "Enter the password to continue", r15
4440:  b012 5845      call	#0x4558 <puts>
4444:  0f41           mov	sp, r15
4446:  b012 7a44      call	#0x447a <get_password>
444a:  0f41           mov	sp, r15
444c:  b012 8444      call	#0x4484 <check_password>
4450:  0f93           tst	r15
4452:  0520           jnz	#0x445e <main+0x26>
4454:  3f40 c744      mov	#0x44c7 "Invalid password; try again.", r15
4458:  b012 5845      call	#0x4558 <puts>
445c:  063c           jmp	#0x446a <main+0x32>
445e:  3f40 e444      mov	#0x44e4 "Access Granted!", r15
4462:  b012 5845      call	#0x4558 <puts>
4466:  b012 9c44      call	#0x449c <unlock_door>
446a:  0f43           clr	r15
446c:  3150 6400      add	#0x64, sp

Many other functions are being called in main but as of now, they are not to be concerned except the get_password, check_password & unlock_door function.

Interpreting that the commands has the pattern operation source,destination, we can observe that instruction at address 0x4446 calls get_password and instruction at 0x444c calls check_password. Right above each of them, there is mov sp, r15 basically telling us get_password is storing it at r15 and check_password is checking it from r15. The instruction at address 0x4450 runs tst r15 which tests if r15 is equal to 0 or not. The next instruction at address 0x4452 runs jnz #0x445e <main+0x26> which jumps & executes the instruction at address 0x445e if the result from the previous operation is 0 otherwise it’ll continue to the next instruction. If the jump is successful, then the door will be unlocked as the string Access Granted! is being moved into register r15, a call to puts is being made in order to print it and, finally, a call to unlock_door that, obviously, unlocks the door and completes the level. But if the jump is unsuccessful, the string Invalid password; try again. is being moved into register r15, a call to puts is being made in order to print it and another jump instruction is being executed at 0x445c which further executes the instruction at 0x446a & clears the content of r15 & ends the program. That’s how the main function works here. Now let’s move on to the exploitation part.

SOLUTION

This challenge is really simple. If you’ll follow the tutorial, you will notice that the vulnerability you need to exploit in this challenge is simply a length based one as the check_password routine simply checks if the password has a length of 9.

4484 <check_password>
4484:  6e4f           mov.b	@r15, r14
4486:  1f53           inc	r15
4488:  1c53           inc	r12
448a:  0e93           tst	r14
448c:  fb23           jnz	#0x4484 <check_password+0x0>
448e:  3c90 0900      cmp	#0x9, r12
4492:  0224           jeq	#0x4498 <check_password+0x14>
4494:  0f43           clr	r15
4496:  3041           ret
4498:  1f43           mov	#0x1, r15
449a:  3041           ret

Once you hit the instruction at 0x4484, the first character of the password you entered is loaded into r14 from the memory location pointed to in r15. Next, the registers r12 and r15 are incremented. This will continue until a null byte is reached, causing the jump at 0x448c not to be followed, making the cmp be the next instruction.

If r12 ends up being 0x0009, indicating that out passwords was 8 characters long with a null byte(\0), then the jump at 0x4492 will occur, finally calling the interrupt to unlock the lock. For solving this challenge enter any 8 character string.

PASSWORD : hackpass
PASSWORD[hex] : 6861636b70617373


Hope you understood this one. It’s an extremely easy one.
I’ll keep posting on for other challenges until I get bored writing them.
Till then, Good Bye !!!