Hello, World! Merlin is a modern C2 framework with many features like support for the HTTP/2 protocol, built-in JWT authentication, domain fronting, and much more. Merlin is written in Go, which means we can easily deploy Merlin servers and agents on most things with a CPU. Merlin comes with a collection of modules that perform common post-exploitation tasks, like persistence and credential gathering. In this blog, I'll demonstrate how easy it is to automate your post-exploit operations by writing your own custom modules. I recommend checking out my recent blog on the basics of Merlin here, just to get your feet wet with the deployment of Merlin servers and agents. With that out of the way, I'll start by demonstrating the execution of one of the modules included with Merlin.

Executing Merlin Modules

Before we write our own Merlin modules, I'll first demonstrate the execution of a default module already included with the Merlin server. To use a module, type use module [module_path] like this (you can auto-complete module names with the TAB key, thank goodness):

None

In this example, we've loaded the linux/x64/bash/privesc/LinEnum module. To show information about the module, use the command show info , and to show only the configurable options for the module, use the command show options:

None

To set an option, use the command set [option] [value] . For example, to set the Agent of this module, use the command set Agent 2aeceb00-c46b-4abc-9483-c68043a9b342 :

None

And finally, to run the module, simply use the command run :

None

Now that we know how to use modules, let's create our own.

Writing Our Custom Merlin Module

All modules are stored under the data/modules/ directory. Modules for different operating systems are divided up into separate folders. Each folder will then contain several a hierarchy of folders defining the architecture the module will run on, the language the module is written in, and finally, the type of module is — whether it's an enumeration module or a privilege escalation module, for example. The full path for a module should look like this:

platform/arch/language/type/module.json
Example: linxu/x64/bash/enumeration/interfaces.json
None

As you can see modules themselves are actually just JSON files. For demonstration purposes, I'll be creating a simple Linux module written in Bash that will list open ports on the victim machine.

So first, let's create a directory in the data/modules/linux/x64/bash/ folder and call it enumeration and then open up a file called localPorts.json:

None

In localPorts.json, enter the following information:

A lot of the stuff in the JSON file is self-explanatory, but here is a quick breakdown of the most important keys:

  • path — the path that we talked about earlier referring to the module itself from within the data/modules directory
  • options — the options that a user can specify when using the module. Options is a list containing JSON objects with the values name, value, required, flag, and description. Name is the name of the option, value is the default value for the option, required tells the user is the option must be specified or not, flag is the CLI flag that will be passed to the command you will be executing, and finally, description defines the purposes of the option.
  • commands — this is where you specify the command/script to execute on the victim machine and where you can substitute options value into the command using double-bracket notation {{}}. You can access an options flag and value using the .Flag and .Value properties of each option.

After saving the file, you can go back to the Merlin server to load and execute the module:

None

And that's all you need to know to create your own Merlin C2 modules. Happy Hacking!

EOF

If you enjoyed reading this article, please follow me on Medium, for more cybersecurity/tech-related articles, and on GitHub, for more cybersecurity programming projects. Thank you for your time!

References: