
Microcorruption CTF Sydney Write-up
- 2 minsSummary:
This is a write-up of my solution to the Microcorruption CTF challenge “Sydney” (LOCKIT PRO r a.02
).
Let’s again begin by first taking a look inside the main function:
4438 <main> | |
4438: 3150 9cff add #0xff9c, sp | |
443c: 3f40 b444 mov #0x44b4 "Enter the password to continue.", r15 | |
4440: b012 6645 call #0x4566 <puts> | |
4444: 0f41 mov sp, r15 | |
4446: b012 8044 call #0x4480 <get_password> | |
444a: 0f41 mov sp, r15 | |
444c: b012 8a44 call #0x448a <check_password> | |
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 | |
4462: b012 6645 call #0x4566 <puts> | |
4466: 3012 7f00 push #0x7f | |
446a: b012 0245 call #0x4502 <INT> | |
446e: 2153 incd sp | |
4470: 0f43 clr r15 | |
4472: 3150 6400 add #0x64, sp |
This looks similar to the last binary, however, we can see that the create_password()
subroutine was removed. A function called check_password()
exists and we can see that after the call is returned, r15
is tested. If that register does not contain 0
, the code will eventually hit the jmp
instruction at 0x445c
and will subsequently exit without unlocking the door, so we need to make sure that when the call is returned, r15
contains a non-zero value.
Let’s dig deeper and see what’s going on inside check_password()
:
448a <check_password> | |
448a: bf90 3622 0000 cmp #0x2236, 0x0(r15) | |
4490: 0d20 jnz $+0x1c | |
4492: bf90 5355 0200 cmp #0x5553, 0x2(r15) | |
4498: 0920 jnz $+0x14 | |
449a: bf90 5d59 0400 cmp #0x595d, 0x4(r15) | |
44a0: 0520 jne #0x44ac <check_password+0x22> | |
44a2: 1e43 mov #0x1, r14 | |
44a4: bf90 3356 0600 cmp #0x5633, 0x6(r15) | |
44aa: 0124 jeq #0x44ae <check_password+0x24> | |
44ac: 0e43 clr r14 | |
44ae: 0f4e mov r14, r15 | |
44b0: 3041 ret |
We can see that there are 4 cmp
instructions occurring which will compare 8 hard-coded bytes, 2 at a time with 2-byte offsets from r15
(the start of our input in memory). If execution can reach the final cmp
instruction, the program will jump over the clr r14
instruction at 0x44ac
, which means that when mov r14, r15
is executed, r15
will have a non-zero value (and instead will contain 0x1
which was set by the previous 44a2: mov #0x1, r14
instruction). Once execution is returned back to main()
, the subsequent tst r15
instruction will cause the jump to 0x445e
to occur, which will print the access granted message and proceed to unlock the door. Let’s grab those 8 hard coded bytes and try it out. Don’t forget that MSP430 byte pairs are little-endian, so we’ll need to reverse the byte order.
Flag (mouse over to reveal)
362253555d593356