Skip to content

Commit

Permalink
Merge branch 'misc002' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
Ne0nd0g committed Jan 26, 2019
2 parents 2c44764 + 53d4a33 commit c258c60
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 33 deletions.
7 changes: 5 additions & 2 deletions cmd/merlinserver/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,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 Down Expand Up @@ -71,7 +71,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
12 changes: 12 additions & 0 deletions docs/CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## 0.6.8 - 2019-01-26

### Added
- The `status` command while in the agent menu to see if agent is Active, Delayed, or Dead
- Messages printed to the CLI now include a UTC timestamp
- Added Merlin version number and new agent checkins to Merlin Server log file

### Fixed
- Formatting error placing time stamp and message in wrong spot in the Merlin Server log file
- Error checking in logging.go
- Server shutdown was not actually being logged

## 0.6.7 - 2019-01-22

### Added
Expand Down
8 changes: 5 additions & 3 deletions pkg/agents/agents.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ func InitialCheckIn(j messages.Base) {
message("debug", fmt.Sprintf("Base Message Type: %s", j.Type))
message("debug", fmt.Sprintf("Base Message Payload: %s", j.Payload))
}
message("success", fmt.Sprintf("Received new agent checkin from %s", j.ID))
logging.Server(fmt.Sprintf("Received new agent checkin from %s", j.ID))
message("success", fmt.Sprintf("Received new agent checkin from %s at %s", j.ID, time.Now().UTC().Format(time.RFC3339)))

// Unmarshal AgentInfo from Base
var agentInfo messages.AgentInfo
Expand Down Expand Up @@ -171,7 +172,7 @@ func InitialCheckIn(j messages.Base) {
Log(j.ID, fmt.Sprintf("HostName: %s", sysInfo.HostName))
Log(j.ID, fmt.Sprintf("UserName: %s", sysInfo.UserName))
Log(j.ID, fmt.Sprintf("UserGUID: %s", sysInfo.UserGUID))
Log(j.ID, fmt.Sprintf("Process ID: %s", sysInfo.Pid))
Log(j.ID, fmt.Sprintf("Process ID: %d", sysInfo.Pid))
Log(j.ID, fmt.Sprintf("IPs: %v", sysInfo.Ips))
}

