Merlin v0.7.0 Release & Roll-up

Russel Van Tuyl
Posts By SpecterOps Team Members
8 min readApr 12, 2019

--

It has been a while since the last blog post on Merlin, but that doesn’t mean there hasn’t been plenty going on with the application. This post will go through some of new features in this release and also go through some of the features from previous releases that haven’t be covered.

Jump to a specific section

Cross-Platform Native Commands

Community member Alex Flores (@audibleblink) has been hard at work adding in native command functionality. Merlin now contains a cross-platform go implementation of the ls, pwd, and cd commands. The advantage is that the commands all execute natively within the Merlin agent and do not require you to leverage an Operating System shell to execute them. This should cut down on command line logging. For instance, ls is an actual binary program located at /bin/ls on a Linux host. In the past you would need to execute the /bin/ls binary like:
Merlin[agent][2de3c393–38ea-40d7–9a8d-2eb885d564cc]» shell ls -l

With the new native ls command, the agent will leverage native go-code to list the contents of the current directory without calling the /bin/ls binary directly, like so:
Merlin[agent][2de3c393–38ea-40d7–9a8d-2eb885d564cc]» ls

The pwd, cd, and ls commands in Action

Agent Kill Date

Ever wanted to make sure your Merlin Agent quit functioning after a per-determined date? Now it can thanks to the killdate field added to the agent by Dan Borges (@ahhh). Ideally the Killdate is hard-coded into the agent during compile time. This ensures that no matter when the binary is executed, it will not check-in after the killdate.

Alternatively, the killdate can be set from the Agent menu. However, the date will NOT persist and will only be set while the current instance of the agent is running. Once the live agent dies, the killdate will go away and the agent will return to its default value of 0. Killdate is an epoch timestamp that can viewed or set from the agent menu.

Agent Killdate

Status Command & UTC Timestamp

The new status command and Coordinated Universal Time (UTC) timestamp features were implemented to increase quality of life. Typing info every time and looking through returned table of information every time just to see if the agent is alive, dead, or delayed got old. The status now succinctly prints JUST the agent’s status to the screen. For a recap, the delay status is issued when the wait time has exceeded but not the max retries. This commonly happens due to skew, which is randomly calculated by the agent is unknown to the server.

When it comes to documenting activities and correlating events, time zones can really cause some problems. In order to remove the complications, all activities should be recorded in UTC. Merlin now displays a UTC time stamp for every job creation, job results, and all log file entries.

Agent Status & UTC Timestamp

Compiling with Hard-coded URL

By default, a Merlin Agent binary will check-in to 127.0.0.1 . This value can be changed with the -url command line parameter at run time or it can be hard-coded straight into cmd/merlinagent/main.go before compiling. New work by Alex Flores (@audibleblink) allows for the target URL to be specified at compile time when using Make instead of modifying the source code. An example is: make agent-linux URL=https://mymalwaredomain.com

Make with URL Parameter

Dockerfile

This release adds in a Dockerfile (thanks Alex) that will be used to automatically build a container for each Merlin release at https://hub.docker.com/r/ne0nd0g/merlin. The Merlin container has also been implemented into Redcloud by Khast3x.

Redcloud is a powerful and user-friendly toolbox for deploying a fully-featured Red Team Infrastructure using Docker.

Extended Modules

Initially Merlin modules were designed to be basic, easy to modify without re-compiling, and portable. This resulted in using JSON files to describe a module. The standard module type was limited to executing big one-line commands that chained everything together based on the values in the module’s options. This limitation prevented the ability to execute any go code on the server prior to sending a job to the Merlin Agent. Ideally, as much processing and validating will happen server side to reduce the lines of code used in the agent. Because of this, a new extended module type was introduced.

Extended modules will be located in the modules package, self-contained in a new directory. For instance, the minidump go module is located at pkg/modules/minidump/minidump.go . The module must have an exported Parse(options map[string]string) ([]string, error)function. This function will be called immediately after calling run from the module menu and is used to parse all of a module’s configurable options that are set in the data/modules/windows/x64/go/credentials/minidump.json file. The function will return a job command that is a pre-positioned string slice.

The module may contain other exported functions that can be used by other modules. For example the srdi.go module leverages the GetJob function from the shellcode.go module to get a job structure for executing shellcode.

Minidump

