1
0
mirror of https://github.com/calebstewart/pwncat.git synced 2024-11-24 01:25:37 +01:00

Run/local command and shortcuts

Added the "run" and "local" commands for remote and local command
execution respectively and the "shortcut" command to allow for shortcuts
like "!ls" for local commands and "@ls" for remote commands.
This commit is contained in:
Caleb Stewart 2020-05-17 02:29:51 -04:00
parent 512dd045c1
commit d62366da45
5 changed files with 89 additions and 14 deletions

View File

@ -17,6 +17,12 @@ set on_load {
bind s "sync" bind s "sync"
bind c "set state command" bind c "set state command"
# Create shortcut aliases for commands # Create aliases for commands
alias up upload alias up upload
alias down download alias down download
# Shortcuts allow single-character prefix which indicate the entire command
# string be passed as the arguments to a specific command. For example:
# "!ls" run "local ls" given the below directives
shortcut ! local
shortcut @ run

View File

@ -146,6 +146,7 @@ class CommandParser:
self.loading_complete = False self.loading_complete = False
self.aliases: Dict[str, CommandDefinition] = {} self.aliases: Dict[str, CommandDefinition] = {}
self.shortcuts: Dict[str, CommandDefinition] = {}
@property @property
def loaded(self): def loaded(self):
@ -220,24 +221,31 @@ class CommandParser:
util.error(e.args[0]) util.error(e.args[0])
return return
# Search for a matching command if argv[0][0] in self.shortcuts:
for command in self.commands: command = self.shortcuts[argv[0][0]]
if command.PROG == argv[0]: argv[0] = argv[0][1:]
break args = argv
else: else:
if argv[0] in self.aliases: # Search for a matching command
command = self.aliases[argv[0]] for command in self.commands:
if command.PROG == argv[0]:
break
else: else:
util.error(f"{argv[0]}: unknown command") if argv[0] in self.aliases:
command = self.aliases[argv[0]]
else:
util.error(f"{argv[0]}: unknown command")
return
if not self.loading_complete and not command.LOCAL:
util.error(
f"{argv[0]}: non-local commands cannot run until after session setup."
)
return return
if not self.loading_complete and not command.LOCAL: args = argv[1:]
util.error(
f"{argv[0]}: non-local commands cannot run until after session setup."
)
return
args = [a.encode("utf-8").decode("unicode_escape") for a in argv[1:]] args = [a.encode("utf-8").decode("unicode_escape") for a in args]
try: try:
# Parse the arguments # Parse the arguments

19
pwncat/commands/local.py Normal file
View File

@ -0,0 +1,19 @@
#!/usr/bin/env python3
import subprocess
from pwncat.commands import CommandDefinition, Complete
from pwncat.commands.base import parameter
class Command(CommandDefinition):
PROG = "local"
ARGS = {
"argv": parameter(
Complete.NONE, nargs="+", help="the local shell command to run"
)
}
LOCAL = True
def run(self, args):
subprocess.run(args.argv, shell=True)

18
pwncat/commands/run.py Normal file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
import sys
import pwncat
from pwncat.commands.base import CommandDefinition, Complete, parameter
class Command(CommandDefinition):
PROG = "run"
ARGS = {
"argv": parameter(
Complete.NONE, nargs="+", help="The command to run on the remote host"
)
}
def run(self, args):
sys.stdout.buffer.write(pwncat.victim.run(args.argv))

View File

@ -0,0 +1,24 @@
import pwncat
from pwncat.commands import CommandDefinition
from pwncat.commands.base import parameter, Complete
class Command(CommandDefinition):
PROG = "shortcut"
ARGS = {
"prefix": parameter(
Complete.NONE, help="the prefix character used for the shortcut"
),
"command": parameter(Complete.NONE, help="the command to execute"),
}
LOCAL = True
def run(self, args):
for command in pwncat.victim.command_parser.commands:
if command.PROG == args.command:
pwncat.victim.command_parser.shortcuts[args.prefix] = command
return
self.parser.error(f"{args.command}: no such command")