Expand All @@ -180,7 +181,8 @@ func StatusCheckIn(j messages.Base) (messages.Base, error) {
// Check to make sure agent UUID is in dataset
_, ok := Agents[j.ID]
if !ok {
message("warn", fmt.Sprintf("Orphaned agent %s has checked in. Instructing agent to re-initialize...", j.ID.String()))
message("warn", fmt.Sprintf("Orphaned agent %s has checked in at %s. Instructing agent to re-initialize...",
time.Now().UTC().Format(time.RFC3339), j.ID.String()))
logging.Server(fmt.Sprintf("[Orphaned agent %s has checked in", j.ID.String()))
job := Job{
ID: core.RandStringBytesMaskImprSrc(10),
Expand Down
63 changes: 45 additions & 18 deletions pkg/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ import (
"github.com/Ne0nd0g/merlin/pkg/agents"
"github.com/Ne0nd0g/merlin/pkg/banner"
"github.com/Ne0nd0g/merlin/pkg/core"
"github.com/Ne0nd0g/merlin/pkg/logging"
"github.com/Ne0nd0g/merlin/pkg/modules"
)

// Global Variables
var serverLog *os.File
var shellModule modules.Module
var shellAgent uuid.UUID
var prompt *readline.Instance
Expand Down Expand Up @@ -182,7 +182,8 @@ func Shell() {
if err != nil {
message("warn", err.Error())
} else {
message("note", fmt.Sprintf("Created job %s for agent %s", m, shellModule.Agent))
message("note", fmt.Sprintf("Created job %s for agent %s at %s",
m, shellModule.Agent, time.Now().UTC().Format(time.RFC3339)))
}
}
case "back":
Expand Down Expand Up @@ -216,7 +217,8 @@ func Shell() {
if err != nil {
message("warn", err.Error())
} else {
message("note", fmt.Sprintf("Created job %s for agent %s", m, shellAgent))
message("note", fmt.Sprintf("Created job %s for agent %s at %s",
m, shellAgent, time.Now().UTC().Format(time.RFC3339)))
}
}
case "download":
Expand All @@ -233,7 +235,8 @@ func Shell() {
message("warn", err.Error())
break
} else {
message("note", fmt.Sprintf("Created job %s for agent %s", m, shellAgent))
message("note", fmt.Sprintf("Created job %s for agent %s at %s",
m, shellAgent, time.Now().UTC().Format(time.RFC3339)))
}
}
} else {
Expand Down Expand Up @@ -323,31 +326,35 @@ func Shell() {
message("warn", err.Error())
break
} else {
message("note", fmt.Sprintf("Created job %s for agent %s", m, shellAgent))
message("note", fmt.Sprintf("Created job %s for agent %s at %s",
m, shellAgent, time.Now().UTC().Format(time.RFC3339)))
}
case "remote":
m, err := agents.AddJob(shellAgent, "shellcode", []string{"remote", cmd[2], b64})
if err != nil {
message("warn", err.Error())
break
} else {
message("note", fmt.Sprintf("Created job %s for agent %s", m, shellAgent))
message("note", fmt.Sprintf("Created job %s for agent %s at %s",
m, shellAgent, time.Now().UTC().Format(time.RFC3339)))
}
case "rtlcreateuserthread":
m, err := agents.AddJob(shellAgent, "shellcode", []string{"rtlcreateuserthread", cmd[2], b64})
if err != nil {
message("warn", err.Error())
break
} else {
message("note", fmt.Sprintf("Created job %s for agent %s", m, shellAgent))
message("note", fmt.Sprintf("Created job %s for agent %s at %s",
m, shellAgent, time.Now().UTC().Format(time.RFC3339)))
}
case "userapc":
m, err := agents.AddJob(shellAgent, "shellcode", []string{"userapc", cmd[2], b64})
if err != nil {
message("warn", err.Error())
break
} else {
message("note", fmt.Sprintf("Created job %s for agent %s", m, shellAgent))
message("note", fmt.Sprintf("Created job %s for agent %s at %s",
m, shellAgent, time.Now().UTC().Format(time.RFC3339)))
}
default:
message("warn", fmt.Sprintf("Invalid shellcode execution method: %s", cmd[1]))
Expand All @@ -368,7 +375,8 @@ func Shell() {
if err != nil {
message("warn", err.Error())
} else {
message("note", fmt.Sprintf("Created job %s for agent %s", m, shellAgent))
message("note", fmt.Sprintf("Created job %s for agent %s at %s",
m, shellAgent, time.Now().UTC().Format(time.RFC3339)))
}
}
case "main":
Expand All @@ -384,7 +392,8 @@ func Shell() {
if err != nil {
message("warn", err.Error())
} else {
message("note", fmt.Sprintf("Created job %s for agent %s", m, shellAgent))
message("note", fmt.Sprintf("Created job %s for agent %s at %s",
m, shellAgent, time.Now().UTC().Format(time.RFC3339)))
}
}
case "padding":
Expand All @@ -393,7 +402,8 @@ func Shell() {
if err != nil {
message("warn", err.Error())
} else {
message("note", fmt.Sprintf("Created job %s for agent %s", m, shellAgent))
message("note", fmt.Sprintf("Created job %s for agent %s at %s",
m, shellAgent, time.Now().UTC().Format(time.RFC3339)))
}
}
case "sleep":
Expand All @@ -402,7 +412,8 @@ func Shell() {
if err != nil {
message("warn", err.Error())
} else {
message("note", fmt.Sprintf("Created job %s for agent %s", m, shellAgent))
message("note", fmt.Sprintf("Created job %s for agent %s at %s",
m, shellAgent, time.Now().UTC().Format(time.RFC3339)))
}
}
case "skew":
Expand All @@ -411,7 +422,8 @@ func Shell() {
if err != nil {
message("warn", err.Error())
} else {
message("note", fmt.Sprintf("Created job %s for agent %s", m, shellAgent))
message("note", fmt.Sprintf("Created job %s for agent %s at %s",
m, shellAgent, time.Now().UTC().Format(time.RFC3339)))
}
}
}
Expand All @@ -422,9 +434,21 @@ func Shell() {
if err != nil {
message("warn", err.Error())
} else {
message("note", fmt.Sprintf("Created job %s for agent %s", m, shellAgent))
message("note", fmt.Sprintf("Created job %s for agent %s at %s",
m, shellAgent, time.Now().UTC().Format(time.RFC3339)))
}
}
case "status":
status := agents.GetAgentStatus(shellAgent)
if status == "Active" {
color.Green("Active")
} else if status == "Delayed" {
color.Yellow("Delayed")
} else if status == "Dead" {
color.Red("Dead")
} else {
color.Blue(status)
}
case "upload":
if len(cmd) >= 3 {
arg := strings.Join(cmd[1:], " ")
Expand All @@ -444,7 +468,8 @@ func Shell() {
message("warn", err.Error())
break
} else {
message("note", fmt.Sprintf("Created job %s for agent %s", m, shellAgent))
message("note", fmt.Sprintf("Created job %s for agent %s at %s",
m, shellAgent, time.Now().UTC().Format(time.RFC3339)))
}
}
} else {
Expand Down Expand Up @@ -525,7 +550,8 @@ func menuAgent(cmd []string) {
if errRemove != nil {
message("warn", fmt.Sprintf("%s", errRemove.Error()))
} else {
message("info", fmt.Sprintf("Agent %s was removed from the server", cmd[1]))
message("info", fmt.Sprintf("Agent %s was removed from the server at %s",
cmd[1], time.Now().UTC().Format(time.RFC3339)))
}
}
}
Expand Down Expand Up @@ -633,6 +659,7 @@ func getCompleter(completer string) *readline.PrefixCompleter {
readline.PcItem("skew"),
readline.PcItem("sleep"),
),
readline.PcItem("status"),
readline.PcItem("upload"),
)

