|
| 1 | +# Quickstart guide to writing a challenge |
| 2 | + |
| 3 | +The basic steps when preparing a challenge are: |
| 4 | + |
| 5 | +* A Docker image is built from the `challenge` directory. For the simplest challenges, replacing `challenge/chal.c` is sufficient. |
| 6 | +* Edit `challenge/Dockerfile` to change the commandline or the files you want to include. |
| 7 | +* To try the challenge locally, you will need to |
| 8 | + * create a a local cluster with `kctf cluster create --type kind --start $configname` |
| 9 | + * build the challenge binary with `make -C challenge` |
| 10 | + * and then deploy the challenge with `kctf chal start` |
| 11 | +* To access the challenge, create a port forward with `kctf chal debug port-forward` and connect to it via `nc localhost PORT` using the printed port. |
| 12 | +* Check out `kctf chal <tab>` for more commands. |
| 13 | + |
| 14 | +## Directory layout |
| 15 | + |
| 16 | +The following files/directories are available: |
| 17 | + |
| 18 | +### /challenge.yaml |
| 19 | + |
| 20 | +`challenge.yaml` is the main configuration file. You can use it to change |
| 21 | +settings like the name and namespace of the challenge, the exposed ports, the |
| 22 | +proof-of-work difficulty etc. |
| 23 | +For documentation on the available fields, you can run `kubectl explain challenge` and |
| 24 | +`kubectl explain challenge.spec`. |
| 25 | + |
| 26 | +### /challenge |
| 27 | + |
| 28 | +The `challenge` directory contains a Dockerfile that describes the challenge and |
| 29 | +any challenge files. This template comes with a Makefile to build the challenge, |
| 30 | +which is the recommended way for pwnables if the deployed binary matters, e.g. |
| 31 | +if you hand it out as an attachment for ROP gadgets. |
| 32 | +If the binary layout doesn't matter, you can build it using an intermediate |
| 33 | +container as part of the Dockerfile similar to how the chroot is created. |
| 34 | + |
| 35 | +### /healthcheck |
| 36 | + |
| 37 | +The `healthcheck` directory is optional. If you don't want to write a healthcheck, feel free to delete it. However, we strongly recommend that you implement a healthcheck :). |
| 38 | + |
| 39 | +We provide a basic healthcheck skeleton that uses pwntools to implement the |
| 40 | +healthcheck code. The only requirement is that the healthcheck replies to GET |
| 41 | +requests to http://$host:45281/healthz with either a success or an error status |
| 42 | +code. |
| 43 | + |
| 44 | +In most cases, you will only have to modify `healthcheck/healthcheck.py`. |
| 45 | + |
| 46 | +## API contract |
| 47 | + |
| 48 | +Ensure your setup fulfills the following requirements to ensure it works with kCTF: |
| 49 | + |
| 50 | +* Verify `kctf_setup` is used as the first command in the CMD instruction of your `challenge/Dockerfile`. |
| 51 | +* You can do pretty much whatever you want in the `challenge` directory but: |
| 52 | +* We strongly recommend using nsjail in all challenges. While nsjail is already installed, you need to configure it in `challenge/nsjail.cfg`. For more information on nsjail, see the [official website](https://nsjail.dev/). |
| 53 | +* Your challenge receives connections on port 1337. The port can be changed in `challenge.yaml`. |
| 54 | +* The healthcheck directory is optional. |
| 55 | + * If it exists, the image should run a webserver on port 45281 and respond to `/healthz` requests. |
0 commit comments