Skip to content

Commit

Permalink
Merge branch 'dev'. Release v0.9.0-beta
Browse files Browse the repository at this point in the history
  • Loading branch information
Ne0nd0g committed Sep 14, 2020
2 parents 2c1146f + 0ec00fc commit 506ebc4
Show file tree
Hide file tree
Showing 161 changed files with 31,301 additions and 1,518 deletions.
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
FROM golang:stretch
MAINTAINER @audibleblink

# Build the Docker image first
# > sudo docker build -t merlin .
Expand All @@ -11,11 +10,12 @@ MAINTAINER @audibleblink
# 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
RUN git clone https://github.com/Ne0nd0g/merlin

WORKDIR $GOPATH/src/github.com/Ne0nd0g/merlin
RUN go mod download
VOLUME ["data/temp"]
EXPOSE 443
CMD ["go", "run", "cmd/merlinserver/main.go", "-i", "0.0.0.0"]
45 changes: 24 additions & 21 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ HOST ?=
XHOST =-X main.host=$(HOST)
PROTO ?= h2
XPROTO =-X main.protocol=$(PROTO)
JA3 ?=
XJA3 =-X main.ja3=$(JA3)
LDFLAGS=-ldflags "-s -w ${XBUILD} ${XPROTO} ${XURL} ${XHOST} ${XPSK} ${XPROXY} -buildid="
WINAGENTLDFLAGS=-ldflags "-s -w ${XBUILD} ${XPROTO} ${XURL} ${XHOST} ${XPSK} ${XPROXY} -H=windowsgui -buildid="
# TODO Update when Go1.13 is released https://stackoverflow.com/questions/45279385/remove-file-paths-from-text-directives-in-go-binaries
Expand Down Expand Up @@ -117,56 +119,57 @@ agent-javascript:

# Make directory 'data' and then agents, db, log, x509; Copy src folder, README, and requirements
package-server-windows:
${PACKAGE} ${DIR}/${MSERVER}-${W}-v${VERSION}.7z ${F}
cd ${DIR};${PACKAGE} ${MSERVER}-${W}-v${VERSION}.7z ${MSERVER}-${W}.exe
${PACKAGE} ${DIR}/${MSERVER}-${W}.7z ${F}
cd ${DIR};${PACKAGE} ${MSERVER}-${W}.7z ${MSERVER}-${W}.exe

package-server-linux:
${PACKAGE} ${DIR}/${MSERVER}-${L}-v${VERSION}.7z ${F}
cd ${DIR};${PACKAGE} ${MSERVER}-${L}-v${VERSION}.7z ${MSERVER}-${L}
${PACKAGE} ${DIR}/${MSERVER}-${L}.7z ${F}
cd ${DIR};${PACKAGE} ${MSERVER}-${L}.7z ${MSERVER}-${L}

package-server-darwin:
${PACKAGE} ${DIR}/${MSERVER}-${D}-v${VERSION}.7z ${F}
cd ${DIR};${PACKAGE} ${MSERVER}-${D}-v${VERSION}.7z ${MSERVER}-${D}
${PACKAGE} ${DIR}/${MSERVER}-${D}.7z ${F}
cd ${DIR};${PACKAGE} ${MSERVER}-${D}.7z ${MSERVER}-${D}

package-agent-windows:
${PACKAGE} ${DIR}/${MAGENT}-${W}-v${VERSION}.7z ${F2}
cd ${DIR};${PACKAGE} ${MAGENT}-${W}-v${VERSION}.7z ${MAGENT}-${W}.exe
${PACKAGE} ${DIR}/${MAGENT}-${W}.7z ${F2}
cd ${DIR};${PACKAGE} ${MAGENT}-${W}.7z ${MAGENT}-${W}.exe
mkdir -p ${BIN}windows
cp ${DIR}/${MAGENT}-${W}.exe ${BIN}windows/

package-agent-linux:
${PACKAGE} ${DIR}/${MAGENT}-${L}-v${VERSION}.7z ${F2}
cd ${DIR};${PACKAGE} ${MAGENT}-${L}-v${VERSION}.7z ${MAGENT}-${L}
${PACKAGE} ${DIR}/${MAGENT}-${L}.7z ${F2}
cd ${DIR};${PACKAGE} ${MAGENT}-${L}.7z ${MAGENT}-${L}
mkdir -p ${BIN}linux
cp ${DIR}/${MAGENT}-${L} ${BIN}linux/

