Ancypwn is your one-key-to-all CTF pwnable challenges environment helper.
It uses docker to manage the tools you might need, so you have separete environment, and you do all the debugging with the shared folder.
(all official pips have been uploaded, enjoy.)
- pwndbg
- pwntools
- keystone assmebler
- capstone disassembler
- glibc source and debug version glibc(so we can debug libc with source)
- Ropper
- ROPGadgets
- one_gadget
Ancypwn is now plugin based, choose your own plugin or write a new plugin if you need more flexible config/environment support.
You will need at least 3 parts to have a working environment (apart from docker).
- ancypwn launcher (
pip install ancypwn
) - a backend: backend provides ability to listen incoming request to pop up a terminal window, then asks terminal plugin to do it and does different docker container launching strategy (like remote support).
- a terminal plugin: this one handles terminal poping up
Backends have the name pattern: ancypwn-backend-*
, while terminal plugin has the pattern ancypwn-terminal-*
.
So you need:
pip3 install ancypwn
# pip3 install ancypwn-backend-* (choose your backend, and install it)
# pip3 install ancypwn-terminal-* (choose your terminal, and install it)
Current official backends:
Current official terminals:
ancypwn is just a docker launcher, and support one instance at a time.
You can do:
ancypwn run
: runs the docker, and mount current directory by default to/pwn
, then you will be passed to the docker shell, do your debugging hereancypwn end
: stops the dockerancypwn attach
: ancypwn run may already be done, without ending, you can attach to the previously run instance, then you will be passed to the docker shell.
What is best of ancypwn
is its supporting of popping up terminal window and runs command inside. This allows the fluent experience of using pwntools' gdb.attach
function to debug target.
To use this, you need to set up your terminal like this:
context.terminal = ['ancyterm', '-s', '[HOST_ADDRESS]', '-p', '15111', '-t', '[TERMINAL]', '-e']
This is a little bit verbose, let me explain:
-s [HOST_ADDRESS]
: this is required to access host from docker, depends on exact backend. For example,ancypwn-backend-macos
backend requireshost.docker.internal
to be the host address.-p 15111
: the port of the server, 15111 by default.-t [TERMINAL]
: the terminal plugin name. For example,alacritty
forancypwn-terminal-alacritty
.
Config is handled by appdirs
, under author = Anciety
, appname = ancypwn
setting. Different OS may have different directory, please refer to appdirs for more information.
When you launch ancypwn the first time, a default configuration will be written to CONFIG_DIR/config.json
.
Some of the configurations are:
backend
: a key-value pair, required at least a "name" to note which backend to use, others are required by specific backendterminal_port
: the port to run terminal popping up service, 15111 by default.install_plugin
: not available feature for now, ignore it.
Mac OSX "objc[1895]: +[NSString initialize] may have been in progress in another thread when fork() was called."
Reported by one of the users, I haven't met this situation, thus I have no idea why this is happening.
Solution is set this environment variable:
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
During CTF games, we usually need a dynamic analysis environment to do all the dynamic stuff, but some challenges may contain extra stuff that may taint your current linux machine.
So, we just use the ancypwn
, and do something like this:
# Suppose we have a directory to save all pwnable challenges
# And we run like this
cd pwn
sudo ancypwn run
# Now we are in a docker shell, and do something, like playing with the original binary
# Then we create another terminal, to use gdb to attach it
# The mounted directory are in `/pwn`
cd /pwn
./example_binary
# In another terminal, you should edit your exploit. Set the pwntools settings like above mentioned.
# Then run it like normal.
python exploit.py
# If you used gdb.attach, it should create a new terminal for you.
In general, this simple script only provides you a direct way of using docker. All things are done by docker itself. The script just makes the docker act like a real "virtual machine".
Since many challenges use different libc
s, this can also be achieved. By default, "17.10" and
"16.04" of ubuntu is provided, if you need others, commit an issue, please. And they can be used
use --ubuntu 17.10
. 16.04
is used by default.
Current supported ubuntu version:
- 18.10
- 18.04
- 16.04