SmokeyJab is a framework that simulates post-exploitation IOC's in an auditable and repeatable way, to exercise detection capabilities and strategies. IOC's are taken largely from MITRE's ATT&CK framework.
git clone https://github.com/klustic/SmokeyJab
The provision.py
script is used to generate a runnable SmokeyJab payload. It does the following:
- Load each module and check it for basic syntax and required components
- Perform any necessary module-level configuration
- Generate a configuration template (optional) to fill in for repeatability
If not generating a module-level configuration template, the provisioning script requires a Splunk HEC host/token and a project name, at the minimum, so have those ready up front.
This command creates a template with all the configuration details for every module:
$ python provision.py -g --config new-template.json
...
WARNING:root:Wrote module configuration template to new-template.json
If you want to force an option to be entered manually at provision time, simply remove it entirely from the JSON file.
WARNING: Do not leave items blank (e.g. ""
) in the configuration file!! This will cause the item to not be configured in its corresponding module, and will lead to undefined behavior.
Once completing a module configuration template, as generated above, you can use that template to automate payload provisioning:
$ python provision.py --config new-template.json -u hec.mydomain.com -t hec-token-looks-like-uuid -p TESTPROJECT
WARNING:root:Minimum engagement time: 86400 seconds (1d 0h 0m 0s)
WARNING:root:Recommended engagement time: 432000 seconds (5d 0h 0m 0s)
How long (seconds) do you want this engagement to run? 432000
WARNING:root:Engagement is expected to last 432000 seconds (5d 0h 0m 0s)
CRITICAL:root:Provision successful! Written to "interrogatingly_tailzie.py"
If you prefer to manually enter your configuration, just enter the same command above without the --config
option.
Note: You can provide a configuration with only some items specified. If you do this, you will be prompted for the missing items during provisioning.
SmokeyJab was tested on Ubuntu 16.04LTS (Python 2.7.12), CentOS 6.7 (Python 2.7.8 and Python 2.6.6), and CentOS 7.2 (Python 2.7.5).
Write the file to disk. Use the name generated by the provisioning script, as it will be overwritten in the process list with the name provided at provision time. Execute in the background as root (for best results), and then exit the terminal.
[root]# python interrogatingly_tailzie.py &
[1] 3124
[root]# exit
WARNING: On CentOS the hiding functionality fails. You should name your file something inconspicuous, and comment out the hide()
call in the script before executing it!
The SmokeyJab framework allows you to create new content and plug it in with minimal effort. All modules should subclass ModuleBase
, which takes care of some setup and basic testing.
Each module, at a minimum, should provide:
absolute_duration
: (integer) The expected runtime in seconds of the modulerelative_delay
: (integer) The delay, 0 <= x < 100, indicates the percentage of time through the total exercise that the module should execute (e.g. for a 2 day test, a module with arelative_delay
of 50 will execute after 1 day has passed).run()
: The function called by the framework
needs_root
: (bool) Tells the framework whether the module requires root permissions
hec_logger()
: A function used to send messages/events to Splunkutil_childproc()
: A function used to create a new orphaned process that executes a Python function (in memory) or any file (on disk)util_netconnect()
: A function that creates a network connection associated with an orphaned process, and provides a socket interfaceutil_orphanwait()
: A function that waits for a PID returned byutil_childproc()
to exit, with an optional timeout that will cause the process to be killed if the timeout expires.
Each module file should contain one module and should try to import ModuleBase
from the framework. This ensures that the checks work properly at provision time and IDE's function properly.
Each module should call self.start()
when it begins (i.e. at the beginning of run()
) and should call self.finish()
when it has completed its action (e.g. at the end of run()
). This sends start/finish logs to Splunk and contributes to auditing later.
If a module is going to create a measurable signature on the system (e.g. network connections, file handles, processes, etc.) it should run from an orphaned process to make it more difficult to trace the activity back to the SmokeyJab core.
For more information see Useful members of ModuleBase
above.
Recommend looking at the BindPort
module for a simple example of how a module works.