mirror of
https://github.com/calebstewart/pwncat.git
synced 2024-11-24 01:25:37 +01:00
Started documenting all pwncat prompt commands
This commit is contained in:
parent
a14c0979d3
commit
b41cfd9aa9
15
docs/source/commands/alias.rst
Normal file
15
docs/source/commands/alias.rst
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
Alias
|
||||||
|
=====
|
||||||
|
|
||||||
|
``alias`` is a simple command. It provides the ability to rename any built-in command. Unlike aliases in common shells,
|
||||||
|
this does not allow you to provide default parameters to commands. Instead, it simply creates an alternative name.
|
||||||
|
|
||||||
|
You can specify a new alias simply by providing the new name followed by the new name. For example, to alias "download"
|
||||||
|
to "down", you could do this in your configuration script:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
alias down "download"
|
||||||
|
|
||||||
|
``alias`` takes as it's second argument a string. Passing anything else (e.g. a code block) will not produce the desired
|
||||||
|
results. The command you are aliasing must exist and be a standard command (no aliases to other aliases are supported).
|
7
docs/source/commands/back.rst
Normal file
7
docs/source/commands/back.rst
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Back
|
||||||
|
====
|
||||||
|
|
||||||
|
The back command is used to exit the local ``pwncat`` prompt and return to your remote shell. It is not expected to be
|
||||||
|
used very often since the ``C-d`` shortcut is the primary method of switching. However, if you need to switch modes from
|
||||||
|
a script, you can do so with this command. It takes no parameters and will immediately exit the ``pwncat`` shell to
|
||||||
|
return to the remote prompt.
|
41
docs/source/commands/bind.rst
Normal file
41
docs/source/commands/bind.rst
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
Bind
|
||||||
|
====
|
||||||
|
|
||||||
|
The bind command is used to create new keyboard shortcuts or change old ones. Keyboard shortcuts are accessed by first
|
||||||
|
pressing your defined "prefix" key (by default: ``C-k``). ``bind`` takes two parameters: the key to bind, and the
|
||||||
|
script to run when it is pressed.
|
||||||
|
|
||||||
|
Key Selection
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The key argument is specified as a string. If the string is a single character, it is assumed to be that literal printed
|
||||||
|
character. For example, to bind the lowercase "a" key to a command you could:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
bind "a" "some helpful command"
|
||||||
|
|
||||||
|
If the key argument is longer than one character, it is assumed to be a key name. The key names accepted by ``pwncat``
|
||||||
|
are taken directly at runtime from the list of known ANSI keystrokes defined in the ``prompt_toolkit`` package. They
|
||||||
|
use the same syntax as in prompt toolkit. All key names are lowercase. The prompt_toolkit documentation covers the
|
||||||
|
keys supported by their module in their `documentation here`_. Any key defined by prompt_toolkit is available for
|
||||||
|
key binding by ``pwncat``.
|
||||||
|
|
||||||
|
Script Content
|
||||||
|
--------------
|
||||||
|
|
||||||
|
The target of a key binding is a script. Scripts in ``pwncat`` can be specified as a string, which can only contain a
|
||||||
|
single command, or as a code block surrounded by curly braces. When in code block mode, you can use as many commands
|
||||||
|
as you like, and even insert comments, blank lines, etc.
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
bind "a" {
|
||||||
|
# you can bind a series of commands which you
|
||||||
|
# do very often to a key, if you find it helpful.
|
||||||
|
privesc -l
|
||||||
|
persist -s
|
||||||
|
tamper
|
||||||
|
}
|
||||||
|
|
||||||
|
.. _`documentation here`: https://python-prompt-toolkit.readthedocs.io/en/master/pages/advanced_topics/key_bindings.html#list-of-special-keys
|
35
docs/source/commands/bruteforce.rst
Normal file
35
docs/source/commands/bruteforce.rst
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
Bruteforce
|
||||||
|
----------
|
||||||
|
|
||||||
|
The ``bruteforce`` command is used to bruteforce authentication of a user locally. It will use the ``su`` command to
|
||||||
|
iteratively try every password for a given user. This is very slow, but does technically work. If no wordlist is
|
||||||
|
specified, the default location of ``rockyou.txt`` in Kali Linux is chosen. This may or may not exist for your system.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
This command is very noisy in log files. Each failed authentication is normally logged by any modern
|
||||||
|
linux distribution. Further, if account lockout is enabled, this will almost certainly lockout the
|
||||||
|
targeted account!
|
||||||
|
|
||||||
|
Selecting a User
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Individual users are selected with the ``--user`` argument. This argument can be passed multiple times to test multiple
|
||||||
|
users in one go. To use the default dictionary to test the root and bob users, you would issue a command like:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
bruteforce -u root -u bob
|
||||||
|
|
||||||
|
User names are automatically tab-completed at the ``pwncat`` prompt for your victim host.
|
||||||
|
|
||||||
|
Selecting a Wordlist
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Word lists are specified with the ``--dictionary`` parameter. This parameter is a path to a file on your attacking
|
||||||
|
host which contains a list of passwords to attempt for the selected users. If a correct password is found, it is stored
|
||||||
|
in the databaase, and the search is aborted for that user. To select a custom database, you would issue a command like:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
bruteforce -d /opt/my-favorite-repo/my-favorite-wordlist.txt -u root
|
||||||
|
|
79
docs/source/commands/busybox.rst
Normal file
79
docs/source/commands/busybox.rst
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
Busybox
|
||||||
|
=======
|
||||||
|
|
||||||
|
``pwncat`` works by try as much as possible not to depend on specific binaries on the remote system. It does this
|
||||||
|
most of the time by selecting an unidentified existing binary from the GTFOBins database in order to perform a
|
||||||
|
generic capability (e.g. file read, file write or shell). However, sometimes a critical binary is missing on the
|
||||||
|
target host which has been removed (either maliciously or never installed). In these situations, obtaining a stable
|
||||||
|
version of all basic binaries is very helpful. To this end, ``pwncat`` has the capability to automatically upload a
|
||||||
|
copy of the ``busybox`` program to the remote host.
|
||||||
|
|
||||||
|
The ``busybox`` command manages the installation, status, and removal of the installed busybox. Installing busybox lets
|
||||||
|
``pwncat`` know that it has a list of standard binaries with known good interfaces easily accessible. The ``busybox``
|
||||||
|
command also understands how to locate a ``busybox`` binary precompiled for the victim architecture and upload it
|
||||||
|
through the existing C2 channel. The new busybox installation will be installed in a temporary directory, and any
|
||||||
|
further automated tools within ``pwncat`` will use it's implementation of common unix tools.
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
To install busybox on the remote victim, you can use the ``--install`` option to the ``busybox`` command. This will
|
||||||
|
first check for an existing, distribution specific, installation on the remote host. If the ``busybox`` command exists,
|
||||||
|
it will utilize that vice installing a new copy. If it doesn't, it will begin proxying a connection to the official
|
||||||
|
busybox servers to upload a busybox binary specific to the victim architecture.
|
||||||
|
|
||||||
|
After installation, ``pwncat`` will examine the endpoints provided by busybox, and remove any that are provided SUID by
|
||||||
|
the remote system. This prevents ``pwncat`` from replacing the real ``su`` binary with ``busybox su`` in it's database.
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
(local) pwncat$ busybox --install
|
||||||
|
uploading busybox for x86_64
|
||||||
|
100.0% [==================================================>] 1066640/1066640 eta [00:00]
|
||||||
|
[+] uploaded busybox to /tmp/busyboxIu1gu
|
||||||
|
[+] pruned 164 setuid entries
|
||||||
|
(local) pwncat$
|
||||||
|
|
||||||
|
Status and Applet List
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
To check if busybox has been installed and is known by ``pwncat`` (for example from a previous session), you can use the
|
||||||
|
``--status`` option. This is the default action, and can be accessed by passing no parameters to ``busybox``:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
(local) pwncat$ busybox
|
||||||
|
[+] busybox is installed to: /tmp/busyboxIu1gu
|
||||||
|
[+] busybox provides 232 applets
|
||||||
|
(local) pwncat$
|
||||||
|
|
||||||
|
If you would like to see a list of binaries which busybox is currently providing for ``pwncat``, you can use the ``--list``
|
||||||
|
option. This is normally a large list (232 lines in this case), but it is provided for completeness sake.
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
(local) pwncat$ busybox --list
|
||||||
|
[+] binaries which the remote busybox provides:
|
||||||
|
* [
|
||||||
|
* [[
|
||||||
|
* acpid
|
||||||
|
* add-shell
|
||||||
|
* addgroup
|
||||||
|
* adduser
|
||||||
|
* adjtimex
|
||||||
|
... removed for brevity ...
|
||||||
|
|
||||||
|
Removing Busybox
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Busybox is tracked by ``pwncat`` as a remote tamper. This means that the ``tamper`` command will show that you have
|
||||||
|
installed busybox, and ``busybox`` can be uninstalled using the ``tamper`` command:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
(local) pwncat$ tamper
|
||||||
|
0 - installed busybox to /tmp/busyboxIu1gu
|
||||||
|
(local) pwncat$ tamper -r -t 0
|
||||||
|
(local) pwncat$ busybox --status
|
||||||
|
[!] busybox hasn't been installed yet
|
||||||
|
(local) pwncat$
|
104
docs/source/commands/connect.rst
Normal file
104
docs/source/commands/connect.rst
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
Connect
|
||||||
|
=======
|
||||||
|
|
||||||
|
The ``connect`` command is used to connect to a remote victim. It can be used to catch a reverse shell, open a bind
|
||||||
|
shell, utilize legitimate SSH credentials, or reconnect via a previous persistence methood to a known host.
|
||||||
|
|
||||||
|
This command is also the command which is run if you pass arguments to the external ``pwncat`` script. All arguments
|
||||||
|
to ``pwncat`` are passed directly to the ``connect`` command at startup. If no connection is made during this command,
|
||||||
|
``pwncat`` will automatically exit after command completion.
|
||||||
|
|
||||||
|
The ``connect`` command is only accessible prior to an active connection. If you attempt to run this command after a
|
||||||
|
connection has been established, it will not attempt a new connection and will not load your configuration script.
|
||||||
|
Because the ``pwncat`` prompt is only accessible after a connection, this command is effectively only useful
|
||||||
|
when used as the arguments to the main ``pwncat`` application or in configuration scripts. Replacing ``connect``
|
||||||
|
with ``pwncat`` in any examples below will also function the same way at startup.
|
||||||
|
|
||||||
|
Catching a Reverse Shell
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Reverse shell listeners are started with the ``--listen`` parameter. This mode requires the ``--host`` and ``--port``
|
||||||
|
parameters as well. If ``--host`` is not specified, it is assumed to be ``0.0.0.0`` to bind to all interfaces. To
|
||||||
|
listen for incoming shell connections on port 4444, you could issue a command like:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
connect -l -H 0.0.0.0 -p 4444
|
||||||
|
|
||||||
|
Connecting to a Bind Shell
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
Making an outbound connection to a bind shell is accomplished through the ``--connect`` parameter. This mode requires
|
||||||
|
both the ``--host`` and ``--port`` parameters to be specified.
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
connect -c -H 1.1.1.1 -p 4444
|
||||||
|
|
||||||
|
Connecting to an SSH Server
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
If you have valid credentials to a remote SSH server, but would like to utilize ``pwncat`` to manage your session, you
|
||||||
|
can use the ``--ssh`` option. This mode requires the ``--host``, ``--user``, and ``--port`` options. If no port is
|
||||||
|
specified, it will default to ``22``. Along with these options, you must specify either a ``--password`` or ``--identity``
|
||||||
|
for the remote password or private key identity file respectively. ``pwncat`` will use Paramiko to connect to the
|
||||||
|
victim and establish a PTY shell. It will then act normally and provide you access to this shell. All normal ``pwncat``
|
||||||
|
features are still available over the SSH transport!
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
:caption: Connecting with a known password
|
||||||
|
|
||||||
|
connect -s -H 1.1.1.1 -u root -p "P@ssw0rd"
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
:caption: Connection with a known private key
|
||||||
|
|
||||||
|
connect -s -H 1.1.1.1 -u root -i "./exfiled-privkey"
|
||||||
|
|
||||||
|
Listing Known Persistence Methods
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
The ``connect`` command has the ability to query the database for all known remote hosts and list installed persistence
|
||||||
|
methods. It also provides the ability to leverage installed persistence methods to reconnect to a specific host. This
|
||||||
|
allows you to easily re-establish your session after disconnection if you installed some form of persistence.
|
||||||
|
|
||||||
|
In ``pwncat`` hosts are identified by a "host hash". This has is generated by combining some unique data taken from the
|
||||||
|
remote host the last time a session was established and should be unique across all hosts (unlike IP addresses). The
|
||||||
|
ideal way to reference a remote host is by it's host hash. With an open session, you can retrieve your host hash with
|
||||||
|
the ``sysinfo`` command. To retrieve known hosts with persistence methods after disconnection, you can use the
|
||||||
|
``--list`` option to the ``connect`` command:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
:caption: Retrieving a list of known hosts
|
||||||
|
|
||||||
|
$ pwncat -C data/pwncatrc --list
|
||||||
|
1.1.1.1 - debian - d87b9646813d250ac433decdee70112a
|
||||||
|
- pam as system
|
||||||
|
- authorized_keys as debian
|
||||||
|
|
||||||
|
When reconnecting to a host, you will need either the host hash or the IP address. While the host hash is preferred,
|
||||||
|
``pwncat`` will lookup a host by IP address in the database. In cases where multiple hosts are NAT'd behind a single
|
||||||
|
IP address, ``pwncat`` will choose the first host from the database with a matching IP address.
|
||||||
|
|
||||||
|
Reconnecting to a Victim
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Once you have your victim's IP address or host hash, you are ready to reconnect. Reconnecting is simple and automatic in
|
||||||
|
most cases. The simplest option is to supply the victim IP or host hash to the ``--host`` parameter and specify the
|
||||||
|
``--reconnect`` option. This will try each persistence method individually until one succeeds in a session:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
$ pwncat -C data/pwncatrc -r -H d87b9646813d250ac433decdee70112a
|
||||||
|
[+] setting terminal prompt
|
||||||
|
[+] running in /bin/bash
|
||||||
|
[+] terminal state synchronized
|
||||||
|
[+] pwncat is ready 🐈
|
||||||
|
|
||||||
|
(remote) debian@debian-s-1vcpu-1gb-nyc1-01:~$
|
||||||
|
|
||||||
|
If you have installed multiple persistence methods for multiple users, you can also specify a persistence method or user
|
||||||
|
to connect with. If only one of ``--method`` or ``--user`` is specified, all methods matching your search will be tried.
|
||||||
|
For example, specifying only ``method`` will cause ``pwncat`` to attempt each user for which that method is installed.
|
||||||
|
On the other hand, specifying only ``--user`` will cause ``pwncat`` to attempt connection with every method which
|
||||||
|
offers persistence as that user. When both are specified, only the exact matching persistence method will be attempted.
|
12
docs/source/commands/index.rst
Normal file
12
docs/source/commands/index.rst
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
Command index
|
||||||
|
=============
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:caption: Contents
|
||||||
|
|
||||||
|
alias.rst
|
||||||
|
back.rst
|
||||||
|
bind.rst
|
||||||
|
bruteforce.rst
|
||||||
|
busybox.rst
|
||||||
|
connect.rst
|
@ -68,6 +68,7 @@ well. Pull requests are always welcome!
|
|||||||
installation.rst
|
installation.rst
|
||||||
usage.rst
|
usage.rst
|
||||||
configuration.rst
|
configuration.rst
|
||||||
|
commands/index.rst
|
||||||
upload.rst
|
upload.rst
|
||||||
download.rst
|
download.rst
|
||||||
tamper.rst
|
tamper.rst
|
||||||
|
@ -61,8 +61,10 @@ class Command(CommandDefinition):
|
|||||||
def run(self, args):
|
def run(self, args):
|
||||||
|
|
||||||
if args.action == "list":
|
if args.action == "list":
|
||||||
if not pwncat.victim.has_busybox:
|
if pwncat.victim.host.busybox is None:
|
||||||
util.error("busybox hasn't been installed yet (hint: run 'busybox'")
|
util.error(
|
||||||
|
"busybox hasn't been installed yet (hint: run 'busybox --install'"
|
||||||
|
)
|
||||||
return
|
return
|
||||||
util.info("binaries which the remote busybox provides:")
|
util.info("binaries which the remote busybox provides:")
|
||||||
|
|
||||||
|
@ -10,8 +10,13 @@ from pwncat import util
|
|||||||
class Command(CommandDefinition):
|
class Command(CommandDefinition):
|
||||||
""" List known commands and print their associated help documentation. """
|
""" List known commands and print their associated help documentation. """
|
||||||
|
|
||||||
|
def get_command_names(self):
|
||||||
|
if pwncat.victim and pwncat.victim.command_parser:
|
||||||
|
return [c.PROG for c in pwncat.victim.command_parser.commands]
|
||||||
|
return []
|
||||||
|
|
||||||
PROG = "help"
|
PROG = "help"
|
||||||
ARGS = {"topic": parameter(Complete.NONE, nargs="?")}
|
ARGS = {"topic": parameter(Complete.CHOICES, choices=get_command_names, nargs="?")}
|
||||||
LOCAL = True
|
LOCAL = True
|
||||||
|
|
||||||
def run(self, args):
|
def run(self, args):
|
||||||
|
@ -569,13 +569,6 @@ class Victim:
|
|||||||
:return: The full path to the requested binary or None if it was not found.
|
:return: The full path to the requested binary or None if it was not found.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if self.host.busybox is not None:
|
|
||||||
if name in self.busybox_provides:
|
|
||||||
if quote:
|
|
||||||
return f"{shlex.quote(str(self.busybox_path))} {name}"
|
|
||||||
else:
|
|
||||||
return f"{self.busybox_path} {name}"
|
|
||||||
|
|
||||||
binary = (
|
binary = (
|
||||||
self.session.query(pwncat.db.Binary)
|
self.session.query(pwncat.db.Binary)
|
||||||
.filter_by(name=name, host_id=self.host.id)
|
.filter_by(name=name, host_id=self.host.id)
|
||||||
|
Loading…
Reference in New Issue
Block a user