Technique – ROPi (Migrating ROP Chains)

During the last two weeks, I participated in the IceCTF competition. During this event, I came across an interesting challenge called ROPi. I made an attempt at this challenge, which I will now record for future reference.

Note that this is not a writeup: the (a!) correct solution is far simpler (re-use the “ezy” function to create a new exploitable condition, after each rop chain), this is simply documentation regarding an exploitation technique which I found amusing.

This challenge was presented as a Linux binary, download here: ropi

Upon initial investigation, it is clear there is a stack overflow vulnerability in the “ezy” function, as illustrated below:

ropi_vulnerable

Some further cursory information gathering also reveals that:

  • the stack is marked as not executable, making a trickier return-based exploit necessary.
  • there are three other functions: ‘ret’, ‘ori’ and ‘pro’, which open the flag file, read the flag and print it respectively – simply put, we should be able to treat them as giant rop gadgets.

Some initial testing reveals that a rop chain is a sensible solution, but we quickly run into problems: the space we have to overflow isn’t very long, and we’re not able to string together three functions to form a rop chain.

A bit more time in the disassembly reveals that each of these functions ends with ‘leave’ / ‘ret’.

According to traditional wisdom, it is easiest to avoid ROP gadgets ending with ‘leave’ / ‘ret’, as ‘leave’ wrecks your stack – but it is possible to leverage this to “migrate” our rop chain, rewriting ESP to point to a location we control (preferrably with more space), and then executing ‘ret’ from there.

We can leverage this in this case as follows:

  • Initial (“stage 1”) ROP against “read”, reading an arbitrary number of bytes into a static offset in the “flag” buffer.
  • Controlling EBP to point to an appropriate location in “flag” buffer, we use a ‘leave / ret’ gadget to migrate ESP to our controlled EBP.
  • The ‘ret’ instruction pops an address off our stack, which is in ‘flag’, executing the new code we supplied to the previous ‘read’ call (“stage 2” – without the arbitrary length limit).

A screenshot of this being exploited is below:

ropi_2stage

As you can see, ESP is now at an unusual-but-controllable address, with the contents of the stack within our control.

Note that this does’t seem to work – a second function call to ‘open’ to get the flag file seems to break the application deep down the call chain; I’m not currently sure why.

At this point, I stopped investigating this challenge, as another team member successfully solved it. You can find the source code for my abortive foray here. It has some extra hardcoded ROP gadget addresses to play with, if you care to explore the technique.

About Norman

Sometimes, I write code. Occasionally, it even works.
This entry was posted in Bards, Jesting. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s