Provide powerful tools for seccomp analysis
Powerful tools for seccomp analysis.
This project is aimed primarily (but not exclusively) at analyzing seccomp sandboxes in CTF pwn challenges. Some features are CTF-specific, but they're just as useful for analyzing real-world seccomp filters.
Available on RubyGems.org!
$ gem install seccomp-toolsIf compilation fails, try:
sudo apt install gcc ruby-dev makethen install seccomp-tools again.
…Dumps the seccomp BPF from an executable, using the ptrace syscall.
NOTE: the target executable is actually run, so be careful with untrusted binaries.
…Disassembles raw seccomp BPF into a readable format.
…Assembles seccomp rules into raw bytes. Useful when you want to write your own seccomp rules.
Supports jump labels and syscall names. See the examples below.
…Since v1.6.0 [not released yet], asm has switched to a yacc-based parser, which allows a more flexible and intuitive syntax!
…The output of seccomp-tools disasm --asm-able is valid input for asm:
…Summarizes a whole filter as a per-action policy: which syscalls end in ALLOW, KILL, ERRNO, etc.,
and under what argument constraints. The input can be a dumped BPF file, an executable (its seccomp is
dumped first, like dump), or a running process via --pid.
…A more involved example - the 0CTF/TCTF 2023 "Nothing is True" filter, which has separate 32/64-bit
allowlists and argument checks on open, mmap and execve:
$ seccomp-tools explain spec/data/tctf-2023-nothing-is-true.bpf -a amd64
# Seccomp policy for spec/data/tctf-2023-nothing-is-true.bpf
#
# Architecture: i386
#
# ALLOW:
# exit, read, write, brk, mmap, munmap, exit_group
#
# KILL:
# (any other syscall)
#
# Architecture: amd64
#
# ALLOW:
# close, munmap, brk, exit, exit_group
# open when filename == 0x31337 && flags == 0x0
# mmap when prot == 0x2
# execve when filename == 0x7ffea12f7d0e
#
# KILL:
# sys_number >= 0x40000000 (x32 ABI)
# (any other syscall)
#
# Other architectures: KILLScans a filter for weaknesses and likely escape routes - a missing architecture or x32 guard, a
permissive (denylist) default, equivalent-syscall gaps (e.g. execve blocked but execveat not),
an open/read/write chain, or dangerous syscalls reachable as ALLOW - and reports each with a
severity. It runs on every supported architecture (architecture-specific quirks like amd64's x32 are
applied only where they exist), and takes the same input as explain (a BPF file, an executable, or
--pid).
…Auditing a denylist with several escape routes (the TokyoWesterns CTF 2016 "diary" filter):
…Use --format json for CI or tooling:
…seccomp-tools completion prints a completion script for the given shell. Load it from your shell's startup file:
# bash (~/.bashrc)
eval "$(seccomp-tools completion bash)"
# zsh (~/.zshrc, after `compinit`)
eval "$(seccomp-tools completion zsh)"
# fish (~/.config/fish/config.fish)
seccomp-tools completion fish | sourceTo avoid the startup cost of evaluating it every time, write the script to the directory your shell loads completions from instead, e.g. seccomp-tools completion zsh > "${fpath[1]}/_seccomp-tools".
Pull requests adding support for more architectures are welcome!
I recommend using rbenv to manage your Ruby environment.
$ gem install bundler$ git clone https://github.com/david942j/seccomp-tools && cd seccomp-tools$ bundle install$ bundle exec rake
Any suggestions or feature requests are welcome! Feel free to file issues or send pull requests. And if you like this project, consider giving it a star :grimacing:
No open issues yet, or sync has not completed.