margaritashotgun¶
Python Remote Memory Aquisition
Quick Start¶
First, Install margaritashotgun.
Capture A Single Machine¶
A single machine can be captured using only the command line arguments for margaritashotgun.
First specify the server and user with the -s
and -u
flags respectively.
Next provide a path to an ssh key with -k
(or use a password with the -p
flag).
Finally provide a lime kernel module with -m
and specify an output file with -f
margaritashotgun -s 172.16.20.10 -u root -k root_access.pem -m lime-3.13.0-74-generic.ko -f 172.16.20.10-mem.lime
Save Memory In S3¶
To save a file to s3 simply replace the -f
or filename
flags with -b
or --bucket
. Ensure that you have aws credentials configured prior to executing the following command.
margaritashotgun -s 172.16.20.10 -u root -k root_access.pem -m lime-3.13.0-74-generic.ko -b memory_capture_bucket
Capture Multiple Machines¶
Run margaritashotgun with a configuration file like parallel_config.yml.example
aws:
bucket: memory_dump_example
hosts:
- addr: 52.36.191.XXX
port: 22
username: ec2-user
key: access.pem
module: lime-4.1.19-24.31.amzn1.x86_64.ko
- addr: 52.36.170.XXX
port: 22
username: ec2-user
key: access.pem
module: lime-4.1.19-24.31.amzn1.x86_64.ko
- addr: 52.36.210.XXX
port: 22
username: ubuntu
key: dev.pem
module: lime-3.13.0-74-generic.ko
- addr: 52.36.90.XXX
port: 22
username: ubuntu
key: dev.pem
module: lime-3.13.0-74-generic.ko
workers: 2
Here parallelism is limited to 2 workers.
Run the capture with:
margaritashotgun -c your_custom_config.yml.
Installation¶
System Requirements¶
Currently only linux is a supported platform. Running on OSX or Windows may be possible with minor modifications.
While margaritashotgun is written purely in python, some of the libraries used require additional system packages.
Fedora / RHEL Distributions¶
- python-devel (2.X or 3.X)
- python-pip
- libffi-devel
- openssl-devel
Debian Distributions¶
- python-dev (2.X or 3.X)
- python-pip
- libffi-dev
- libssl-dev
Install From PyPi¶
Margaritashotgun is not currently listed in PyPi, while we work on that install via one of the methods below.
Installing From Github¶
$ pip install git+ssh://git@github.com/ThreatResponse/margaritashotgun.git@master
$ margaritashotgun -h
Local Build and Install¶
$ git clone https://github.com/ThreatResponse/margaritashotgun.git
$ cd margaritashotgun
$ python setup.py
$ pip install dist/margarita_shotgun-*.tar.gz
$ margaritashotgun -h
Local Execution¶
In the previous two example dependencies are automatically resolved, if you simply want to run margaritashotgun using the script bin/margaritashotgun
you will have to manually install dependencies
$ git clone https://github.com/ThreatResponse/margaritashotgun.git
$ cd margaritashotgun
$ pip install -r requirements.txt
$ ./bin/margaritashotgun -h
User Guide¶
Contents
Command Line¶
Common Examples¶
See the quickstart for common examples.
Usage¶
margaritashotgun
has man configuration flags which are outlined in detail below.
$ margaritashotgun -h
usage: margaritashotgun [-h] (-c CONFIG | -s SERVER) [-P PORT] [-u USERNAME]
[-m MODULE] [-p PASSWORD] [-k KEY] [-f FILENAME]
[--repository] [--repository-url REPOSITORY_URL]
[-w WORKERS] [-v] [-b BUCKET | -o OUTPUT_DIR]
[-d LOG_DIR] [--log_prefix LOG_PREFIX]
Remote memory aquisition wrapper for LiME
optional arguments:
-h, --help show this help message and exit
-c CONFIG, --config CONFIG
path to config.yml
-s SERVER, --server SERVER
hostname or ip of target server
-b BUCKET, --bucket BUCKET
memory dump output bucket
-o OUTPUT_DIR, --output_dir OUTPUT_DIR
memory dump output directory
-P PORT, --port PORT ssh port on remote server
-u USERNAME, --username USERNAME
username for ssh connection
-m MODULE, --module MODULE
path to kernel lime kernel module
-p PASSWORD, --password PASSWORD
password for user or encrypted keyfile
-k KEY, --key KEY path to rsa key for ssh connection
-f FILENAME, --filename FILENAME
memory dump filename
--repository enable automatic kernel module downloads
--repository-url REPOSITORY_URL
repository url
-w WORKERS, --workers WORKERS
number of workers to run in parallel,default: auto
acceptable values are(INTEGER | "auto")
-v, --verbose log debug messages
-d LOG_DIR, --log_dir LOG_DIR
log directory
--log_prefix LOG_PREFIX
log file prefix
Config¶
The -c
and --config
flags accept a relative or absolute path to a yml config file.
The structure of this file is outlided in the Configuration
section below.
Server¶
The -s
and --server
flags specify the server being targeted for memory capture.
A DNS record or IP address are valid inputs.
Bucket¶
The -b
and --bucket
flags specify the destination bucket when dumping memory to s3.
This flag cannot be used in conjunction wth -o
or --output_dir
.
Output_Dir¶
The -o
and --output_dir
flags specify the destination folder when dumping memory to the local filesystem.
This flag cannot be used in conjunction with -b
or --bucket
.
Port¶
The -p
and --port
flags specify the port that ssh is running on the remote server specified by -s
or --server
.
This flag is optional and port 22
will be assumed if no value is provided.
Username¶
The -u
and --username
flags specify the user account to authenticate with when connecting to the remote server specified by -s
or --server
.
Module¶
The -m
and --module
flags accept a relative or absolute path to a LiME kernel module.
This flag is required if no kernel module repository is enabled with the --repository
flag.
Password¶
The -p
and --password
flags specify the password used for authentication with connection to the remote server specified by -s
or --server
.
When used in conjuction with the -k
or --key
flags this password will be used to unlock a protected private key file.
Key¶
The -k
and --key
flags accept a relative or absolute path to a a private key file used for authentication when connecting to the server specified by -s
or -server
.
If the private key file specified is password protected use the -p
or --password
flags to specify the password that unlocks the private key.
Filename¶
The -f
and --filename
flags specify the name of the file memory will be saved to when dumping to the local filesystem.
The file will be saved to the local directory unless the -o
or --output_dir
options are configured.
Repository¶
The --repository
flag enables automatic kernel module resolution via the repository configured with --repository-url
.
Margaritashotgun will not query any repositories unless explicitly enabled with the --repository
flag.
Repository_Url¶
The --repository-url
flag specifies where to search for kernel modules. The default public repository provided by Threat Response is availible at https://threatresponse-lime-modules.s3.amazonaws.com
Workers¶
The -w
and --workers
flags specify how many worker processes will be spawned to process memory captures in parallel.
The default value for this flag is auto
which will spawn a process per remote host up to the number of cpu cores on the local system.
Integer values can be provided instead of the auto
keyword.
Eg. --workers 3
will process 3 memory captures simultaneously.
Verbose¶
The -v
and --verbose
flags enable debug logging, including each command executed on remote hosts as a part of the memory capture process.
Log_Dir¶
The -d
and --log_dir
flags specify the directory in which to log files will be saved during memory capture.
Log_Prefix¶
The --log_prefix
flag allows a custom case number to be prepended onto log files for easy identification.
Configuration File¶
Example configuration files are availible in the repository. More documentation about the configuration file format is in the works.
Managing AWS Credentials¶
Margaritashotgun does not support explicitly declaring aws credentials. Currently the only way to interact with S3 is by configuring an aws profile.
A feature is planned to allow selecting a profile other than the default
profile. Until that feature is completed the default
profile must be used.
Wrapping Margarita Shotgun¶
Margarita Shotgun can be driven by another program when included as a python module. The configuration object passed to the margaritashotgun client must have the exact structure of the configuration file outlined above.
Example¶
>>> import margaritashotgun
>>> config = dict(aws dict(bucket = 'case-bucket'),
... hosts = [ dict(addr = '10.10.12.10',
... port = 22,
... username = 'ec2-user',
... key = '/path/to/private-key') ]
... workers = 'auto',
... logging = dict(log_dir = 'logs/',
... prefix = 'casenumber-10.10.12.10'),
... repository = dict(enabled = true,
... url = 'your-custom-kernel-module-repo.io'))
...
>>> capture_client = margaritashotgun.client(name='mem-capture', config=config,
... library=True, verbose=False)
...
>>> response = capture_client.run()
>>> print(response)
{'total':1,'failed':[],'completed':['10.10.12.10']}
Note that calling capture_client.run()
is a blocking operation.
Real world implementation¶
An example of wrapping margaritashotgun is the project aws ir availible on github.
Reference Guide¶
Authentication¶
Client¶
-
class
margaritashotgun.client.
Client
(config=None, library=True, name=None, verbose=False)¶ Client for parallel memory capture with LiME
-
__init__
(config=None, library=True, name=None, verbose=False)¶ Parameters:
-
__module__
= 'margaritashotgun.client'¶
-
map_config
()¶
-
run
()¶ Captures remote hosts memory
-
statistics
(results)¶
-
Cli¶
-
class
margaritashotgun.cli.
Cli
¶ -
__module__
= 'margaritashotgun.cli'¶
-
check_directory_path
(path)¶ Ensure directory exists at the provided path
Parameters: path (string) – path to directory to check
-
check_directory_paths
(*args)¶ Ensure all arguments correspond to directories
-
check_file_path
(path)¶ Ensure file exists at the provided path
Parameters: path (string) – path to directory to check
-
check_file_paths
(*args)¶ Ensure all arguments provided correspond to a file
-
configure
(arguments=None, config=None)¶ Merge command line arguments, config files, and default configs
Params arguments: Arguments produced by Cli.parse_args Params config: configuration dict to merge and validate
-
configure_args
(arguments)¶ Create configuration has from command line arguments
Params arguments: arguments produced by Cli.parse_args()
-
get_env_default
(variable, default)¶ Fetch environment variables, returning a default if not found
-
load_config
(path)¶ Load configuration from yaml file
Parameters: path (string) – path to configuration file
-
Exceptions¶
-
exception
margaritashotgun.exceptions.
AuthenticationMethodMissingError
¶ Raised when no ssh authentication methods are specified
-
__init__
()¶
-
__module__
= 'margaritashotgun.exceptions'¶
-
-
exception
margaritashotgun.exceptions.
AuthenticationMissingUsernameError
¶ Raised when authentication method is configured without a username
-
__init__
()¶
-
__module__
= 'margaritashotgun.exceptions'¶
-
-
exception
margaritashotgun.exceptions.
InvalidConfigurationError
(key, value, reason='unsupported configuration')¶ Raised when an unsupported configuration option is supplied
-
__init__
(key, value, reason='unsupported configuration')¶
-
__module__
= 'margaritashotgun.exceptions'¶
-
-
exception
margaritashotgun.exceptions.
KernelModuleNotFoundError
(kernel_version, repo_url)¶ Raised when no kernel module is provided and a suitable module cannot be found
-
__init__
(kernel_version, repo_url)¶
-
__module__
= 'margaritashotgun.exceptions'¶
-
-
exception
margaritashotgun.exceptions.
KernelModuleNotProvidedError
(kernel_version)¶ Raised when no kernel module is provided and repository is disabled
-
__init__
(kernel_version)¶
-
__module__
= 'margaritashotgun.exceptions'¶
-
-
exception
margaritashotgun.exceptions.
LimeRetriesExceededError
(retries)¶ Raised when max number of retries are exceeded waiting for LiME to load.
-
__init__
(retries)¶
-
__module__
= 'margaritashotgun.exceptions'¶
-
-
exception
margaritashotgun.exceptions.
MargaritaShotgunError
¶ Base Error Class
-
__module__
= 'margaritashotgun.exceptions'¶
-
__weakref__
¶ list of weak references to the object (if defined)
-
-
exception
margaritashotgun.exceptions.
MemoryCaptureAttributeMissingError
(attribute)¶ Raised when memory capture is missing a required attribute
-
__init__
(attribute)¶
-
__module__
= 'margaritashotgun.exceptions'¶
-
-
exception
margaritashotgun.exceptions.
MemoryCaptureOutputMissingError
(remote_host)¶ Raised when no output is configured when capturing memory
-
__init__
(remote_host)¶
-
__module__
= 'margaritashotgun.exceptions'¶
-
Logging¶
-
class
margaritashotgun.logger.
Logger
(*args, **kwargs)¶ -
__init__
(*args, **kwargs)¶
-
__module__
= 'margaritashotgun.logger'¶
-
-
margaritashotgun.logger.
cleanup
(log_file)¶
-
margaritashotgun.logger.
get_times
()¶
-
margaritashotgun.logger.
listener
(queue, name, log_file, desc)¶
Memory¶
-
class
margaritashotgun.memory.
Memory
(remote_addr, mem_size, progressbar=False, recv_size=1048576, sock_timeout=1)¶ -
__init__
(remote_addr, mem_size, progressbar=False, recv_size=1048576, sock_timeout=1)¶ Parameters:
-
__module__
= 'margaritashotgun.memory'¶
-
capture
(tunnel_addr, tunnel_port, filename=None, bucket=None, destination=None)¶ Captures memory based on the provided OutputDestination
Parameters: - tunnel_port (int) – ssh tunnel hostname or ip
- tunnel_port – ssh tunnel port
- filename (str) – memory dump output filename
- bucket (str) – output s3 bucket
- destination (
margaritashotgun.memory.OutputDestinations
) – OutputDestinations member
-
cleanup
()¶ Release resources used during memory capture
-
max_size
(mem_size, padding_percentage)¶ Calculates the excpected size in bytes of the memory capture
Parameters:
-
to_file
(filename, tunnel_addr, tunnel_port)¶ Writes memory dump to a local file
Parameters:
-
to_s3
(bucket, filename, tunnel_addr, tunnel_port)¶ Writes memory dump to s3 bucket
Parameters:
-
update_progress
(complete=False)¶ Logs capture progress
Params complete: toggle to finish ncurses progress bar
-
Remote Host¶
-
class
margaritashotgun.remote_host.
Host
¶ -
__init__
()¶
-
__module__
= 'margaritashotgun.remote_host'¶
-
capture_memory
(destination, filename, bucket, progressbar)¶
-
check_for_lime
(pattern, listen_port)¶ Check to see if LiME has loaded on the remote system
Parameters:
-
cleanup
()¶ Release resources used by supporting classes
-
connect
(username, password, key, address, port)¶ Connect ssh tunnel and shell executor to remote host
Parameters:
-
kernel_version
()¶ Returns the kernel kernel version of the remote host
-
load_lime
(remote_path, listen_port, dump_format='lime')¶ Load LiME kernel module from remote filesystem
Parameters:
-
log_async_result
(future)¶
-
mem_size
()¶ Returns the memory size in bytes of the remote host
-
start_tunnel
(local_port, remote_address, remote_port)¶ Start ssh forward tunnel
Parameters:
-
unload_lime
()¶ Remove LiME kernel module from remote host
-
upload_module
(local_path=None, remote_path='/tmp/lime.ko')¶ Upload LiME kernel module to remote host
Parameters:
-
wait_for_lime
(listen_port, listen_address='0.0.0.0', max_tries=20, wait=1)¶ Wait for lime to load unless max_retries is exceeded
Parameters:
-
-
margaritashotgun.remote_host.
process
(conf)¶
Remote Shell¶
-
class
margaritashotgun.remote_shell.
Commands
¶ -
__format__
(format_spec)¶
-
__module__
= 'margaritashotgun.remote_shell'¶
-
static
__new__
(value)¶
-
__reduce_ex__
(proto)¶
-
__repr__
()¶
-
__str__
()¶
-
kernel_version
= <Commands.kernel_version: 'uname -r'>¶
-
lime_check
= <Commands.lime_check: 'netstat -lnt | grep {0}'>¶
-
lime_pattern
= <Commands.lime_pattern: '{0}:{1}'>¶
-
load_lime
= <Commands.load_lime: 'sudo insmod {0} "path=tcp:{1}" format={2}'>¶
-
mem_size
= <Commands.mem_size: "cat /proc/meminfo | grep MemTotal | awk '{ print $2 }'">¶
-
unload_lime
= <Commands.unload_lime: 'sudo pkill insmod; sudo rmmod lime'>¶
-
-
class
margaritashotgun.remote_shell.
RemoteShell
(max_async_threads=2)¶ -
-
__module__
= 'margaritashotgun.remote_shell'¶
-
cleanup
()¶ Release resources used during shell execution
-
connect
(auth, address, port)¶ Creates an ssh session to a remote host
Parameters: - auth (
margaritashotgun.auth.AuthMethods
) – Authentication object - address (str) – remote server address
- port (int) – remote server port
- auth (
-
connect_with_key
(username, key, address, port)¶ Create an ssh session to a remote host with a username and rsa key
Parameters:
-
connect_with_password
(username, password, address, port)¶ Create an ssh session to a remote host with a username and password
Parameters:
-
decode
(stream, encoding='utf-8')¶ Convert paramiko stream into a string
Parameters: - stream – stream to convert
- encoding (str) – stream encoding
-
execute
(command)¶ Executes command on remote hosts
Parameters: command (str) – command to be run on remote host
-
Repository¶
SSH Tunnel¶
-
class
margaritashotgun.ssh_tunnel.
Forward
(local_port, remote_address, remote_port, transport)¶ -
__init__
(local_port, remote_address, remote_port, transport)¶ type: local_port: int param: local_port: local tunnel endpoint ip binding type: remote_address: str param: remote_address: Remote tunnel endpoing ip binding type: remote_port: int param: remote_port: Remote tunnel endpoint port binding type: transport:
paramiko.Transport
param: transport: Paramiko ssh transport
-
__module__
= 'margaritashotgun.ssh_tunnel'¶
-
forward_tunnel
(local_port, remote_address, remote_port, transport)¶
-
run
()¶
-
stop
()¶
-
-
class
margaritashotgun.ssh_tunnel.
ForwardServer
(server_address, RequestHandlerClass, bind_and_activate=True)¶ -
__module__
= 'margaritashotgun.ssh_tunnel'¶
-
allow_reuse_address
= True¶
-
daemon_threads
= True¶
-
-
class
margaritashotgun.ssh_tunnel.
Handler
(request, client_address, server)¶ -
__module__
= 'margaritashotgun.ssh_tunnel'¶
-
handle
()¶
-
-
class
margaritashotgun.ssh_tunnel.
SSHTunnel
¶ -
__init__
()¶
-
__module__
= 'margaritashotgun.ssh_tunnel'¶
-
cleanup
()¶ Cleanup resources used during execution
-
connect
(auth, address, port, hostkey=None)¶ Connect paramico transport
Parameters:
-
connect_with_key
(username, key, hostkey=None)¶ Connect paramico transport with public key authentication
Parameters: - username (str) – ssh authentication username
- key (
paramiko.key.RSAKey
) – ssh authentication private key - hostkey (
paramiko.key.HostKey
) – remote host ssh server key
-
connect_with_password
(username, password, hostkey=None)¶ Connect paramico transport with password authentication
Parameters:
-
start
(local_port, remote_address, remote_port)¶ Start ssh tunnel
type: local_port: int param: local_port: local tunnel endpoint ip binding type: remote_address: str param: remote_address: Remote tunnel endpoing ip binding type: remote_port: int param: remote_port: Remote tunnel endpoint port binding
-
Workers¶
-
class
margaritashotgun.workers.
Workers
(conf, workers, name, library=True)¶ -
__init__
(conf, workers, name, library=True)¶
-
__module__
= 'margaritashotgun.workers'¶
-
cleanup
(terminate=False)¶
-
count
(workers, cpu_count, host_count)¶
-
cpu_count
= None¶
-
hosts
= None¶
-
progress_bar
= True¶
-
spawn
(desc, timeout=1800)¶
-
worker_count
= None¶
-
Architecture¶
An Overview of margaritashotugn’s architecture Coming Soon!
Development¶
Tests¶
The test suite is written with pytest and can be run with py.test --cov=margaritashotgun
About¶
Margaritashotgun is a part of the Threat Response project.