A single Dockerfile that bundles 45+ CTF pwn and reverse-engineering tools into one Ubuntu 24.04 image. Includes 7 disassemblers and decompilers (Ghidra, IDA Free, Binary Ninja Free, Cutter, radare2, rizin, retdec), 3 GDB plugins with instant switching, and a pre-populated command history.
IDA Free and Binary Ninja Free are installed from their vendors' free-tier downloads. Users are responsible for compliance with each vendor's license terms.
Given Docker on the host, this image packages 45+ tools that would otherwise require separate installation steps -- Python packages, Java-based disassemblers, GDB plugins, and Ruby gems -- into a single Dockerfile.
# Pull from GHCR (fastest)
docker pull ghcr.io/gl0bal01/pwndocker-reverse:latest
docker run -it --rm --cap-add=SYS_PTRACE -v $(pwd):/ctf ghcr.io/gl0bal01/pwndocker-reverse
# Or build locally
docker build -t pwndocker-reverse .
docker run -it --rm --cap-add=SYS_PTRACE -v $(pwd):/ctf pwndocker-reverse
# With X11 forwarding (requires X11 server on host -- see GUI tools section)
docker run -it --rm --cap-add=SYS_PTRACE \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v $(pwd):/ctf pwndocker-reverse
# Custom UID/GID (if your host UID is not 1000)
docker build --build-arg CTF_UID=$(id -u) --build-arg CTF_GID=$(id -g) -t pwndocker-reverse .You land in /ctf as user ctf with sudo, oh-my-zsh, and 97 pre-loaded history entries searchable via Ctrl+R.
The image is rebuilt every Monday from master so latest stays fresh against upstream tool releases. Three ways to consume it:
# Rolling (weekly fresh) — convenient, not reproducible
docker pull ghcr.io/gl0bal01/pwndocker-reverse:latest
# Dated weekly snapshot — fresh but frozen, good for a CTF weekend
docker pull ghcr.io/gl0bal01/pwndocker-reverse:weekly-20260406
# Immutable digest — fully reproducible, pin this in team setups / scripts
docker pull ghcr.io/gl0bal01/pwndocker-reverse@sha256:<digest>Every pushed image is signed with cosign (keyless, via GitHub OIDC) and ships with an SBOM + SLSA provenance attestation. Verify before running in sensitive contexts:
cosign verify ghcr.io/gl0bal01/pwndocker-reverse:latest \
--certificate-identity-regexp 'https://github.com/gl0bal01/pwndocker-reverse/.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
# Inspect the SBOM
docker buildx imagetools inspect ghcr.io/gl0bal01/pwndocker-reverse:latest --format '{{ json .SBOM }}'| Category | Tools |
|---|---|
| Exploit Dev | pwntools, angr, ROPgadget, ropper, one_gadget, seccomp-tools, qiling, pwninit |
| Libraries | capstone, keystone, unicorn, z3, yara, r2pipe (in pwntools venv) |
| Disassemblers / Decompilers | Ghidra, IDA Free, Binary Ninja Free, Cutter (rizin), retdec, radare2, rizin, pycdc, jd-gui |
| GDB | pwndbg, GEF, PEDA + switcher scripts |
| Hex Editors | ImHex, hexedit |
| Fuzzing | AFL++ |
| Dynamic | frida, strace, ltrace, villoc |
| Workflow | libc-database, pwninit, patchelf, binwalk, unblob, upx |
| Analysis | binary-refinery, opengrep, hash-identifier |
| Networking | socat, ncat, tcpdump, tshark, nmap |
| Editors | vim, neovim |
| System | QEMU user-mode, wabt, gdb-multiarch, p7zip, oh-my-zsh |
# Start the container with your challenge directory mounted
docker run -it --rm --cap-add=SYS_PTRACE -v $(pwd):/ctf pwndocker-reverse
# Analyze the binary
checksec --file=./challenge
file ./challenge
strings -n 8 ./challenge
r2 -A ./challenge
# Find gadgets
ROPgadget --binary ./challenge --ropchain
ropper --file ./challenge --search "pop rdi"
one_gadget ./libc.so.6
# Patch the binary to use the provided libc
pwninit --bin ./challenge --libc ./libc.so.6
patchelf --set-interpreter ./ld-linux-x86-64.so.2 --set-rpath . ./challenge
# Write and run your exploit
python3 exploit.pyThree plugins installed, instantly switchable:
gdb-pwndbg ./binary # launch with pwndbg
gdb-gef ./binary # launch with GEF
gdb-peda ./binary # launch with PEDA
gdb-switch pwndbg # set default for plain `gdb`Requires X11 forwarding. On Linux this works natively; on macOS install XQuartz, on Windows install VcXsrv or use WSLg.
docker run -it --rm --cap-add=SYS_PTRACE \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v $(pwd):/ctf pwndocker-reverse
# Inside the container
ghidra # launch Ghidra
ida64 ./binary # launch IDA Free
binaryninja ./binary # launch Binary Ninja Free
start-cutter.sh ./binary # launch Cutter (checks $DISPLAY)
jd-gui ./app.jar # launch Java decompilerr2 -A ./binary # radare2 with analysis
rizin -A ./binary # rizin with analysis
retdec-decompiler ./binary # decompile to C
pycdc ./script.pyc # decompile Python bytecodeafl-fuzz -i input/ -o output/ -- ./binary @@
afl-cmin -i input/ -o input_min/ -- ./binary @@frida -f ./binary -l script.js # hook functions at runtime
frida-trace -f ./binary -i "malloc" # trace calls
strace -f ./binary # system call trace
ltrace ./binary # library call trace
villoc /tmp/ltrace.out > heap.html # heap visualizationlibc-database is installed with scripts only. Download libcs on demand:
# First time: download libc database (run once)
cd /opt/libc-database && sudo PATH=/usr/bin:$PATH ./get ubuntu debian
# Then use it
libc-find d8 e9 31 60
libc-identify ./libc.so.6
libc-dump ./libc.so.6 system __free_hookqemu-user -L /usr/arm-linux-gnueabihf ./arm_binary
qemu-user -g 1234 ./binary # start with GDB server on port 1234socat TCP-LISTEN:1337,reuseaddr,fork EXEC:./binary # host a binary
ncat -lvp 1337 # listen
tcpdump -i any -w capture.pcap # capture traffic
tshark -r capture.pcap # analyze pcapHit Ctrl+R and search. 97 commands covering all installed tools are already in your history -- no need to remember syntax.
Dockerfile # Single-file image definition (13 layers)
config/
gdb-pwndbg # GDB launcher (pwndbg)
gdb-gef # GDB launcher (GEF)
gdb-peda # GDB launcher (PEDA)
gdb-switch # Set default GDB plugin
jd-gui # java -jar wrapper
start-cutter.sh # GUI launcher with $DISPLAY check
start-ghidra.sh # GUI launcher with $DISPLAY check
zsh_history # Pre-populated command history
.dockerignore