package-agent-darwin:
${PACKAGE} ${DIR}/${MAGENT}-${D}-v${VERSION}.7z ${F2}
cd ${DIR};${PACKAGE} ${MAGENT}-${D}-v${VERSION}.7z ${MAGENT}-${D}
${PACKAGE} ${DIR}/${MAGENT}-${D}.7z ${F2}
cd ${DIR};${PACKAGE} ${MAGENT}-${D}.7z ${MAGENT}-${D}
mkdir -p ${BIN}darwin/
cp ${DIR}/${MAGENT}-${D} ${BIN}darwin/

package-agent-dll:
${PACKAGE} ${DIR}/${MAGENT}-DLL-v${VERSION}.7z ${F2}
cd ${DIR};${PACKAGE} ${MAGENT}-DLL-v${VERSION}.7z merlin.dll
${PACKAGE} ${DIR}/${MAGENT}-DLL.7z ${F2}
cd ${DIR};${PACKAGE} ${MAGENT}-DLL.7z merlin.dll
cp ${DIR}/merlin.dll ${BIN}dll

package-prism-windows:
${PACKAGE} ${DIR}/PRISM-${W}-v${VERSION}.7z ${F2}
cd ${DIR};${PACKAGE} PRISM-${W}-v${VERSION}.7z PRISM-${W}.exe
${PACKAGE} ${DIR}/PRISM-${W}.7z ${F2}
cd ${DIR};${PACKAGE} PRISM-${W}.7z PRISM-${W}.exe
cp ${DIR}/PRISM-${W}.exe ${BIN}windows/

package-prism-linux:
${PACKAGE} ${DIR}/PRISM-${L}-v${VERSION}.7z ${F2}
cd ${DIR};${PACKAGE} PRISM-${L}-v${VERSION}.7z PRISM-${L}
${PACKAGE} ${DIR}/PRISM-${L}.7z ${F2}
cd ${DIR};${PACKAGE} PRISM-${L}.7z PRISM-${L}
cp ${DIR}/PRISM-${L} ${BIN}linux/

package-prism-darwin:
${PACKAGE} ${DIR}/PRISM-${D}-v${VERSION}.7z ${F2}
cd ${DIR};${PACKAGE} PRISM-${D}-v${VERSION}.7z PRISM-${D}
${PACKAGE} ${DIR}/PRISM-${D}.7z ${F2}
cd ${DIR};${PACKAGE} PRISM-${D}.7z PRISM-${D}
cp ${DIR}/PRISM-${D} ${BIN}darwin/

package-all: package-agent-windows package-agent-dll package-agent-linux package-agent-darwin package-prism-windows package-server-windows package-server-linux package-server-darwin
# Package agents and PRISM first so that they can be included in the Server distro
package-all: package-agent-windows package-agent-dll package-agent-linux package-agent-darwin package-prism-windows package-prism-linux package-prism-darwin package-server-linux package-server-windows package-server-darwin

clean:
rm -rf ${DIR}*
Expand Down
6 changes: 4 additions & 2 deletions cmd/merlinagent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,18 @@ var build = "nonRelease"
var psk = "merlin"
var proxy = ""
var host = ""
var ja3 = ""

