Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and simply didn't have the time to go back and retroactively create one.

### Added
- Added missed `PlatformError` for `upload` command (e.g. "no gtfobins writers available")
- Addes Python 3.13 support

## [0.5.4] - 2022-01-27
Bug fix for the `load` command.
Expand Down
57 changes: 26 additions & 31 deletions pwncat/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,46 +34,43 @@ class Command(CommandDefinition):
def run(self, manager: "pwncat.manager.Manager", args: "argparse.Namespace"):
manager.log("we ran a custom command!")
"""

import argparse
import fcntl
import importlib
import os
import pkgutil
import re
import sys
import tty
import fcntl
import shlex
import pkgutil
import sys
import termios
import argparse
from io import TextIOWrapper
import tty
from enum import Enum, auto
from typing import Dict, List, Type, Callable, Iterable
from functools import partial
from io import TextIOWrapper
from typing import Callable, Dict, Iterable, List, Type

import rich.text
from pygments import token
from prompt_toolkit import ANSI, PromptSession
from pygments.lexer import RegexLexer
from pygments.styles import get_style_by_name
from prompt_toolkit.lexers import PygmentsLexer
from prompt_toolkit.styles import Style, merge_styles
from prompt_toolkit.history import History
from prompt_toolkit.application.current import get_app
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
from prompt_toolkit.completion import (CompleteEvent, Completer, Completion,
WordCompleter, merge_completers)
from prompt_toolkit.document import Document
from prompt_toolkit.completion import (
Completer,
Completion,
CompleteEvent,
WordCompleter,
merge_completers,
)
from prompt_toolkit.history import History
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
from prompt_toolkit.lexers import PygmentsLexer
from prompt_toolkit.patch_stdout import patch_stdout
from prompt_toolkit.styles import Style, merge_styles
from prompt_toolkit.styles.pygments import style_from_pygments_cls
from prompt_toolkit.application.current import get_app
from pygments import token
from pygments.lexer import RegexLexer
from pygments.styles import get_style_by_name

import pwncat
import pwncat.db
from pwncat.util import console
from pwncat.channel import ChannelClosed
from pwncat.util import console


class Complete(Enum):
Expand Down Expand Up @@ -432,20 +429,17 @@ def __init__(self, manager: "pwncat.manager.Manager"):
for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):
if module_name == "base":
continue
self.commands.append(
loader.find_module(module_name)
.load_module(module_name)
.Command(manager)
)
full_module_name = f"{__name__}.{module_name}"
module = importlib.import_module(full_module_name)
self.commands.append(module.Command(manager))

self.prompt: PromptSession = None
self.toolbar: PromptSession = None
self.loading_complete = False
self.aliases: Dict[str, CommandDefinition] = {}
self.shortcuts: Dict[str, CommandDefinition] = {}
self.found_prefix: bool = False
# Saved terminal state to support switching between raw and normal
# mode.
# Saved terminal state to support switching between raw and normal mode.
self.saved_term_state = None

def setup_prompt(self):
Expand Down Expand Up @@ -788,7 +782,8 @@ def restore_term(self, new_line=True):

class CommandLexer(RegexLexer):
"""Implements a Regular Expression based pygments lexer for dynamically highlighting
the pwncat prompt during typing. The tokens are generated from command definitions."""
the pwncat prompt during typing. The tokens are generated from command definitions.
"""

tokens = {}

Expand Down
56 changes: 31 additions & 25 deletions pwncat/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,43 +23,46 @@
callback which receives the new session as an argument.

"""

import contextlib
import datetime
import fnmatch
import importlib
import importlib.util
import os
import ssl
import sys
import pkgutil
import queue
import signal
import socket
import fnmatch
import pkgutil
import datetime
import ssl
import sys
import tempfile
import threading
import contextlib
from io import TextIOWrapper
from enum import Enum, auto
from typing import Dict, List, Tuple, Union, Callable, Optional, Generator
from io import TextIOWrapper
from typing import Callable, Dict, Generator, List, Optional, Tuple, Union

import persistent.list
import rich.progress
import ZODB
import zodburi
import rich.progress
import persistent.list
from cryptography import x509
from cryptography.x509.oid import NameOID
from prompt_toolkit.shortcuts import confirm
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.x509.oid import NameOID
from prompt_toolkit.shortcuts import confirm

import pwncat.db
import pwncat.facts
import pwncat.modules
import pwncat.modules.enumerate
from pwncat.util import RawModeExit, console
from pwncat.config import Config
from pwncat.target import Target
from pwncat.channel import Channel, ChannelError, ChannelClosed
from pwncat.channel import Channel, ChannelClosed, ChannelError
from pwncat.commands import CommandParser
from pwncat.platform import Platform, PlatformError
from pwncat.config import Config
from pwncat.modules.enumerate import Scope
from pwncat.platform import Platform, PlatformError
from pwncat.target import Target
from pwncat.util import RawModeExit, console


class InteractiveExit(Exception):
Expand Down Expand Up @@ -388,7 +391,8 @@ def _open_socket(self) -> socket.socket:

def _ssl_wrap(self, server: socket.socket) -> ssl.SSLSocket:
"""Wrap the given server socket in an SSL context and return the new socket.
If the ``ssl`` option is not set, this method simply returns the original socket."""
If the ``ssl`` option is not set, this method simply returns the original socket.
"""

if not self.ssl:
return server
Expand Down Expand Up @@ -925,28 +929,30 @@ def load_modules(self, *paths):
"""Dynamically load modules from the specified paths

If a module has the same name as an already loaded module, it will
take it's place in the module list. This includes built-in modules.
take its place in the module list. This includes built-in modules.
"""

for loader, module_name, _ in pkgutil.walk_packages(
paths, prefix="pwncat.modules."
):

# Why is this check *not* part of pkgutil??????? D:<
if module_name not in sys.modules:
module = loader.find_module(module_name).load_module(module_name)
try:
module = importlib.import_module(module_name)
except ImportError:
continue # Skip modules that can't be loaded
else:
module = sys.modules[module_name]

if getattr(module, "Module", None) is None:
continue

# Create an instance of this module
module_name = module_name.split("pwncat.modules.")[1]
self.modules[module_name] = module.Module()
short_name = module_name.split("pwncat.modules.")[1]
self.modules[short_name] = module.Module()

# Store it's name so we know it later
setattr(self.modules[module_name], "name", module_name)
# Store its name so we know it later
setattr(self.modules[short_name], "name", short_name)

def log(self, *args, **kwargs):
"""Output a log entry"""
Expand Down