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

Merge branch 'master' of github.com:calebstewart/pwncat

This commit is contained in:
Caleb Stewart 2022-03-21 16:35:00 -04:00
commit 37f04d4e16
10 changed files with 63 additions and 34 deletions

View File

@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
The Changelog starts with v0.4.1, because we did not keep one before that,
and simply didn't have the time to go back and retroactively create one.
## [Unreleased]
### Fixed
- Fixed `shlex.join` use with non-str type objects (e.g. `RemotePath`)
- Fixed `set` command use with incorrect keys (e.g. `set invalid value`)
### Added
- Added missed `PlatformError` for `upload` command (e.g. "no gtfobins writers available")
## [0.5.4] - 2022-01-27
Bug fix for the `load` command.

View File

@ -12,7 +12,8 @@
#
import os
import sys
sys.path.insert(0, os.path.abspath('../..'))
sys.path.insert(0, os.path.abspath("../.."))
# -- Project information -----------------------------------------------------

View File

@ -68,12 +68,6 @@ class Command(CommandDefinition):
if args.module is not None:
manager.config.back()
except pwncat.modules.ModuleFailed as exc:
if args.traceback:
console.print_exception()
else:
console.log(f"[red]error[/red]: module failed: {exc}")
return
except pwncat.modules.ModuleNotFound:
console.log(f"[red]error[/red]: {module_name}: not found")
return
@ -86,6 +80,12 @@ class Command(CommandDefinition):
except pwncat.modules.InvalidArgument as exc:
console.log(f"[red]error[/red]: invalid argument: {exc}")
return
except pwncat.modules.ModuleFailed as exc:
if args.traceback:
console.print_exception()
else:
console.log(f"[red]error[/red]: module failed: {exc}")
return
if isinstance(result, list):
result = [r for r in result if not r.hidden]

View File

@ -80,9 +80,14 @@ class Command(CommandDefinition):
try:
if manager.sessions and args.variable == "db":
raise ValueError("cannot change database with running session")
if args.variable in manager.config:
manager.config.set(
args.variable, args.value, getattr(args, "global")
)
else:
console.log(
f"[red]error[/red]: invalid choice {repr(args.variable)}"
)
if args.variable == "db":
# Ensure the database is re-opened, if it was already
manager.open_database()
@ -95,10 +100,15 @@ class Command(CommandDefinition):
except ValueError as exc:
console.log(f"[red]error[/red]: {exc}")
elif args.variable is not None:
if args.variable in manager.config:
value = manager.config[args.variable]
console.print(
f" [cyan]{args.variable}[/cyan] = [yellow]{repr(value)}[/yellow]"
)
else:
console.log(
f"[red]error[/red]: invalid choice {repr(args.variable)}"
)
else:
for name in manager.config:
value = manager.config[name]

View File

@ -14,6 +14,7 @@ from rich.progress import (
import pwncat
from pwncat.util import console, copyfileobj, human_readable_size, human_readable_delta
from pwncat.commands import Complete, Parameter, CommandDefinition
from pwncat.platform import PlatformError
class Command(CommandDefinition):
@ -77,5 +78,10 @@ class Command(CommandDefinition):
f"uploaded [cyan]{human_readable_size(length)}[/cyan] "
f"in [green]{human_readable_delta(elapsed)}[/green]"
)
except (FileNotFoundError, PermissionError, IsADirectoryError) as exc:
except (
FileNotFoundError,
PermissionError,
IsADirectoryError,
PlatformError,
) as exc:
self.parser.error(str(exc))

View File

@ -41,7 +41,7 @@ class AuthorizedKeyImplant(PrivateKey):
user = session.find_user(uid=self.uid)
if current_user.id != self.uid and current_user.id != 0:
raise ModuleFailed(f"must be root or {user.name}")
raise ModuleFailed(f"must be [blue]root[/blue] or [blue]{user.name}[/blue]")
# Ensure the directory exists
homedir = session.platform.Path(user.home)
@ -93,10 +93,12 @@ class Module(ImplantModule):
yield Status("verifying user permissions")
current_user = session.current_user()
if user != "__pwncat_current__" and current_user.id != 0:
raise ModuleFailed("only root can install implants for other users")
raise ModuleFailed(
"only [blue]root[/blue] can install implants for other users"
)
if not os.path.isfile(key):
raise ModuleFailed(f"private key {key} does not exist")
raise ModuleFailed(f"private key [blue]{key}[/blue] does not exist")
try:
yield Status("reading public key")
@ -119,7 +121,7 @@ class Module(ImplantModule):
for implant in session.run("enumerate", types=["implant.*"]):
if implant.source == self.name and implant.uid == user_info.uid:
raise ModuleFailed(
f"{self.name} already installed for {user_info.name}"
f"[blue]{self.name}[/blue] already installed for [blue]{user_info.name}[/blue]"
)
# Ensure the directory exists