Expand All @@ -646,7 +673,6 @@ func getCompleter(completer string) *readline.PrefixCompleter {
default:
return main
}
return main
}

func menuHelpMain() {
Expand Down Expand Up @@ -720,6 +746,7 @@ func menuHelpAgent() {
{"main", "Return to the main menu", ""},
{"set", "Set the value for one of the agent's options", "maxretry, padding, skew, sleep"},
{"shell", "Execute a command on the agent", "shell ping -c 3 8.8.8.8"},
{"status", "Print the current status of the agent", ""},
{"upload", "Upload a file to the agent", "upload <local_file> <remote_file>"},
}

Expand Down Expand Up @@ -759,7 +786,7 @@ func message(level string, message string) {

func exit() {
color.Red("[!]Quitting")
serverLog.WriteString(fmt.Sprintf("[%s]Shutting down Merlin Server due to user input", time.Now()))
logging.Server("Shutting down Merlin Server due to user input")
os.Exit(0)
}

Expand Down
15 changes: 12 additions & 3 deletions pkg/logging/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,14 @@ func init() {

// Server Logging
if _, err := os.Stat(filepath.Join(core.CurrentDir, "data", "log", "merlinServerLog.txt")); os.IsNotExist(err) {
os.Mkdir(filepath.Join(core.CurrentDir, "data", "log"), os.ModeDir)
os.Create(filepath.Join(core.CurrentDir, "data", "log", "merlinServerLog.txt"))
errM := os.Mkdir(filepath.Join(core.CurrentDir, "data", "log"), os.ModeDir)
if errM != nil {
message("warn", "There was an error creating the log directory")
}
_, errC := os.Create(filepath.Join(core.CurrentDir, "data", "log", "merlinServerLog.txt"))
if errC != nil {
message("warn", "[!]There was an error creating the merlinServerLog.txt file")
}
if core.Debug {
message("debug", fmt.Sprintf("Created server log file at: %s\\data\\log\\merlinServerLog.txt", core.CurrentDir))
}
Expand All @@ -53,7 +59,10 @@ func init() {

// Server writes a log entry into the server's log file
func Server(logMessage string) {
serverLog.WriteString(fmt.Sprintf("[%s]%s\r\n", logMessage, time.Now()))
_, err := serverLog.WriteString(fmt.Sprintf("[%s]%s\r\n", time.Now().UTC().Format(time.RFC3339), logMessage))
if err != nil {
message("warn", "There was an error writing to the Merlin Server log file")
}
}

// Message is used to print a message to the command line
Expand Down
2 changes: 1 addition & 1 deletion pkg/merlin.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
package merlin

// Version is a constant variable containing the version number for the Merlin package
const Version = "0.6.7.BETA"
const Version = "0.6.8.BETA"

// Build is the unique number based off the git commit in which it is compiled against
var Build = "nonRelease"
10 changes: 4 additions & 6 deletions pkg/servers/http2/http2.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"encoding/pem"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
Expand Down Expand Up @@ -169,8 +168,7 @@ func New(iface string, port int, protocol string, key string, certificate string

// Run function starts the server on the preconfigured port for the preconfigured service
func (s *Server) Run() error {
logging.Server(fmt.Sprintf("Starting %s Listener", s.Protocol))
logging.Server(fmt.Sprintf("Address: %s:%d/", s.Interface, s.Port))
logging.Server(fmt.Sprintf("Starting %s Listener at %s:%d", s.Protocol, s.Interface, s.Port))
logging.Server(fmt.Sprintf("x.509 Certificate %s", s.Certificate))
logging.Server(fmt.Sprintf("x.509 Key %s", s.Key))

Expand All @@ -180,12 +178,12 @@ func (s *Server) Run() error {
if s.Protocol == "h2" {
server := s.Server.(*http.Server)
defer server.Close()
go log.Print(server.ListenAndServeTLS(s.Certificate, s.Key))
go logging.Server(server.ListenAndServeTLS(s.Certificate, s.Key).Error())
return nil
} else if s.Protocol == "hq" {
server := s.Server.(*h2quic.Server)
defer server.Close()
go log.Print(server.ListenAndServeTLS(s.Certificate, s.Key))
go logging.Server(server.ListenAndServeTLS(s.Certificate, s.Key).Error())
return nil
}
return fmt.Errorf("%s is an invalid server protocol", s.Protocol)
Expand Down Expand Up @@ -259,7 +257,7 @@ func agentHandler(w http.ResponseWriter, r *http.Request) {
json.Unmarshal(payload, &p)
agents.Log(j.ID, fmt.Sprintf("Results for job: %s", p.Job))

message("success", fmt.Sprintf("Results for job %s", p.Job))
message("success", fmt.Sprintf("Results for job %s at %s", p.Job, time.Now().UTC().Format(time.RFC3339)))
if len(p.Stdout) > 0 {
agents.Log(j.ID, fmt.Sprintf("Command Results (stdout):\r\n%s", p.Stdout))
color.Green(fmt.Sprintf("%s", p.Stdout))
Expand Down

0 comments on commit c258c60

Please sign in to comment.