Microcorruption: Sydney

In the last installment of my Microcorruption walk through, I learned how to bypass the password requirement of an MSP430-based electronic lock by setting breakpoints in the assembly language and finding where the password is stored and checked.

The general procedure so far is:

  • Set breakpoints on functions
  • Enter any password
  • Step through these functions
  • Examine memory and registers
  • Observe how password is checked

The next stage in the game is based in Sydney and features a lock with updated security, the Lock-It-All company having learned their lesson from my last exploit. This time, they have removed the hard-coded password, so I cannot simply dump memory and find it. Right, so let's begin then!

On the main screen I select Sydney, and I am transported to the now-familiar debugger screen, where a popup description tells me that Lockitall has become wise to hackers bypassing the previous iteration of the lock, and have removed the password from memory:

Great! It should be more of a challenge now, so I'll click "okay" and move to the main debugger screen. As usual, I will type b main to set a breakpoint on the main function, after which I type c to continue. The software runs until it hits my breakpoint, and I can immediately see that main calls check_password much like last time.

Also like last time, I will set a breakpoint on check_password and type c to continue. A popup appears that asks for a password, and here I enter my normal password and click send:

Once I click send, I have to continue as the debugger will automatically break, and doing so brings me to my breakpoint in check_password. Looking at the contents of that function, I am struck by the appearance of a number of CMP instructions, particularly the very first instruction. A brief examination of the logic here seems to show that, while the password is not hard coded into the software directly, it still looks like the password is compared against something static:

448a <check_password>
448a:  bf90 5e3e 0000 cmp	#0x3e5e, 0x0(r15)
4490:  0d20           jnz	$+0x1c
4492:  bf90 4b3b 0200 cmp	#0x3b4b, 0x2(r15)
4498:  0920           jnz	$+0x14
449a:  bf90 2c7e 0400 cmp	#0x7e2c, 0x4(r15)
44a0:  0520           jne	#0x44ac <check_password+0x22>
44a2:  1e43           mov	#0x1, r14
44a4:  bf90 7c53 0600 cmp	#0x537c, 0x6(r15)
44aa:  0124           jeq	#0x44ae <check_password+0x24>
44ac:  0e43           clr	r14
44ae:  0f4e           mov	r14, r15
44b0:  3041           ret

Sure enough, at 0x448a there is a compare of two bytes starting at byte 0x0 at the address in register 15 (which is 0x439c...the location of the entered password) against the immediate value of 0x3e5e, followed by a jump of 28 bytes (0x1c) if it doesn't match. This will take me to address 0x44ac which will lead me out of the function.

Each letter in an ASCII table corresponds to a byte, and the ASCII value for the first two letters of "brian" is 0x6272; definitely not equal to 0x3e5e, so the JNZ instruction will happen leading me out of check_password and presumably to the "invalid password" code at 0x4454. Just for fun, I will continue here and try to confirm my suspicions:

...
4450:  0f93           tst	r15
4452:  0520           jnz	#0x445e <main+0x26>
4454:  3f40 d444      mov	#0x44d4 "Invalid password; try again.", r15
4458:  b012 6645      call	#0x4566 <puts>
445c:  093c           jmp	#0x4470 <main+0x38>
445e:  3f40 f144      mov	#0x44f1 "Access Granted!", r15
...

Well, I don't land directly on the "invalid password" code, instead the jump instruction ultimately takes me out and I land on 0x4450 where register 15 is tested against 0x0, and if the test fails (i.e. r15 is not zero) the code jumps to main+0x26, which is address 0x445e, the "access granted" code!

By now I think I have a working theory, so I'll reset the debugger, keep my breakpoints and type c to run the code. When it stops at main, I want to find check_password in the code listing and examine all the CMP instructions to scrape the bytes they are comparing my password against.

After scraping all the CMP instructions for bytes, I have the byte string 0x3e5e3b4b7e2c537c. The entered password is compared two bytes at a time against that byte string. I suspect I can use the ASCII characters these bytes represent as the password, but I noticed on the password box that I can enter hexadecimal values as a password, and since I am far too lazy to look things up, I'll just paste these directly into the password box as hexadecimal and send it:

I am rewarded for my laziness with total failure. What did I do wrong? In my state of depression I pore over the code for check_password over and over. It should work, but it doesn't. Then I see it; looking at the opcodes to the left of the instructions, I notice that the byte-order is reversed. "Of course!" I yell, which makes everyone in the living room look at me strangely.

448a <check_password>
448a:  bf90 5e3e 0000 cmp	#0x3e5e, 0x0(r15)
4490:  0d20           jnz	$+0x1c
4492:  bf90 4b3b 0200 cmp	#0x3b4b, 0x2(r15)
4498:  0920           jnz	$+0x14
449a:  bf90 2c7e 0400 cmp	#0x7e2c, 0x4(r15)
44a0:  0520           jne	#0x44ac <check_password+0x22>
44a2:  1e43           mov	#0x1, r14
44a4:  bf90 7c53 0600 cmp	#0x537c, 0x6(r15)
44aa:  0124           jeq	#0x44ae <check_password+0x24>
44ac:  0e43           clr	r14
44ae:  0f4e           mov	r14, r15
44b0:  3041           ret

When I look at CMP #0x3e5e, 0x0(r15) I see the assembled code is bf90 5e3e 0000, so 0x3e5e resides in memory as 5e3e. So I scraped all the bytes out of the check_password function, but perhaps I didn't put them in the password box in the order that is needed. Switching the byte-order of the password string gives me 0x5e3e4b3b2c7e7c53, so I will put this in the password box and see what happens:

Success! Once again I am granted access to the LockIT Pro's super-secure locking system through cunning, persistence, and a little laziness:

As before, I have to return to the debugger, type solve to reset and run the system in "release" mode, use my new scraped, byte-reversed password and allow my operatives to enter the warehouse. Presumably this comes with a large "donation" to my imaginary bank account as well.


要查看或添加评论,请登录

Brian Mitchell的更多文章

  • Microcorruption - Hanoi

    Microcorruption - Hanoi

    So a while back I was reworking through Microcorruption, the wonderful online CTF that emulates a basic MSP430…

  • Microcorruption: New Orleans

    Microcorruption: New Orleans

    Years ago I worked through most of the challenging embedded security problems on the Microcorruption website. I have…

社区洞察

其他会员也浏览了