View File

@ -1111,7 +1111,7 @@ class Linux(Platform):
)
if isinstance(args, list):
command = shlex.join(args)
command = shlex.join(str(arg) for arg in args)
elif isinstance(args, str):
command = args
else:

View File

@ -146,7 +146,7 @@ def human_readable_delta(seconds):
def join(argv: List[str]):
"""Join the string much line shlex.join, except assume that each token
"""Join the string much like shlex.join, except assume that each token
is expecting double quotes. This allows variable references within the
tokens."""

View File

@ -8,9 +8,10 @@ import dataclasses
from io import StringIO
import pytest
from pwncat.channel import ChannelError
from Crypto.PublicKey import RSA
from pwncat.channel import ChannelError
PLATFORM_MAP = {"ubuntu": "linux", "centos": "linux", "windows": "windows"}
@ -37,13 +38,13 @@ def connection_details_for(name):
@pytest.fixture(params=["ubuntu", "centos"])
def linux_details(request):
""" Get available connection details for linux hosts """
"""Get available connection details for linux hosts"""
return connection_details_for(request.param)
@pytest.fixture(params=["windows"])
def windows_details(request):
""" Get available connection details for windows hosts """
"""Get available connection details for windows hosts"""
return connection_details_for(request.param)
@ -84,18 +85,18 @@ set -g db "memory://"
@pytest.fixture(params=["windows", "ubuntu", "centos"])
def session(request):
""" Start a session with any platform """
"""Start a session with any platform"""
yield from session_for(request)
@pytest.fixture(params=["windows"])
def windows(request):
""" Start a windows session """
"""Start a windows session"""
yield from session_for(request)
@pytest.fixture(params=["ubuntu", "centos"])
def linux(request):
""" Start a linux session """
"""Start a linux session"""
yield from session_for(request)

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3
import pytest
from pwncat.modules import IncorrectPlatformError
@ -13,13 +14,13 @@ def test_session_iter_users(session):
def test_session_find_user_name(session):
""" Test that locating a user by name works """
"""Test that locating a user by name works"""
assert session.find_user(name="john") is not None
def test_session_find_user_uid(linux):
""" Test locating a user by their UID (for linux only) """
"""Test locating a user by their UID (for linux only)"""
user = linux.find_user(uid=0)
@ -28,7 +29,7 @@ def test_session_find_user_uid(linux):
def test_session_find_user_sid(windows):
""" Test locating a user by their SID (for windows only) """
"""Test locating a user by their SID (for windows only)"""
# This is the SID of the Administrator in the windows servercore image...
# This will only work from the testing container, but I've decided that's fine.
@ -39,7 +40,7 @@ def test_session_find_user_sid(windows):
def test_session_find_module(session):
""" Test that locating modules works """
"""Test that locating modules works"""
assert len(list(session.find_module("enumerate.*"))) > 0
assert len(list(session.find_module("enumerate.user"))) == 1
@ -47,7 +48,7 @@ def test_session_find_module(session):
def test_session_run_module(session):
""" Test running a module within a session """
"""Test running a module within a session"""
# We should be able to enumerate a hostname
facts = session.run("enumerate", types=["system.hostname"])
@ -55,14 +56,14 @@ def test_session_run_module(session):
def test_session_wrong_platform_linux(linux):
""" Test that windows modules don't run in linux """
"""Test that windows modules don't run in linux"""
with pytest.raises(IncorrectPlatformError):
linux.run("windows.enumerate.user")
def test_session_wrong_platform_windows(windows):
""" Test that linux modules don't run on windows """
"""Test that linux modules don't run on windows"""
with pytest.raises(IncorrectPlatformError):
windows.run("linux.enumerate.user")