TIL that the capital of Uruguay is Montevideo. This is the next level in Microcorruption, which was unlocked after I completed Whitehorse.
If we read the release notes, it says:
Lockitall developers have rewritten the code to conform to the internal secure development process.
Lol okay, whatever that means.
Hahaha oh no. Let’s get started!
If we have a look around, we see:
Login is a bit longer this time:
44f4 <login> 44f4: 3150 f0ff add #0xfff0, sp 44f8: 3f40 7044 mov #0x4470 "Enter the password to continue.", r15 44fc: b012 b045 call #0x45b0 <puts> 4500: 3f40 9044 mov #0x4490 "Remember: passwords are between 8 and 16 characters.", r15 4504: b012 b045 call #0x45b0 <puts> 4508: 3e40 3000 mov #0x30, r14 450c: 3f40 0024 mov #0x2400, r15 4510: b012 a045 call #0x45a0 <getsn> 4514: 3e40 0024 mov #0x2400, r14 4518: 0f41 mov sp, r15 451a: b012 dc45 call #0x45dc <strcpy> 451e: 3d40 6400 mov #0x64, r13 4522: 0e43 clr r14 4524: 3f40 0024 mov #0x2400, r15 4528: b012 f045 call #0x45f0 <memset> 452c: 0f41 mov sp, r15 452e: b012 4644 call #0x4446 <conditional_unlock_door> 4532: 0f93 tst r15 4534: 0324 jz #0x453c <login+0x48> 4536: 3f40 c544 mov #0x44c5 "Access granted.", r15 453a: 023c jmp #0x4540 <login+0x4c> 453c: 3f40 d544 mov #0x44d5 "That password is not correct.", r15 4540: b012 b045 call #0x45b0 <puts> 4544: 3150 1000 add #0x10, sp 4548: 3041 ret
Basically, we are:
- Prompting the user for a password, and warning them about password length.
- Getting the user’s input
- Strcpy-ing that input elsewhere
- Using memset
- Then reporting back to the user if their attempt worked or not.
- Then adding 0x10 to the stack pointer and returning.
Conditional_unlock_door looks very similar (possibly identical?) to the function in Whitehorse. If you remember from that level, we ignored the
conditional_unlock_door function and focused on the interrupt.
We overwrote the interrupt type to be “7f” which means “unconditionally unlock the door.” For a refresher on the interrupt types, take a look at the manual.
Since we’ve got the “add 0x10 and return” thing going on here, too, let’s try to use a buffer overflow to redirect the program.
Redirecting => Interrupt
From the Whitehorse level, you might remember that we gave an input of:
The ‘3245’ in there refers to the location of the interrupt function in that level. It’s different for Montevideo, though.
We can see that it’s 0x454c, which we need to enter as “4c45” instead.
So, we have:
Let’s give that a shot, with a breakpoint set at the end of
And as expected, we get to here:
If we step over this, we see that r14 gets a value of… 44. Wait, what?
We told it to have “7f”. What’s going on?
If we looked at 0x2400 block of memory after the
gets call, we would see:
We sent “414141414242424243434343444444444c457f007f00” and it’s all there. So far, so good.
But after the
strcpy, we see that the last part of our string is truncated.
Why is this happening?
My guess is that strcpy sees a 0x0 and thinks that it’s a null byte, and the string should be terminated. That means we’ll have to use something else instead of “00”.
Buffer Overflow 2: Electric Boogaloo
If we try this again, but we get rid of the 0’s at the end of our string (lest they be mistaken for null bytes), we have:
The ending “00” is fine, and in fact, we need it so that the
sr doesn’t get messed up.
If we use our breakpoint and stop at the INT function (after the
ret at the end of
We can see that our memory now looks like this. Two bytes over from the stack pointer is “7f00” instead of “0044” (from before we fixed our null char issue).
If we step a few times, we see that our attempt to overwrite the interrupt type from 7e to 7f worked:
Our payload to redirect the program and overwrite the conditional interrupt type to be conditional, via buffer overflow, is:
To solve this level, type
solve and then enter the payload.