Skip to main content
Modules are used to perform a set of pre-defined actions or execute a program on an agent. The modules are described using JavaScript Object Notation (JSON). Modules will be stored in platform/arch/language/type directories. Every module must have the base object and may have additional objects. Examples of the module structures can be found in the data/modules/templates directory. All keys used when describing a module will be lowercase (i.e. name and NOT Name).

Base

The base module is required and is the lowest level of describing a module and its function.

Full Example:

Type

Modules can be either standard or extended. A STANDARD module does not leverage any Go packages or functions from the pkg/modules directory. Standard modules are best used to run a single command, or a series of commands, that leverage functionality and programs on the host where the agent is running. The data/modules/linux/x64/bash/exec/bash.json module is a standard module that takes a Command argument that is subsequently run in bash -c {{Command}}. This could be useful to abstract out command line arguments with easy to set options or to run a single command across all agents using set Agent all while in the module’s prompt. An EXTENDED module DOES leverage code from an associated package pkg/modules. The sRDI module at data/modules/windows/x64/go/exec/sRDI.json is an example of an extended module that uses exported functions from the srdi package at pkg/modules/srdi/srdi.go. This extended module reads in a Windows DLL and returns shellcode that will be executed on the agent. The extended function’s code must be located in pkg/modules/<function>. The extended function’s code must expose a Parse() function that returns an array of strings that contain commands for the agent to interpret. Extended function must be programmed into the getExtendedCommand() function in modules.go and point to the module’s exported Parse() function.

Remote vs Local

When the module leverages a script, it can be accessed with either the local or remote values of the base module. The local specifies the file path on the server where the script can be found. Merlin DOES NOT ship with scripts. However, they should be copied to the data/source directory using something like Git. For example, you move into the data/source direct and do a git clone https://github.com/PowerShellMafia/PowerSploit.git. When the local source is used, the script is uploaded to the target from the server. When the remote source is used, the script is downloaded from that location to the target.

Options

The options uses a special data type that requires five parts.

Name

This is the name of the option that can be set by a user. This value is used as a variable in the commands section of the module file. The name is case sensitive (Name != name != NAME). An example option object looks like:
An example of setting the count option is:
Using just the option’s name within double curly braces will return both the flag and value. For example {{count}} would be parsed and replaced with -c 3. The flag and value properties can be accessed individually if needed with {{count.Flag}} and {{count.Value}}.

Value

This is the value that the options has been set to. The value can be directly accessed in the commands section by using .Value after option’s name. This is ideal for positional arguments that do not have a flag or specify an application executable file name. An example option object that uses the value property is:
For example {{host.Value}} would be parsed and replaced with just the value of the host option (google.com). If an option’s value is empty, it will not be ignored and not parsed.

Flag

The flag property is used to specify what the notation is for a specific argument when executing a command. The name property can be used in conjunction with the flag property when the flag is not descriptive enough to make sense. A command line flag could start with a variety of options like -, --, or /. An example option object that uses a flag property is:
Some applications use a flag with no value after it. A common example of this -h to view an application’s help information. A flag, WITHOUT its value can be accessed in the commands section with .Flag. For example {{help.Flag}} would be parsed and replaced with just -h. If you want to only use the flag, and not its value, then you must set its value to true. Using just the option’s name within double curly braces will return both the flag and value. For example {{help}} would be parsed and replaced with -h true.

Commands

The commands section of the module is used to provide the commands that are going to be executed on the host. The array should consist of every command in its own list item. You do not need to account for spaces. This is automatically done when the command is executed on the host. You specify the location of an option by using double curly brace and the option’s name. This will be parsed and replaced with both the value and flag values from the option’s list entry. The option’s flag and value can be accessed individually. An example command section looks like:
This would get parsed as /bin/ping -c 3 google.com If an option’s value is not set, it will be ignored. An example of accessing only an option’s flag while ignoring everything else is:
This would get parsed as /bin/ping -h

PowerShell

The powershell module is used to provide additional configuration options that pertain to PowerShell commands. Support for this module type is currently lacking. At this time is being used as placeholder for future development.