Recently my friend Colin started the HackerOne CTF and encouraged me to participate as well. I know nothing about web hacking and most of the CTF is web based. I’ve installed Burp Suite and messed around with it a little bit. I have only found two of the web based flags so far and have been struggling to find more. Web hacking seems really fun and interesting but I have big gaps in my knowledge. I need to spend time learning more of the fundamentals and tools used before continuing the web based CTF’s.
There are flags for two other categories: Android and Native. In this post I’ll be talking about how I found the flag for
When beginning this CTF you’re met with a webpage asking for your name which it takes in
stdin. There’s also a download link for the binary.
The binary, named
vulernable, has no file extension so I opened it in 010 Editor to get a better idea.
Googling for “ELF magic number” gives me the answer right away. Utilizing the headers listed in the article I can see this file is 64-bit. This was pretty intimidating at first because I have only used Linux when setting up my droplet(which hosts this WordPress) on Digitial Ocean. So far I’ve had very limited experience with Linux, and the same goes for 64-bit assembly.
vulnerable looks like this when opened in IDA.
And the pseudocode of
main produced by IDA looks like this.
Right away I’m seeing similarities between this and Colin’s CTF Stage 5. There’s
0x20 bytes of memory allocated for the user input but the only check on the input is if it exists or not. I can input 32 characters to fill up the buffer, then another 8 characters for the address of
ebp that’s pushed during the prologue. Then we’re at the address pushed before the function was called, the return address.
Just like in Stage 5 I need to overwrite the return address with the address of the
print_flags function to get the flag I’m after. Before attempting this in my browser I wanted to be sure I could get it to work in a debugger.
So next I installed VirtualBox. I’ve never used a virtual machine before so this was a learning experience as well. After following some guides I had Ubuntu installed on my virtual machine and I was ready to debug using gdb. My friend Colin was nice enough to put me on to gdb-dashboard which is absolutely fantastic!
Here’s what the stack looks like after the buffer is filled with 32
A‘s, followed by the address of
ebp and then the return address in red.
I used hexcurse to setup a
.txt file that would fill the buffer and overwrite the return address with the address of
Now with the file ready I can redirect it to
run < file.txt and hopefully I should end up inside
print_flags. Here’s the stack before the input file.
And here it is after with the return address successfully overwritten.
And after the return.
Alright! Now I’m finally ready to get my flag by solving this in my browser. It was a lot of work to get to this point but it felt really good.
I started trying to solve it using alt codes but that wasn’t working for me. I noticed my input was going into the URL bar and figured out I could use percent-encoding to create the string of hex bytes to pass to
stdin in my web browser and get my flag.
In reality this challenge took me a bit longer than it should have. This being my first 64-bit program I’ve reversed I was not comfortable with seeing an 8-byte address and so originally I didn’t even correctly identify
0x7FFFF7A05B97 as the return address. I skimmed over it and immediately focused all my attention on the addresses
0x400710. This really set me back because I kept making attempts at the wrong places in memory. It wasn’t until revisiting Stage 5 of Colin’s CTF and reading some helpful write-ups that I was able to see my mistake. Then I realized I had been using
nexti, or step over, almost entirely. I then used
stepi on the return which finally provided the moment of clarity when I realized the address I needed had been in front of me the entire time.
I learned several new skills and expanded my knowledge of RE during this challenge. I also went back and read up on some fundamentals such as the prologue/epilogue, the stack pointer, the base pointer, and how
ret are actually composed of other instructions.
Overall this CTF challenge was equal parts exhilarating and frustrating. It feels really good to have solved it. I look forward to using virtual machines and Linux more in the future. I’m also planning on learning some more web security stuff between RE projects.