Skip to content

Commit 5b8c846

Browse files
authored
Merge pull request #246 from Mitul16/master
Fixes #245 and minor patches
2 parents 49b23fd + 8549ca3 commit 5b8c846

File tree

10 files changed

+63
-34
lines changed

10 files changed

+63
-34
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77
The Changelog starts with v0.4.1, because we did not keep one before that,
88
and simply didn't have the time to go back and retroactively create one.
99

10+
## [Unreleased]
11+
### Fixed
12+
- Fixed `shlex.join` use with non-str type objects (e.g. `RemotePath`)
13+
- Fixed `set` command use with incorrect keys (e.g. `set invalid value`)
14+
15+
### Added
16+
- Added missed `PlatformError` for `upload` command (e.g. "no gtfobins writers available")
17+
1018
## [0.5.4] - 2022-01-27
1119
Bug fix for the `load` command.
1220

docs/source/conf.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
#
1313
import os
1414
import sys
15-
sys.path.insert(0, os.path.abspath('../..'))
15+
16+
sys.path.insert(0, os.path.abspath("../.."))
1617

1718

1819
# -- Project information -----------------------------------------------------

pwncat/commands/run.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,6 @@ def run(self, manager: "pwncat.manager.Manager", args):
6868

6969
if args.module is not None:
7070
manager.config.back()
71-
except pwncat.modules.ModuleFailed as exc:
72-
if args.traceback:
73-
console.print_exception()
74-
else:
75-
console.log(f"[red]error[/red]: module failed: {exc}")
76-
return
7771
except pwncat.modules.ModuleNotFound:
7872
console.log(f"[red]error[/red]: {module_name}: not found")
7973
return
@@ -86,6 +80,12 @@ def run(self, manager: "pwncat.manager.Manager", args):
8680
except pwncat.modules.InvalidArgument as exc:
8781
console.log(f"[red]error[/red]: invalid argument: {exc}")
8882
return
83+
except pwncat.modules.ModuleFailed as exc:
84+
if args.traceback:
85+
console.print_exception()
86+
else:
87+
console.log(f"[red]error[/red]: module failed: {exc}")
88+
return
8989

9090
if isinstance(result, list):
9191
result = [r for r in result if not r.hidden]

pwncat/commands/set.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,14 @@ def run(self, manager, args):
8080
try:
8181
if manager.sessions and args.variable == "db":
8282
raise ValueError("cannot change database with running session")
83-
manager.config.set(
84-
args.variable, args.value, getattr(args, "global")
85-
)
83+
if args.variable in manager.config:
84+
manager.config.set(
85+
args.variable, args.value, getattr(args, "global")
86+
)
87+
else:
88+
console.log(
89+
f"[red]error[/red]: invalid choice {repr(args.variable)}"
90+
)
8691
if args.variable == "db":
8792
# Ensure the database is re-opened, if it was already
8893
manager.open_database()
@@ -95,10 +100,15 @@ def run(self, manager, args):
95100
except ValueError as exc:
96101
console.log(f"[red]error[/red]: {exc}")
97102
elif args.variable is not None:
98-
value = manager.config[args.variable]
99-
console.print(
100-
f" [cyan]{args.variable}[/cyan] = [yellow]{repr(value)}[/yellow]"
101-
)
103+
if args.variable in manager.config:
104+
value = manager.config[args.variable]
105+
console.print(
106+
f" [cyan]{args.variable}[/cyan] = [yellow]{repr(value)}[/yellow]"
107+
)
108+
else:
109+
console.log(
110+
f"[red]error[/red]: invalid choice {repr(args.variable)}"
111+
)
102112
else:
103113
for name in manager.config:
104114
value = manager.config[name]

pwncat/commands/upload.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import pwncat
1515
from pwncat.util import console, copyfileobj, human_readable_size, human_readable_delta
1616
from pwncat.commands import Complete, Parameter, CommandDefinition
17+
from pwncat.platform import PlatformError
1718

1819

1920
class Command(CommandDefinition):
@@ -77,5 +78,10 @@ def run(self, manager: "pwncat.manager.Manager", args):
7778
f"uploaded [cyan]{human_readable_size(length)}[/cyan] "
7879
f"in [green]{human_readable_delta(elapsed)}[/green]"
7980
)
80-
except (FileNotFoundError, PermissionError, IsADirectoryError) as exc:
81+
except (
82+
FileNotFoundError,
83+
PermissionError,
84+
IsADirectoryError,
85+
PlatformError,
86+
) as exc:
8187
self.parser.error(str(exc))

pwncat/modules/linux/implant/authorized_key.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def remove(self, session: "pwncat.manager.Session"):
4141
user = session.find_user(uid=self.uid)
4242

4343
if current_user.id != self.uid and current_user.id != 0:
44-
raise ModuleFailed(f"must be root or {user.name}")
44+
raise ModuleFailed(f"must be [blue]root[/blue] or [blue]{user.name}[/blue]")
4545

4646
# Ensure the directory exists
4747
homedir = session.platform.Path(user.home)
@@ -93,10 +93,12 @@ def install(self, session: "pwncat.manager.Session", user, key):
9393
yield Status("verifying user permissions")
9494
current_user = session.current_user()
9595
if user != "__pwncat_current__" and current_user.id != 0:
96-
raise ModuleFailed("only root can install implants for other users")
96+
raise ModuleFailed(
97+
"only [blue]root[/blue] can install implants for other users"
98+
)
9799

