Internetwache RE60 Writeup: Symbolic Execution for the win

21 Feb 2016
on re and angr

(This challenge was performed entirely in EpicTreasure. If you don’t want to setup the tools listed in this writeup, simply install EpicTreasure and you are off to the races. Also, mirrored from my Praetorian post)

We begin by doing a bit of preliminary analysis to understand what the binary can do.

Hm.. so we are now seeing that we have the wrong characters. A slightly deeper view might help at this point. Our good friend radare2 can definitely help with this. Let’s find where we are in the binary currently.

At this point we only know that the .password file is being read in by fgetc. Let’s take a closer look at the for loop.

From the for loop, we see the fgetc and some black box function at 0x40079c. Beyond this function, there is only some check and a branch to either the previously seen Wrong characters message (boo) and a Congrats message (yay!). Something in this function is deciding if this password is legitimate.

For the purposes of this writeup, we don’t really care what this function is doing. We could substitute this function with other number crunching shenanigans if we wanted to.

At this point, we can see this could be a job for a symbolic execution engine. Let’s recap:

We read in a file containing a supposed password

This password is fed into a black box function that does some sort of validation

There is a clear yes/no answer after this validation step

And our path that we believe we can follow is shown below:

We take the leap of faith into the symbolic execution route and attempt to solve this purely symbolically.

I choose you, angr!

The only big hurdle at this point is determining how to represent this file symbolically. Luckily, angr makes this bit fairly painless. angr is a “platform-agnostic binary analysis framework developed by the Computer Security Lab at UC Santa Barbara and their associated CTF team, Shellphish.” (from their Github readme).

We also need a starting state in our execution. Because we will be executing from main forward, the entry_state is exactly what we need. This will begin execution at the entry point of the program. (If we were symbolically executing a smaller chunk of code, the blank_state would have been an more applicable state to choose).

state=p.factory.entry_state()

Now the fun part, getting our symbolic file up and running. One particular snag in symbolic execution is when the length of a given input is unknown. Thankfully, we are given an upper bound of the password length right above our for loop.

With an input lenth of 15 (0xf) in hand, we can construct our SimFile. We create a symbolic input of 15 bytes as our upper bound shown above. This input is then stored in a symbolic memory region. This symbolic memory region is then mapped to a SimFile where the filename .password is associated with it.

With the SimFile ready for action, we begin constructing the path constraints. We have highlighted a few places that we want to avoid when searching for a path. These places are essentially any place with an error or failed message. We begin a path_group starting at our entry_state. This path_group will manage all paths created and handle the checking of valid or invalid paths by verifying that each path has stayed away from the avoided locations.

These statements start the path traversal process of finding a valid path from main to our basic block that prints Congrats.

At this point we have a found path, but we need to solve the path to create a valid input that successfully completes the problem. We can ask angr to concretize the contents of a given file descriptor. We need to find the internal file descriptor of our file and pass that number to the posix.dumps utility to solve the path for the correct contents of the .password file.

Cory Duplantis

I am a senior security researcher for Cisco Talos and play on Samurai for CTFs. Being happily married, CTFs, tool development, and singing barbershop take up the majority of my time. This blog is the home for my CTF writeups, development tricks, and other random hacker tips.