In order to provide a convenient API, Sploitkit defines a central class aimed to declare everything that can be tuned and imported to make a new CLI framework. As explained previously, this central class is called
Entity. This holds the generic logic, namely for :
- registering entity classes (see hereafter:
- handling requirements, dynamically enabling/disabling entities
- handling metadata (formatting them for display in the CLI)
Requirements and applicability¶
Requirements can be defined in order to dynamically enable/disable entities. These are managed through the
requirements class attribute. Currently, a few requirement types exist :
Option values to be set (see hereafter).
|List of files that must exist in the current workspace.
|List of Python packages required to be installed in the environment.
|State variables to be set in the Global State (see section Console) ; can be defined in three ways :
|List of system tools and/or packages to be installed ; can be defined in two ways :
In parallel with the requirements, the applicability is checked, that is, if the entity has a reference with a value that exactly matches the expected one.
Example: Setting a command as applicable only for modules named '
Let us consider defining a command that only applies to any module whose name is "
do_something". Then defining the
applies_to attribute like hereafter allows to limit the scope of the command to only modules named so.
1 2 3 4 5
Inheritance and aggregation¶
Entities can be defined in subclasses as a tree structure so that the leaves share some information from their proxy subclasses. The precedence goes bottom-up, that is, from the leaves to the entity classes. This is especially the case for :
configattribute (applies to consoles and modules) : Configurations are agreggated (in a
ProxyConfiginstance) so that an option that is common to multiple entities can be defined only once and modified for all these entities at once during the execution.
- Metadata (especially useful for modules) : metadata is aggregated (during entity import only) so that, if multiple modules inheriting from a proxy class have, for instance, the same author, this data can be declared only once in the proxy class and applied to modules.
Metadata of entities can be defined in three different ways (can be combined, listed hereafter in inverse order of precedence) :
- Docstring : By default, Sploitkit provides a parsing function that follows the convention presented hereafter, resulting in a dictionary of metadata key-values. However, a custom parsing function can be input as an argument when instantiating a parent
metaattribute : A dictionary of metadata key-values that will update the final metadata dictionary.
metadataattribute : Same as for
meta(exists for a question of cross-compatibility with plugins of other frameworks).
This leads to a
_metadata class attribute holding the metadata dictionary. Note that, when
metadata class attributes are use to update
_metadata, they are removed to only hold this last one. This is mostly a question of compatibility with modules of other frameworks (e.g. Recon-ng).
Options can even be defined through the
metadata class attributes (but NOT directly
_metadata as it is created/overwritten when parsing the docstring). Their format follows this convention : (name, default_value, required, description). It contains less fields than what is really supported (see the
Option class in the next subsection) but, once again, it is mostly a question of compatibility with modules from other frameworks.
The default docstring format (parsed through a dedicated function within Sploitkit's utils) consists of sections separated by double newlines. Parsing occurs as follows :
- The first section is always the description.
Next sections are handled this way :
If the first line of the section follows the convention hereafter, it is parsed as a separated field (saved in the metadata dictionary as lowercase) up to the next field-value OR section's end.
That is, the field name capitalized with no whitespace before the colon and whatever value, multiline.
If the first line of the section does not follow the convention, it is parsed as a comment and saved into the comments list of the metadata dictionary. Note that using the field name comments append the value to the comments list of the metadata dictionary.
Example: Writing a docstring for an entity
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
A configuration object is an instance of the
Config class subclassing the common type
dict and refining its capabilities to handle special key-value objects called
Option's that also have a description and other attributes (e.g.
required). This way, it is easier to associate more data than simply a value to a key, i.e. when it comes to providing help text about the option.
A configuration is declared by providing a dictionary as the only positional argument and/or key-values as keyword-arguments. It is important to note that, if options are defined with the keyword-arguments, they won't of course have any other data defined but they will be easilly accessible for further tuning.
Example: Declaring a configuration (entity class attribute)
1 2 3 4 5 6
Two types of option exist (for a question of performance) :
Option (the normal one) and
ROption (aka Resetting Option) that triggers resetting the entity bindings (e.g. the commands applicability to the current console given the new option). So, beware that, when using the
Option class, the modification of its value does not update bindings between entities.
An example of use of the behavior of
ROption is when a
config requirement is used in another entity which is to be enabled/disabled according to option's value. This way, entity bindings are reset when tuning the option like when starting a console (for more details on this, see section Console).
A configuration option object, that is, an instance of the
ROption class, is defined using multiple arguments :
|option's name, conventionally uppercase
|help text for this option
|whether it shall be defined or not
|the possible values (as a list or lazily defined through a lambda function that outputs a list), used for validation ; its value can also be
bool (the type, not as a string !) for setting choices to false and true
|a function that is triggered after setting the value
|a function that is triggered after unsetting the value
|a function transforming the value input as for any dictionary, but for computing a new value
|by default, a lambda function that checks for the given
choices if defined, but can be tuned accordingly
Each lambda function takes
self as the first argument.
validate also takes option's value as the second argument.
Config declaration (extract from the
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16