func main() {
verbose := flag.Bool("v", false, "Enable verbose output")
version := flag.Bool("version", false, "Print the agent version and exit")
debug := flag.Bool("debug", false, "Enable debug output")
flag.StringVar(&url, "url", url, "Full URL for agent to connect to")
flag.StringVar(&psk, "psk", psk, "Pre-Shared Key used to encrypt initial communications")
flag.StringVar(&protocol, "proto", protocol, "Protocol for the agent to connect with [https (HTTP/1.1), h2 (HTTP/2), hq (QUIC or HTTP/3.0)]")
flag.StringVar(&protocol, "proto", protocol, "Protocol for the agent to connect with [https (HTTP/1.1), http (HTTP/1.1 Clear-Text), h2 (HTTP/2), h2c (HTTP/2 Clear-Text), http3 (QUIC or HTTP/3.0)]")
flag.StringVar(&proxy, "proxy", proxy, "Hardcoded proxy to use for http/1.1 traffic only that will override host configuration")
flag.StringVar(&host, "host", host, "HTTP Host header")
flag.StringVar(&ja3, "ja3", ja3, "JA3 signature string (not the MD5 hash). Overrides -proto flag")
sleep := flag.Duration("sleep", 30000*time.Millisecond, "Time for agent to sleep")
flag.Usage = usage
flag.Parse()
Expand All @@ -60,7 +62,7 @@ func main() {
}

// Setup and run agent
a, err := agent.New(protocol, url, host, psk, proxy, *verbose, *debug)
a, err := agent.New(protocol, url, host, psk, proxy, ja3, *verbose, *debug)
if err != nil {
if *verbose {
color.Red(err.Error())
Expand Down
3 changes: 2 additions & 1 deletion cmd/merlinagentdll/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,13 @@ var url = "https://127.0.0.1:443"
var psk = "merlin"
var proxy = ""
var host = ""
var ja3 = ""

func main() {}

// run is a private function called by exported functions to instantiate/execute the Agent
func run(URL string) {
a, err := agent.New("h2", URL, host, psk, proxy, false, false)
a, err := agent.New("h2", URL, host, psk, proxy, ja3, false, false)
if err != nil {
os.Exit(1)
}
Expand Down
37 changes: 3 additions & 34 deletions cmd/merlinserver/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ package main
import (
// Standard
"flag"
"fmt"
"os"
"path/filepath"

// 3rd Party
"github.com/fatih/color"
Expand All @@ -31,34 +29,23 @@ import (
"github.com/Ne0nd0g/merlin/pkg"
"github.com/Ne0nd0g/merlin/pkg/banner"
"github.com/Ne0nd0g/merlin/pkg/cli"
"github.com/Ne0nd0g/merlin/pkg/core"
"github.com/Ne0nd0g/merlin/pkg/logging"
"github.com/Ne0nd0g/merlin/pkg/servers/http2"
)

// Global Variables
var build = "nonRelease"
var psk = "merlin"

func main() {
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")
port := flag.Int("p", 443, "Merlin Server Port")
ip := flag.String("i", "127.0.0.1", "The IP address of the interface to bind to")
proto := flag.String("proto", "h2", "Protocol for the agent to connect with [h2, hq]")
crt := flag.String("x509cert", filepath.Join(string(core.CurrentDir), "data", "x509", "server.crt"),
"The x509 certificate for the HTTPS listener")
key := flag.String("x509key", filepath.Join(string(core.CurrentDir), "data", "x509", "server.key"),
"The x509 certificate key for the HTTPS listener")
flag.StringVar(&psk, "psk", psk, "Pre-Shared Key used to encrypt initial communications")
flag.Usage = func() {
color.Blue("#################################################")
color.Blue("#\t\tMERLIN SERVER\t\t\t#")
color.Blue("#################################################")
color.Blue("Version: " + merlin.Version)
color.Blue("Build: " + build)
color.Yellow("Merlin Server does not take any command line arguments")
color.Yellow("Visit the Merlin wiki for additional information: https://github.com/Ne0nd0g/Merlin/wiki")
flag.PrintDefaults()
os.Exit(0)
}
Expand All @@ -69,23 +56,5 @@ func main() {
color.Blue("\t\t Build: %s", build)

// Start Merlin Command Line Interface
go cli.Shell()

// Start Merlin Server to listen for agents
server, err := http2.New(*ip, *port, *proto, *key, *crt, psk)
if err != nil {
color.Red(fmt.Sprintf("[!]There was an error creating a new server instance:\r\n%s", err.Error()))
os.Exit(1)
} else {
err := server.Run()
if err != nil {
color.Red(fmt.Sprintf("[!]There was an error starting the server:\r\n%s", err.Error()))
os.Exit(1)
}
}
cli.Shell()
}

// TODO add CSRF tokens
// TODO check if agentLog exists even outside of InitialCheckIn
// TODO readline for file paths to use with upload
// TODO handle file names containing a space for upload/download
23 changes: 19 additions & 4 deletions cmd/prism/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"encoding/json"
"flag"
"fmt"
"io"
"net/http"
"os"
"strings"
Expand Down Expand Up @@ -55,6 +56,14 @@ var verbose = false
var debug = false
var merlinJWT string
var host string
var ja3 = ""

type merlinClient interface {
Do(req *http.Request) (*http.Response, error)
Get(url string) (resp *http.Response, err error)
Head(url string) (resp *http.Response, err error)
Post(url, contentType string, body io.Reader) (resp *http.Response, err error)
}

func main() {
flag.BoolVar(&verbose, "verbose", false, "Enable verbose output")
Expand All @@ -64,13 +73,14 @@ func main() {
protocol := flag.String("proto", "h2", "Protocol for the agent to connect with [https (HTTP/1.1), h2 (HTTP/2), hq (QUIC or HTTP/3.0)]")
flag.StringVar(&proxy, "proxy", proxy, "Hardcoded proxy to use for http/1.1 traffic only that will override host configuration")
flag.StringVar(&host, "host", host, "HTTP Host header")
flag.StringVar(&ja3, "ja3", ja3, "JA3 signature string (not the MD5 hash). Overrides -proto flag")
flag.Usage = usage
flag.Parse()

var err error

// Setup and run agent
a, errNew := agent.New(*protocol, url, host, psk, proxy, verbose, debug)
a, errNew := agent.New(*protocol, url, host, psk, ja3, proxy, verbose, debug)
if errNew != nil {
message("warn", errNew.Error())
os.Exit(1)
Expand Down Expand Up @@ -134,7 +144,9 @@ func opaqueRegister(a agent.Agent) error {
Padding: core.RandStringBytesMaskImprSrc(a.PaddingMax),
}

regInitResp, errRegInitResp := sendMessage("POST", regInitBase, a.Client)
var client merlinClient = *a.Client

regInitResp, errRegInitResp := sendMessage("POST", regInitBase, client)

if errRegInitResp != nil {
return fmt.Errorf("there was an error sending the agent OPAQUE user registration initialization message:\r\n%s", errRegInitResp.Error())
Expand Down Expand Up @@ -189,7 +201,10 @@ func sendPre8Message(a agent.Agent) error {

req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.85 Safari/537.36 ")
req.Header.Set("Content-Type", "application/json; charset=utf-8")
resp, err := a.Client.Do(req)

var client merlinClient = *a.Client

resp, err := client.Do(req)

if err != nil {
return fmt.Errorf("there was an error sending the request:\r\n%s", err.Error())
Expand Down Expand Up @@ -218,7 +233,7 @@ func sendPre8Message(a agent.Agent) error {

// sendMessage is a generic function to receive a messages.Base struct, encode it, encrypt it, and send it to the server
// The response message will be decrypted, decoded, and return a messages.Base struct.
func sendMessage(method string, m messages.Base, client *http.Client) (messages.Base, error) {
func sendMessage(method string, m messages.Base, client merlinClient) (messages.Base, error) {
if debug {
message("debug", "Entering into agent.sendMessage")
}
Expand Down
4 changes: 3 additions & 1 deletion data/agents/README.MD
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
# Merlin Agent Data Directory
# Merlin Agent Data Directory

This directory contains a folder for each agent, by its UUID, and contains the Merlin Agent logs and files downloaded through the agent.
62 changes: 2 additions & 60 deletions data/bin/README.MD
Original file line number Diff line number Diff line change
@@ -1,62 +1,4 @@
# Merlin Binaries

This directory contains compiled binaries for different operating
systems and architectures. A list of golang supported operating
systems and architectures can be found here:
https://golang.org/doc/install/source#environment

This directory is here because the `bin` in the root of the Merlin's
folders is used and created by golang for subsequent binaries.

The agent & server can be cross-compiled using:
`GOOS=darwin GOARCH=amd64 go build -o bin\merlinserver.dmg merlinserver.go`


The gomobile library can be used to compile for Android and iOS:
https://godoc.org/golang.org/x/mobile/cmd/gomobile


$GOOS | $GOARCH
--- | ---
android | arm
darwin | 386
darwin | amd64
darwin | arm
darwin | arm64
dragonfly | amd64
freebsd | 386
freebsd | amd64
freebsd | arm
linux | 386
linux | amd64
linux | arm
linux | arm64
linux | ppc64
linux | ppc64le
linux | mips
linux | mipsle
linux | mips64
linux | mips64le
netbsd | 386
netbsd | amd64
netbsd | arm
openbsd | 386
openbsd | amd64
openbsd | arm
plan9 | 386
plan9 | amd64
solaris | amd64
windows | 386
windows | amd64

# Compile for Android
These instructions can be followed to compile for Android

* Install Android SDK
https://developer.android.com/ndk/guides/index.html
* Install gomobile
`go get golang.org/x/mobile/cmd/gomobile`
* Initialize gomobile
`bin\gomobile init
-ndk=C:\Users\[username]\AppData\Local\Android\Sdk\ndk-bundle`
* Build the APK `bin\gomobile build -target=android merlinagent`
This directory contains compiled Merlin Agent binaries for different operating
systems and architectures.
Loading

0 comments on commit 506ebc4

Please sign in to comment.