mirror of
https://github.com/calebstewart/pwncat.git
synced 2024-11-27 19:04:15 +01:00
bcb1f77606
- Added some last touches to module system. - Modified connect syntax to allow more flexible parameters - Still need to update enumeration API docs and connect command docs
118 lines
5.3 KiB
ReStructuredText
118 lines
5.3 KiB
ReStructuredText
Command Parser
|
|
==============
|
|
|
|
The local ``pwncat`` prompt and scripting configuration language are powered by the ``CommandParser``
|
|
class which is responsible for parsing lines of text, extracting arguments, and dispatching them
|
|
to the appropriate command.
|
|
|
|
Commands are loaded automatically through the ``pkgutils`` module in Python from the ``pwncat/commands``
|
|
directory. Every Python file from this directory is loaded as a module and checked for a ``Command``
|
|
attribute. This attribute must be a class which inherits from the ``pwncat.commands.base.CommandDefinition``
|
|
class. This class defines the structure of a command and allows the ``CommandParser`` to intelligently
|
|
create ``argparse`` objects, syntax highlighting lexers, and ``prompt_toolkit`` completers for your
|
|
commands.
|
|
|
|
To create a new command, simply create a python file under the ``pwncat/commands`` directory. The name
|
|
can be anything that conforms to python module naming standards. As an example, the ``sysinfo`` command
|
|
is fairly straightforward:
|
|
|
|
.. code-block:: python
|
|
|
|
#!/usr/bin/env python3
|
|
from pwncat.commands.base import CommandDefinition, Complete, Parameter
|
|
from pwncat.util import console
|
|
import pwncat
|
|
|
|
|
|
class Command(CommandDefinition):
|
|
"""
|
|
Display remote system information including host ID, IP address,
|
|
architecture, kernel version, distribution and init system. This
|
|
command also provides the capability to view installed services
|
|
if the init system is supported by ``pwncat``.
|
|
"""
|
|
|
|
PROG = "sysinfo"
|
|
ARGS = {
|
|
"--services,-s": Parameter(
|
|
Complete.NONE, action="store_true", help="List all services and their state"
|
|
)
|
|
}
|
|
|
|
def run(self, args):
|
|
|
|
if args.services:
|
|
for service in pwncat.victim.services:
|
|
if service.running:
|
|
console.print(
|
|
f"[green]{service.name}[/green] - {service.description}"
|
|
)
|
|
else:
|
|
console.print(f"[red]{service.name}[/red] - {service.description}")
|
|
else:
|
|
console.print(f"Host ID: [cyan]{pwncat.victim.host.hash}[/cyan]")
|
|
console.print(
|
|
f"Remote Address: [green]{pwncat.victim.client.getpeername()}[/green]"
|
|
)
|
|
console.print(f"Architecture: [red]{pwncat.victim.host.arch}[/red]")
|
|
console.print(f"Kernel Version: [red]{pwncat.victim.host.kernel}[/red]")
|
|
console.print(f"Distribution: [red]{pwncat.victim.host.distro}[/red]")
|
|
console.print(f"Init System: [blue]{pwncat.victim.host.init}[/blue]")
|
|
|
|
This is a simple command that will print system information from the host database and provide
|
|
the capability to view installed services, provided the init system is supported. This command also shows a
|
|
basic example of interacting with the remote victim. The ``pwncat.victim`` object allows you to
|
|
interact abstractly with the currently connected victim. The ``LOCAL`` property tells the ``CommandParser``
|
|
whether this command operates only on local resources. If set to true, the command will be allowed
|
|
to run prior to a connected victim. In this case, we interact directly with the victim, and therefore
|
|
set the ``LOCAL`` property to false.
|
|
|
|
Command Arguments
|
|
-----------------
|
|
|
|
Argument parsing is achieved using the python built-in module ``argparse``. The parser is automatically
|
|
created based on the ``ARGS``, and ``DEFAULTS`` dictionaries defined in your ``Command`` class.
|
|
|
|
``DEFAULTS`` is a dictionary mapping argument names to default values. This is passed directly to
|
|
the ``argparse.ArgumentParser.set_defaults`` method. This allows you to set defaults for values which
|
|
can't be set in the argument definition (such as values referenced in multiple arguments with
|
|
`dest` parameter).
|
|
|
|
The ``ARGS`` property is a dictionary which matches argument names to the ``parameter`` objects.
|
|
The key for this dictionary is a string representing the a comma-separated list of parameter
|
|
names (e.g. "--param,-p"). The values in this dictionary are built from the ``parameter`` method
|
|
imported above:
|
|
|
|
.. code-block:: python
|
|
|
|
def parameter(complete, token=Name.Label, *args, **kwargs):
|
|
|
|
The first parameter is one of the ``pwncat.commands.base.Complete`` enumeration items. Which includes
|
|
things like ``Complete.REMOTE_FILE``, ``Complete.LOCAL_FILE``, ``Complete.CHOICES`` and ``Complete.NONE``.
|
|
For parameters with no argument ("switches"), this should be ``Complete.NONE``. This controls how
|
|
the CommandParser tab-completes your command at the local prompt.
|
|
|
|
The second parameter is the Pygments token which this option should be highlighted with. Normally,
|
|
you can leave this as default, but you may change it if you like. The remaining arguments are passed
|
|
directly to ``argparse.ArgumentParser.add_argument``.
|
|
|
|
Command Helpers
|
|
---------------
|
|
|
|
.. autoclass:: pwncat.commands.base.Complete
|
|
:members:
|
|
|
|
.. autofunction:: pwncat.commands.base.parameter
|
|
|
|
.. autoclass:: pwncat.commands.base.StoreConstOnce
|
|
|
|
.. autofunction:: pwncat.commands.base.StoreForAction
|
|
|
|
.. autofunction:: pwncat.commands.base.RemoteFileType
|
|
|
|
CommandDefinition Object
|
|
------------------------
|
|
|
|
.. autoclass:: pwncat.commands.base.CommandDefinition
|
|
:members:
|