Athena Wiki

VM & Docker Setup

getting startedbeginner

Build isolated, reproducible CTF environments with virtual machines and containers — snapshots, networking, and disposable challenge sandboxes.

setupvmdockerpodmanvirtualizationisolationsandboxdevcontainer

VM & Docker Setup

Two rules make CTF work safe and repeatable: never run untrusted challenge files on your host, and never let a broken toolchain cost you points. Virtual machines and containers solve both. A VM gives you a full, snapshot-able operating system; a container gives you a fast, disposable sandbox for a single challenge.

Treat every challenge file as hostile

Pwn binaries, malware-analysis samples, and forensic images can contain code that runs on extraction or execution. Detonate them inside a VM or container with no access to your host filesystem or credentials — never on your daily-driver OS.


VM vs Container — When to Use Which

NeedUseWhy
Full Kali/Ubuntu desktop with GUI tools (Burp, Ghidra, Wireshark)VMReal kernel, GUI, persistent state, snapshots
Run a single Linux challenge binary in a clean libcContainerStarts in milliseconds, matches the remote glibc
Detonate malware / analyze ransomwareVM (isolated network)Hardware-level isolation, revertible snapshot
Reproduce a remote pwn target's exact environmentContainerPin the same Ubuntu/glibc the organizer used
Kernel exploitation, custom kernel modulesVM (or QEMU)You need your own kernel you can crash freely

A practical setup is both: a Kali or Ubuntu VM as your working desktop, and Docker/Podman inside that VM for per-challenge sandboxes.


Virtual Machine Setup

Download the prebuilt Kali Linux VM image rather than installing from ISO — it saves an hour of configuration.

  1. Get the official VM image from kali.org/get-kali.
  2. Import the .ova / VMware bundle.
  3. Allocate at least 4 GB RAM, 2 vCPUs, 60 GB disk (Ghidra and Burp are memory-hungry).
  4. Install guest additions / VMware Tools for clipboard sharing and a resizable display.

Snapshots Are Your Safety Net

Take a clean snapshot before every malware/forensics session and revert afterwards.

Clean install  →  snapshot "baseline"
Install tools  →  snapshot "tooling"
Per engagement →  snapshot "before-<challenge>", revert when done

Container Setup (Docker / Podman)

In 2026, prefer rootless containers. Both Docker (rootless mode) and Podman run without granting containers root on your host, which is the right default for running untrusted code.

# Install Docker Engine, then enable rootless mode
curl -fsSL https://get.docker.com | sh
dockerd-rootless-setuptool.sh install
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
docker run --rm hello-world

Disposable Challenge Sandbox

Spin up a throwaway shell with the challenge directory mounted, no network, and dropped privileges:

docker run --rm -it \
  --network none \                 # no outbound network (pwn/RE analysis)
  --cap-drop ALL \                 # drop Linux capabilities
  --security-opt no-new-privileges \
  -v "$PWD":/ctf:ro \              # challenge files, read-only
  -w /ctf \
  ubuntu:24.04 bash

Match the remote glibc

Pwn exploits are sensitive to the exact libc. Find out which Ubuntu the organizer used (often stated, or inferable from the provided libc.so.6) and base your container on the same tag — ubuntu:22.04 (glibc 2.35), ubuntu:24.04 (glibc 2.39), etc. See Pwn → ret2libc for identifying libc versions.

Reproducible Toolkits with a Dockerfile

Pin your exploitation toolkit so it is identical on every machine and CI runner:

FROM ubuntu:24.04
RUN apt-get update && apt-get install -y \
    python3-pip gdb git ruby file binutils && \
    pip3 install --break-system-packages pwntools ropgadget && \
    gem install one_gadget && \
    bash -c "$(curl -fsSL https://gef.blah.cat/sh)"
WORKDIR /ctf
docker build -t ctf-pwn .
docker run --rm -it -v "$PWD":/ctf ctf-pwn bash

Docker Compose for Multi-Service Web Challenges

Many web challenges ship as a docker-compose.yml. Run them locally to test exploits offline before burning attempts on the live target:

docker compose up -d        # start the challenge stack
docker compose logs -f web  # watch app logs while you attack
docker compose down -v      # tear everything down, including volumes

Dev Containers (Reproducible, Shareable Environments)

A .devcontainer/devcontainer.json lets you (and teammates) open the same fully-provisioned environment in VS Code or a Codespace. This is the modern way to share a team toolkit.

{
  "name": "ctf-toolkit",
  "image": "ubuntu:24.04",
  "features": {
    "ghcr.io/devcontainers/features/python:1": {},
    "ghcr.io/devcontainers/features/docker-in-docker:2": {}
  },
  "postCreateCommand": "pip install --break-system-packages pwntools pycryptodome"
}

Networking Models You Should Know

ModeBehaviourUse for
NAT (default)VM shares host IP, outbound onlyGeneral browsing, reaching CTF targets
BridgedVM gets its own LAN IPHosting a listener reachable by other hosts
Host-only / InternalVM ↔ host only, no internetMalware detonation, isolated lab
--network none (Docker)No network at allStatic analysis of untrusted binaries

For reverse shells during web/pwn challenges, your listener must be reachable by the target. On a NAT'd VM that usually means port-forwarding or using a tunneling service (e.g. an SSH reverse tunnel) — see Web → Command Injection for shell-catching setups.


Checklist

  • Working VM (Kali/Ubuntu) with a clean baseline snapshot
  • Rootless Docker or Podman installed inside the VM
  • A pinned Dockerfile/dev container for your toolkit
  • Know how to run a sandbox with --network none --cap-drop ALL
  • Match challenge containers to the remote glibc/Ubuntu version
  • Revert to a clean snapshot before/after malware or forensics work
  • Understand NAT vs bridged for catching reverse shells

See Also


Last updated on

On this page