picoCTF

We are going to be creating a simple buffer overflow challenge. The first step is to create an empty directory, let’s name it BufferOverflow1. Within this directory, we will place 3 files: our source file (vuln.c), our problem information file (problem.json), and our instance generation file (challenge.py).

We’ll start with the source file. Copy the following source code into vuln.c and replace the definition of BUFSIZE with your desired buffer size.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

#define BUFSIZE 64

void vuln(){
  char buf[BUFSIZE];
  gets(buf);
  puts(buf);
  fflush(stdout);
}

int main(int argc, char **argv){
  // Set the gid to the effective gid
  // this prevents /bin/sh from dropping the privileges
  gid_t gid = getegid();
  setresgid(gid, gid, gid);

  vuln();
  return 0;
}

The next thing to create is the problem.json file. This will store information about the problem such as its name, category, score, and so forth. The full specification for this file can be found problem-json-spec.md.

Our problem.json will look something like:

{
  "name": "Buffer Overflow 1",
  "category": "Binary Exploitation",
  "description": "Exploit the buffer overflow found in . Connect to it with <code>nc  </code>.",
  "score" : 50,
  "hints": [],
  "author": "Your name here",
  "organization": "Example",
  "event": "Sample"
}

Remember to change the author field to your own name, e.g. “Fred Hacker”.

Now we must create out challenge.py script that specifies how to create an instance of our challenge. We must assign this specification to the variable Problem. The API provides a function for creating challenges that are simply compiled source files, shown below.

from hacksport.problem_templates import CompiledBinary
Problem = CompiledBinary(sources=["vuln.c"], remote=True)

It’s worth noting the following points:

Now that we have all of the files we need, we can try to generate a test instance. First, we must install the problem onto the shell server. From the directory above BufferOverflow1, run sudo shell_manager install BufferOverflow1. Your buffer overflow problem should now appear in the sudo shell_manager status problem listing, with 0 current instances. A new, unique name containing a hash will be assigned to your problem upon installation.

You can now perform a dry-run deployment of the problem to verify the templated instance output. Run sudo shell_manager deploy -d <installed-problem-name> and the location of a staging directory for your problem instance will be provided. Listing the contents of that directory should yield:

-r--r----- 1 hacksports 1230   32 Jul 20 20:09 flag.txt
-rwxr-sr-x 1 hacksports 1230 7388 Jul 20 20:09 vuln

As expected, we have a vulnerable binary named vuln that has the setgid bit on. Thus, when exploited, it will be able to read the flag file.

After confirming that the instance was created successfully, we can deploy a real instance of the problem by forgoing the -d flag: sudo shell_manager deploy <installed-problem-name>. Real problem instances will appear within the /problems directory, and sudo shell_manager status will note the current number of instances.

Continue to the next example problem here.