mirror of
https://github.com/calebstewart/pwncat.git
synced 2024-11-23 17:15:38 +01:00
Added prompt command to fix your prompt in the event of a simple shell like dash
This commit is contained in:
parent
d0e0179fda
commit
8dea0b61e8
14
README.md
14
README.md
@ -132,9 +132,15 @@ terminal escape sequences which `pwncat` adds, so you may get a very long termin
|
||||
\[\033[01;31m\](remote)\[\033[00m\] \[\033[01;33m\]\u@\h\[\033[00m\]:\[\033[01;36m\]\w\[\033[00m\]$
|
||||
```
|
||||
|
||||
We are currently trying to figure out an acceptible way of handling with. `dash` (and other
|
||||
minimalist shells) are capable of handling terminal escape sequences for color, but inserting
|
||||
things like user and host name automatically are unsupported.
|
||||
Currently, the only workaround is to use the `prompt` command at the local `pwncat` prompt.
|
||||
The command allows you to modify the prompt which `pwncat` will automatically set whenever
|
||||
resetting the remote terminal. Two options are provided: "basic" and "fancy". The "fancy"
|
||||
prompt is the default which causes the above output in Dash. To switch to the basic prompt
|
||||
you can use the following command at the `pwncat` prompt:
|
||||
|
||||
```shell script
|
||||
prompt --basic
|
||||
```
|
||||
|
||||
While this is inconvenient, it does not affect the behaviour of `pwncat`. All `pwncat`
|
||||
features will continue to function properly.
|
||||
features will continue to function properly no matter what your prompt looks like.
|
45
pwncat/commands/prompt.py
Normal file
45
pwncat/commands/prompt.py
Normal file
@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env python3
|
||||
import pwncat
|
||||
from pwncat.commands.base import CommandDefinition, Parameter, Complete, Group
|
||||
|
||||
|
||||
class Command(CommandDefinition):
|
||||
"""
|
||||
Reset the prompt used for shells in pwncat. This allows you to choose
|
||||
between the fancier colored prompt and more basic prompt. You can
|
||||
also specify a custom prompt if you'd like.
|
||||
|
||||
This is mainly useful for basic shells such as /bin/sh or /bin/dash
|
||||
which do not support the nicer prompts by default.
|
||||
"""
|
||||
|
||||
PROG = "prompt"
|
||||
GROUPS = {"mutex": Group(mutex=True, required=True)}
|
||||
ARGS = {
|
||||
"--basic,-b": Parameter(
|
||||
Complete.NONE,
|
||||
group="mutex",
|
||||
action="store_true",
|
||||
help="Set a basic prompt with no color or automatic system information",
|
||||
),
|
||||
"--fancy,-f": Parameter(
|
||||
Complete.NONE,
|
||||
group="mutex",
|
||||
action="store_true",
|
||||
help="Set a fancier prompt including auto-user, hostname, cwd information",
|
||||
),
|
||||
}
|
||||
|
||||
def run(self, args):
|
||||
|
||||
if args.fancy:
|
||||
pwncat.victim.remote_prefix = "\\[\\033[01;31m\\](remote)\\[\\033[00m\\]"
|
||||
pwncat.victim.remote_prompt = (
|
||||
"\\[\\033[01;33m\\]\\u@\\h\\[\\033[00m\\]:\\["
|
||||
"\\033[01;36m\\]\\w\\[\\033[00m\\]\\$ "
|
||||
)
|
||||
else:
|
||||
pwncat.victim.remote_prefix = "(remote)"
|
||||
pwncat.victim.remote_prompt = f"{pwncat.victim.host.ip}:$PWD\\$ "
|
||||
|
||||
pwncat.victim.reset(hard=False)
|
@ -89,9 +89,7 @@ def enumerate() -> Generator[FactData, None, None]:
|
||||
|
||||
for i in range(0, len(data), 5):
|
||||
if i >= (len(data) - 4):
|
||||
print(data[i:])
|
||||
break
|
||||
print(data[i : i + 4])
|
||||
name = data[i + 2].strip().rstrip(".service")
|
||||
pid = int(data[i].strip())
|
||||
if "[not set]" in data[i + 1]:
|
||||
|
@ -707,6 +707,9 @@ class Finder:
|
||||
# Attempt to escalate with the local persistence method
|
||||
if persist.escalate(target_user):
|
||||
|
||||
# Stabilize the terminal
|
||||
pwncat.victim.reset(hard=False)
|
||||
|
||||
# The method thought it worked, but didn't appear to
|
||||
if pwncat.victim.update_user() != target_user:
|
||||
if pwncat.victim.getenv("SHLVL") != shlvl:
|
||||
@ -738,6 +741,7 @@ class Finder:
|
||||
tech, exit_command = self.escalate_single(
|
||||
techniques[target_user], shlvl
|
||||
)
|
||||
pwncat.victim.reset(hard=False)
|
||||
pwncat.victim.update_user()
|
||||
chain.append((tech, exit_command))
|
||||
return chain
|
||||
@ -753,6 +757,11 @@ class Finder:
|
||||
f"checking local persistence implants: {persist.format(user)}"
|
||||
)
|
||||
if persist.escalate(user):
|
||||
|
||||
# Ensure history and prompt are correct
|
||||
pwncat.victim.reset(hard=False)
|
||||
|
||||
# Update the current user
|
||||
if pwncat.victim.update_user() != user:
|
||||
if pwncat.victim.getenv("SHLVL") != shlvl:
|
||||
pwncat.victim.run("exit", wait=False)
|
||||
@ -780,6 +789,8 @@ class Finder:
|
||||
try:
|
||||
tech, exit_command = self.escalate_single(techs, shlvl)
|
||||
chain.append((tech, exit_command))
|
||||
pwncat.victim.reset(hard=False)
|
||||
pwncat.victim.update_user()
|
||||
except PrivescError:
|
||||
continue
|
||||
try:
|
||||
|
@ -22,7 +22,7 @@ class Method(BaseMethod):
|
||||
"""
|
||||
|
||||
for fact in pwncat.victim.enumerate.iter("system.service"):
|
||||
if "ssh" in fact.data.name and fact.data.running:
|
||||
if "ssh" in fact.data.name and fact.data.state == "running":
|
||||
break
|
||||
else:
|
||||
raise PrivescError("no sshd service running")
|
||||
|
@ -1459,13 +1459,17 @@ class Victim:
|
||||
|
||||
return output
|
||||
|
||||
def reset(self):
|
||||
def reset(self, hard: bool = True):
|
||||
"""
|
||||
Reset the remote terminal using the ``reset`` command. This also restores
|
||||
your prompt, and sets up the environment correctly for ``pwncat``.
|
||||
|
||||
|
||||
:param hard: whether to actually call the `reset` command.
|
||||
This prevents a long pause when we simply need to reset other
|
||||
things such as the prompt, aliases or history control.
|
||||
"""
|
||||
self.run("reset", wait=False)
|
||||
if hard:
|
||||
self.run("reset", wait=False)
|
||||
self.has_cr = True
|
||||
self.has_echo = True
|
||||
self.run("unset HISTFILE; export HISTCONTROL=ignorespace")
|
||||
|
Loading…
Reference in New Issue
Block a user