Merlin now contains a minidump extended module, courtesy of Cameron Stokes (@C__Sto) in Pull Request 51, that will execute Windows’s MiniDumpWriteDump API call from Go on any process. Executing Mimikatz on a host might not be a path you want to take as a measure to avoid unnecessarily risking detection by EDR. The MiniDumpWriteDump API call is commonly used to dump the memory from LSASS to a file and then extract credentials from the file on an attacker controlled host to evade detection.

By default, the module will dump the memory of LSASS to a file, upload the dump file to the Merlin server, and then delete the dump file from the host where the agent is running. This module can be used to dump the memory of any interesting process, not just LSASS, by providing the target process name or by the target Process ID (PID).

Minidump Module
Mimikatz

Auto Generate X.509 Certificate

Past Merlin releases were distributed with a self-signed X.509 certificate to facilitate ease of use so that Merlin could be used right away. The down side is that the certificate information is public information and can be leveraged by anyone to do things like finger print Merlin servers using the default configuration. I was OK with this because, by default, Merlin only listens on the loopback adapter and ideally operators using Merlin for campaigns would generate a new, valid, certificate.

Cameron Stokes (@C__Sto)submitted a Pull Request that takes the best of both worlds by generating a unique self-signed certificate every time Merlin server is executed. This allows Merlin to be used straight out of the box and prevents static indicators from the publicly distributed X.509 certificate. Merlin server will not generate a self-signed certificate if one is specified with the -x509cert and -x509key command line flags at run time.

Certificate Generation

Shellcode Execution

One of the more notable new features added to Merlin is the ability to execute shellcode, on Windows hosts, from Go using three different methods. Shellcode can be executed in the Merlin process using the self method or in a remote process using the remote or RtlCreateUserThread methods.

The remote method creates a thread in another process using the CreateRemoteThreadEx Windows API call. The rtlcreateuserthread method creates a thread in another process using the undocumented RtlCreateUserThread Windows API call.

Shellcode can be executed straight from the agent menu using the execute-shellcode command or by using the windows/x64/go/exec/shellcodeInjection extended module. Both methods will accept shellcode in one of the following formats:

  • Hex (i.e. 5051525356)
  • 0x50, 0x51, 0x52, 0x53, 0x56 with or without spaces and commas
  • \x50\x51\x52\x53\x56
  • Base64 encoded version of the above formats
  • A file containing any of the above formats or just a raw byte file

Documentation for executing each method, with examples, can be found on the Merlin Wiki.

Shellcode Reflective DLL Injection (sRDI)

Reflective DLL injection is used to load a DLL into a process without having to place it on the host’s file system. The initial work was completed by Stephen Fewer in his Reflective DLL Injection paper / GitHub project, and later updated by Dan Staples. This technique was further advanced by Nick Landers in his sRDI — Shellcode Reflective DLL Injection blog post where he implements a method to reflectively load any arbitrary DLL as shellcode.

Reflective DLL injection will execute the DLL_PROCESS_ATTACH function when the DLL is loaded. The work done by Dan Staples allows an exported function to be called after the DLL is loaded. Previous versions of the merlin.dll did not include either the DLL_PROCESS_ATTACH function or an exported function in the merlin.c file that could be called. This release includes an updated merlin.dll with Magic and Merlin as exported functions. The DLL_PROCESS_ATTACH function does not contain any code. However, the function was left in place so that an operator could update it to call one of the exported functions if they are using a technique that depends on calling the DLL_PROCESS_ATTACH function or does not facilitate calling another function after loading the DLL.

The merlin.dll can be loaded a number of ways to include using rundll32.exe or regsvr32 with examples documented on the Merlin Wiki.

Merlin now contains a sRDI extended module based on the work by Leo Loobeek that implemented sRDI in Go. This module can be used to reflectively execute any DLL in a process using the shellcode execution methods self , remote , or RtlCreateUserThread. One of the primary reasons to use this module is to inject merlin.dll into another process to spawn a new agent. asciinema

Merlin sRDI Module Video

Wrap Up

Merlin version 0.7.0 is packed with a bunch of new features thanks to community member support. This release comes with new minidump, shellcode execution, and sRDI modules. Several native commands were added to the agent menu along with new status and killdate commands. This release all includes a Dockerfile and UTC timestamps along with auto generated X.509 certificates.

Downloaded the latest release, complete with compiled binaries, from the Merlin GitHub page.

I would enjoy hearing from you if you have questions, issues, or just want to talk about Merlin and its capabilities. You can leave a comment here, join the #merlin channel on the BloodHoundGang slack or hit me up on Twitter.

Happy Hacking

--

--