98100
if not os.path.isfile(key):
99-
raise ModuleFailed(f"private key {key} does not exist")
101+
raise ModuleFailed(f"private key [blue]{key}[/blue] does not exist")
100102

101103
try:
102104
yield Status("reading public key")
@@ -119,7 +121,7 @@ def install(self, session: "pwncat.manager.Session", user, key):
119121
for implant in session.run("enumerate", types=["implant.*"]):
120122
if implant.source == self.name and implant.uid == user_info.uid:
121123
raise ModuleFailed(
122-
f"{self.name} already installed for {user_info.name}"
124+
f"[blue]{self.name}[/blue] already installed for [blue]{user_info.name}[/blue]"
123125
)
124126

125127
# Ensure the directory exists

pwncat/platform/linux.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1111,7 +1111,7 @@ def Popen(
11111111
)
11121112

11131113
if isinstance(args, list):
1114-
command = shlex.join(args)
1114+
command = shlex.join(str(arg) for arg in args)
11151115
elif isinstance(args, str):
11161116
command = args
11171117
else:

pwncat/util.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ def human_readable_delta(seconds):
146146

147147

148148
def join(argv: List[str]):
149-
"""Join the string much line shlex.join, except assume that each token
149+
"""Join the string much like shlex.join, except assume that each token
150150
is expecting double quotes. This allows variable references within the
151151
tokens."""
152152

tests/conftest.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
from io import StringIO
99

1010
import pytest
11-
from pwncat.channel import ChannelError
1211
from Crypto.PublicKey import RSA
1312

13+
from pwncat.channel import ChannelError
14+
1415
PLATFORM_MAP = {"ubuntu": "linux", "centos": "linux", "windows": "windows"}
1516

1617

@@ -37,13 +38,13 @@ def connection_details_for(name):
3738

3839
@pytest.fixture(params=["ubuntu", "centos"])
3940
def linux_details(request):
40-
""" Get available connection details for linux hosts """
41+
"""Get available connection details for linux hosts"""
4142
return connection_details_for(request.param)
4243

4344

4445
@pytest.fixture(params=["windows"])
4546
def windows_details(request):
46-
""" Get available connection details for windows hosts """
47+
"""Get available connection details for windows hosts"""
4748
return connection_details_for(request.param)
4849

4950

@@ -84,18 +85,18 @@ def session_for(request):
8485

8586
@pytest.fixture(params=["windows", "ubuntu", "centos"])
8687
def session(request):
87-
""" Start a session with any platform """
88+
"""Start a session with any platform"""
8889
yield from session_for(request)
8990

9091

9192
@pytest.fixture(params=["windows"])
9293
def windows(request):
93-
""" Start a windows session """
94+
"""Start a windows session"""
9495
yield from session_for(request)
9596

9697

9798
@pytest.fixture(params=["ubuntu", "centos"])
9899
def linux(request):
99-
""" Start a linux session """
100+
"""Start a linux session"""
100101

101102
yield from session_for(request)

tests/test_session.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env python3
22

33
import pytest
4+
45
from pwncat.modules import IncorrectPlatformError
56

67

@@ -13,13 +14,13 @@ def test_session_iter_users(session):
1314

1415

1516
def test_session_find_user_name(session):
16-
""" Test that locating a user by name works """
17+
"""Test that locating a user by name works"""
1718

1819
assert session.find_user(name="john") is not None
1920

2021

2122
def test_session_find_user_uid(linux):
22-
""" Test locating a user by their UID (for linux only) """
23+
"""Test locating a user by their UID (for linux only)"""
2324

2425
user = linux.find_user(uid=0)
2526

@@ -28,7 +29,7 @@ def test_session_find_user_uid(linux):
2829

2930

3031
def test_session_find_user_sid(windows):
31-
""" Test locating a user by their SID (for windows only) """
32+
"""Test locating a user by their SID (for windows only)"""
3233

3334
# This is the SID of the Administrator in the windows servercore image...
3435
# This will only work from the testing container, but I've decided that's fine.
@@ -39,30 +40,30 @@ def test_session_find_user_sid(windows):
3940

4041

4142
def test_session_find_module(session):
42-
""" Test that locating modules works """
43+
"""Test that locating modules works"""
4344

4445
assert len(list(session.find_module("enumerate.*"))) > 0
4546
assert len(list(session.find_module("enumerate.user"))) == 1
4647
assert len(list(session.find_module("module_does_not_exist"))) == 0
4748

4849

4950
def test_session_run_module(session):
50-
""" Test running a module within a session """
51+
"""Test running a module within a session"""
5152

5253
# We should be able to enumerate a hostname
5354
facts = session.run("enumerate", types=["system.hostname"])
5455
assert len(facts) > 0
5556

5657

5758
def test_session_wrong_platform_linux(linux):
58-
""" Test that windows modules don't run in linux """
59+
"""Test that windows modules don't run in linux"""
5960

6061
with pytest.raises(IncorrectPlatformError):
6162
linux.run("windows.enumerate.user")
6263

6364

6465
def test_session_wrong_platform_windows(windows):
65-
""" Test that linux modules don't run on windows """
66+
"""Test that linux modules don't run on windows"""
6667

6768
with pytest.raises(IncorrectPlatformError):
6869
windows.run("linux.enumerate.user")

0 commit comments

Comments
 (0)