penpal package

Submodules

penpal.baseexecutor module

class penpal.baseexecutor.BaseExecutor(cmdconfig=None)

Bases: object

The BaseExecutor is the base class of all Executors. It enables base functionality for all Executors and provides a structure for all Executors.

In order to create a custom Executor, one must simply derive from the BaseExecutor and implement the method _exec_cmd()

error_if(command: BaseCommand, result: Result)
error_if_not(command: BaseCommand, result: Result)
exec(command: BaseCommand)
log_command(command)

Log starting-status of the command

loop_if(command: BaseCommand, result: Result)
loop_if_not(command: BaseCommand, result: Result)
run(command: BaseCommand)

Execute the command

This method is executed by PenPal and executes the given command. This method sets the run_count to 1 and runs the method exec()

Parameters:

command (BaseCommand) – The settings for the command to execute

exception penpal.baseexecutor.ExecException

Bases: Exception

Exception for all Executors

This exception is raised by Executors if anything goes wrong. The BaseExecutor will catch the Exception, writes it to the console and exits gracefully.

class penpal.baseexecutor.Result(stdout, returncode)

Bases: object

Instances of this Result-class will be returned by the Executors. It stores the standard-output and the returncode.

returncode: int
stdout: str

penpal.metadata module

penpal.msfexecutor module

class penpal.msfexecutor.MsfModuleExecutor(cmdconfig=None, *, msfconfig=None, msfsessionstore: MsfSessionStore)

Bases: BaseExecutor

connect(msfconfig=None)
log_command(command: BaseCommand)

Log starting-status of the command

prepare_exploit(command: MsfModuleCommand)
prepare_payload(command: MsfModuleCommand)

penpal.penpal module

PenPal reads a playbook and executes the attack

A playbook stored in a dictionary with a list of attacks. Attacks are executed by “Executors”. There are many different Executors like: ShellExecutor, SleepExecutor or MsfModuleExecutor This class creates instances of all possible Executors, iterates over all attacks and runs the specific Executor with the given configuration.

class penpal.penpal.PenPal(config_file: str)

Bases: object

initialize_executors()

Initialize all Executors

Executors are supposed to execute commands. This method initializes all possible executors.

initialize_variable_parser()

Initializes the variable-parser

The variable-parser replaces variables with values in certain strings

main()

The main function

This function calls the variable_parser() and interates over all configured commands and passes them to the executors.

parse_config(config_file: str)

Config-Parser for PenPal

This parser reads the playbook-file and validates the config-settings.

Parameters:

config_file (str) – The path to a yaml-playbook

Notes

This method will exit(1) on errors.

penpal.schemas module

class penpal.schemas.BaseCommand(*, error_if: str | None = None, error_if_not: str | None = None, loop_if: str | None = None, loop_if_not: str | None = None, loop_count: int = 3, exit_on_error: bool = True, cmd: str)

Bases: BaseModel

cmd: str
error_if: str | None
error_if_not: str | None
exit_on_error: bool
loop_count: int
loop_if: str | None
loop_if_not: str | None
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class penpal.schemas.CommandConfig(*, loop_sleep: int = 5)

Bases: BaseModel

loop_sleep: int
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class penpal.schemas.Config(*, msf_config: MsfConfig = MsfConfig(password=None, ssl=True, port=55553, server='127.0.0.1', uri='/api/'), cmd_config: CommandConfig = CommandConfig(loop_sleep=5), vars: Dict[str, str] | None = None, commands: List[ShellCommand | MsfModuleCommand | MsfSessionCommand | SleepCommand | SSHCommand])

Bases: BaseModel

cmd_config: CommandConfig
commands: List[ShellCommand | MsfModuleCommand | MsfSessionCommand | SleepCommand | SSHCommand]
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

msf_config: MsfConfig
vars: Dict[str, str] | None
class penpal.schemas.MsfConfig(*, password: str | None = None, ssl: bool = True, port: int = 55553, server: str | None = '127.0.0.1', uri: str | None = '/api/')

Bases: BaseModel

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

password: str | None
port: int
server: str | None
ssl: bool
uri: str | None
class penpal.schemas.MsfModuleCommand(*, error_if: str | None = None, error_if_not: str | None = None, loop_if: str | None = None, loop_if_not: str | None = None, loop_count: int = 3, exit_on_error: bool = True, cmd: str, type: Literal['msf-module'], target: int = 0, creates_session: str | None, session: str | None, payload: str | None, options: Dict[str, str] = {}, payload_options: Dict[str, str] = {})

Bases: BaseCommand

cmd: str
creates_session: str | None
is_interactive()
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

module_path()
module_type()
options: Dict[str, str]
payload: str | None
payload_options: Dict[str, str]
session: str | None
target: int
type: Literal['msf-module']
class penpal.schemas.MsfSessionCommand(*, error_if: str | None = None, error_if_not: str | None = None, loop_if: str | None = None, loop_if_not: str | None = None, loop_count: int = 3, exit_on_error: bool = True, cmd: str, type: Literal['msf-session'], stdapi: bool = False, write: bool = False, read: bool = False, session: str, end_str: str | None)

Bases: BaseCommand

cmd: str
end_str: str | None
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

read: bool
session: str
stdapi: bool
type: Literal['msf-session']
write: bool
class penpal.schemas.SSHCommand(*, error_if: str | None = None, error_if_not: str | None = None, loop_if: str | None = None, loop_if_not: str | None = None, loop_count: int = 3, exit_on_error: bool = True, cmd: str, type: Literal['ssh'], hostname: str | None, port: int | None, username: str | None, password: str | None, passphrase: str | None, key_filename: str | None, creates_session: str | None, session: str | None, clear_cache: bool = False, timeout: float = 60, jmp_hostname: str | None, jmp_port: int | None, jmp_username: str | None)

Bases: BaseCommand

clear_cache: bool
creates_session: str | None
hostname: str | None
jmp_hostname: str | None
jmp_port: int | None
jmp_username: str | None
key_filename: str | None
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

passphrase: str | None
password: str | None
port: int | None
session: str | None
timeout: float
type: Literal['ssh']
username: str | None
class penpal.schemas.ShellCommand(*, error_if: str | None = None, error_if_not: str | None = None, loop_if: str | None = None, loop_if_not: str | None = None, loop_count: int = 3, exit_on_error: bool = True, cmd: str, type: Literal['shell'])

Bases: BaseCommand

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

type: Literal['shell']
class penpal.schemas.SleepCommand(*, error_if: str | None = None, error_if_not: str | None = None, loop_if: str | None = None, loop_if_not: str | None = None, loop_count: int = 3, exit_on_error: bool = True, cmd: str = 'sleep', type: Literal['sleep'], min_sec: int = 0, seconds: int = 1, random: bool = False)

Bases: BaseCommand

cmd: str
min_sec: int
model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

random: bool
seconds: int
type: Literal['sleep']

penpal.shellexecutor module

shellexecutor.py

This class enables executing shell commands in PenPal.

class penpal.shellexecutor.ShellExecutor(cmdconfig=None)

Bases: BaseExecutor

log_command(command: BaseCommand)

Log starting-status of the command

penpal.sleepexecutor module

class penpal.sleepexecutor.SleepExecutor(cmdconfig=None)

Bases: BaseExecutor

log_command(command)

Log starting-status of the command

set_sleeptime(command)

penpal.varparse module

class penpal.varparse.VarParse(variables)

Bases: object

parse_command(parse_str)

Module contents