Okay. Super late write up right here.
Anyway, as you, dear reader, may not be aware of, me and some friends participated in the Hack the Vote CTF 2016 this last November. I wasn’t able to work on the puzzles as much as I wanted to because of work obligations, but I was able to solve a really interesting reverse engineering problem that I think you might find interesting.
Reversing 100 (Consul)

As a greenhorn in the magnificent field of reverse engineering, this was the only one that I was able to manage in the short amount of time that the challenge was open, but it’s better than nothing I guess, and I believe that other greenhorns such as myself would learn very much from this very simple example of reverse engineering. And so, off we go!
Requirements
- REC Decompiler (a decompiler obviously)
- gdb (a debugger)
Process
- Download the ELF binary by clicking the “consul” link the description of the challenge and try running it. We want to be able to observe what the binary does normally before we break it down into tiny little pieces.
Sad - Nothing useful from there. Go ahead and decompile the ELF binary with the REC Decompiler, and then locate the main function.
- Alright. Now let’s look at the other interesting functions above the
main
function.
- These, aside from the main function, are the only ones whose names are not gibberish, so it may be possible that the solution to the problem might indeed be in one of these functions, but if you look at the main function again, it doesn’t seem to access any of the functions above.
- Luckily for us though, we can arbitrarily call functions from ELF binaries by using the wonderful tool called “gdb” – also known as the GNU Debugger. So just go pass the ELF as a parameter to the tool in question, and we’ll be doing the magic along the way.
- So, first, we’d want to be able to get a hold of the application in it’s initial state, so we are going to have to stop at the
main
function once the application execution gets there. To do this, just do abreak main
after entering gdb in order to schedule the suspension of the application’s execution immediately after entering themain
function, and then do arun
to start the program’s execution.
- Now, let’s try calling some functions. You can arbitrarily call functions in the ELF binary using a really neat command called
call
.
- Only
real_help
seems to work. I think it was trying to give people a clue. Something about the Fibonacci sequence, but I never really understood the purpose, and I was able to finish the challenge even while ignoring it. - Let’s just take a closer look at the other functions and see where they fail.
- Let’s do the
dont_call_me
function first. Since we already called the other functions, let’s start gdb again and call thedont_call_me
function so we’d avoid any of the possible unintended modifications that the other functions may have made to the environment when we tested them previously.
- The
dont_call_me
function failed as expected. By observing the back trace using thebt
command, we can see that the program stopped inside a function that is inside thesub_41F2
function. Now, thesub_41F2
function only contains a handful of calls to other functions, so it would only be one of the following.
- Let’s see if it’s the
strlen
function. To check, simply add abreak
tostrlen
and then call thesub_41F2
function.
- As you see, the program stopped at the start of
strlen
. We then entered thefinish
command so that the program would execute until thestrlen
function finished. There doesn’t seem to have been any problems with thestrlen
function because the segmentation fault occurred AFTER it finished (as indicated by the segmentation fault message). That means, the problem occurs either on them0
function, or the otherstrlen
function. - Let’s check the
m0
function next. As you can see in the code below,m0
is actually a variable meant to contain a pointer to a function which is supposed to be called on the*m0();
line below.
- However, upon inspecting the contents of the
m0
variable using thep
command, it seems that it contains a reference toNULL
so naturally the program WILL throw a segmentation fault for attempting to callNULL
as a function.
- A quick search in the source code reveals that the
m0
variable is initialised inside thec55
function.
- However, the
c55
function is never actually called anywhere and directly calling thec55
function causes and infinite loop.
- Let’s restart gdb to get rid of the breakpoints and then let’s try setting the
m0
variable directly.
- Now let’s try calling the
dont_call_me
function again.
- Looks like it’s still broken. Buuuuuuut… look carefully at the decompiled code. There’s another
malloc
function there residing on a different address. This might be themalloc
function that’s being set to them0
variable.
- Now let’s set
m0
to that address. Good thing the decompiler outputs the addresses of decompiled functions (as indicated in the comment below the declaration of themalloc
function).
- Now let’s call
dont_call_me
function again. - >mfw
MOM, GET THE CAMERA! #MLG #360NOSCOPE #GITREKT - It works. But there doesn’t seem to be anything useful in the
dont_call_me
function. Let’s try the other functions.
Illuminati Confirmed? [Insert X-Files Theme Music] - It seems the other functions started working once we set the
m0
variable to the right value. Now search form0
in the source code and you will find that the functions that referencem0
aresub_41F2
,sub_9F36
, andsub_198A
. The functions that, in turn, reference these functions aredont_call_me
,help
,c8
, andfake_help
. We haven’t triedc8
yet, so we just might find the answer there.What’s that? “Jet fuel can’t melt steel beams”? - Gibberish. But to be sure, let’s do it again.
“Harambe was an inside job”? - Different gibberish. I wonder what will happen if we keep doing it over and over again.
“Lizard people are running the White House”!? - Suddenly… [insert x-files theme music]
The plot thickens… - That’s not the flag though. We need to go deeper.
Voila! - And finally, we have our flag, which is
flag{write_in_bernie!}
.
And that’s it for now folks. I hope you enjoyed this CTF write up despite it being a month late. I surely did enjoy writing it. Anyway, if you need the binary and the decompiled source code, I have attached them onto the section below.