Microcorruption (Embedded Security CTF): Cusco

Wooo, another CTF level. This time it’s Cusco. Again, I’m not sure I’m doing these in order, but that’s alright.

What does this level have for us? More software updates!

This is Software Revision 02. We have improved the security of the    lock by  removing a conditional  flag that could  accidentally get    set by passwords that were too long.

Clearly, I’m doing things out of order, because yesterday’s post is for Johannesburg, which had software version 4. Oop.

Cusco Codeflow

Once again, main is a one-way trip to the login function.

If we look at the login function:

What’s going on here? We are:

If you read the post for Johannesburg, you know that we had two goals for that level: trick the overflow detection, and reroute program flow.

Since it doesn’t look like there’s overflow detection here, we just have to reroute the program flow (I think?)

Let’s give it a try.

Testing Out Password Length

The program says we can’t use more than 16 characters, yet it’s passing an argument of “0x30” (decimal 48) to the gets function… soooooooo 🤷‍♀️

Let’s try out a longer input.

First, I put a breakpoint at 453a. Then, I entered in “AAAABBBBCCCCDDDDEEEE” (length 20) to see what might happen:

After we’ve stopped at our breakpoint, we can see that it copied the entire string over. If it were enforcing the 16-char length, the “E"s would get cut off.

As with Johannesburg, we’ve kind of abandoned the idea of getting the password right. Instead, we’re trying to use the return statement at the end of login to re-route the program to a different function, instead of just ending execution.

What does that mean for you, reader? Type s to step once, and you’ll see that we’ve added 0x10 to the stack pointer, and which is now pointing to:

We’re one instruction away from returning, and we’re headed straight towards *squints* “EE”.

If you step again, you’ll get a message like so:

insn address unaligned

That’s because 0x4545 (“EE”) isn’t a valid place to go to. So let’s find out somewhere else to go.

How about the unlock function? It doesn’t take any arguments, it just… unlocks the door. Seems like a poor design choice but okay.

Its address is “4446”. Instead of messing around with the “AAAABBBB…” etc nonsense, we could just send the address repeatedly. Or not. It’s up to you. I mistyped the input too many times and lost patience, so repeated-address-input it is.

Cusco Solution

I repeated the “new” address of “4644”* 9 times:

464446444644464446444644464446444644

*adjusted for endianness

If you stop at the end of login, you’ll see that we’ve overwritten the return address, and now we’re on our way to 4446 (unlock_door)

To complete this level, type solve and then enter the payload of “464446444644464446444644464446444644”.