Skip to content

Commit

Permalink
Updated build constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
Ne0nd0g committed Feb 19, 2024
1 parent c07d1c0 commit a80c0da
Show file tree
Hide file tree
Showing 17 changed files with 380 additions and 36 deletions.
2 changes: 1 addition & 1 deletion clients/http/http.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !mythic
//go:build http || http1 || http2 || http3 || winhttp || !(mythic || smb || tcp || udp)

/*
Merlin is a post-exploitation command and control framework.
Expand Down
126 changes: 126 additions & 0 deletions clients/http/http_exclude.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
//go:build !http && !http1 && !http2 && !http3 && !winhttp && (mythic || smb || tcp || udp)

/*
Merlin is a post-exploitation command and control framework.
This file is part of Merlin.
Copyright (C) 2023 Russel Van Tuyl
Merlin is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.
Merlin is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Merlin. If not, see <http://www.gnu.org/licenses/>.
*/

// Package http implements the Client interface and contains the structures and functions to communicate to the Merlin
// server over the HTTP protocol
package http

import (
// Standard
"fmt"

// 3rd Party
"github.com/google/uuid"

// Internal
messages "github.com/Ne0nd0g/merlin-message"
)

// Client is a type of MerlinClient that is used to send and receive Merlin messages from the Merlin server
type Client struct {
}

// Config is a structure used to pass in all necessary information to instantiate a new Client
type Config struct {
AgentID uuid.UUID // AgentID the Agent's UUID
Protocol string // Protocol contains the transportation protocol the agent is using (i.e., http2 or smb-reverse)
Host string // Host is used with the HTTP Host header for Domain Fronting activities
Headers string // Headers is a new-line separated string of additional HTTP headers to add to client requests
URL []string // URL is the protocol, domain, and page that the agent will communicate with (e.g., https://google.com/test.aspx)
Proxy string // Proxy is the URL of the proxy that all traffic needs to go through, if applicable
ProxyUser string // ProxyUser is the username for the proxy, if applicable
ProxyPass string // ProxyPass is the password for the proxy, if applicable
UserAgent string // UserAgent is the HTTP User-Agent header string that Agent will use while sending traffic
Parrot string // Parrot is a feature of the github.com/refraction-networking/utls to mimic a specific browser
PSK string // PSK is the Pre-Shared Key secret the agent will use to start authentication
JA3 string // JA3 is a string that represents how the TLS client should be configured, if applicable
Padding string // Padding is the max amount of data that will be randomly selected and appended to every message
AuthPackage string // AuthPackage is the type of authentication the agent should use when communicating with the server
Opaque []byte // Opaque is the byte representation of the EnvU object used with the OPAQUE protocol (future use)
Transformers string // Transformers is an ordered comma seperated list of transforms (encoding/encryption) to apply when constructing a message
InsecureTLS bool // InsecureTLS is a boolean that determines if the InsecureSkipVerify flag is set to true or false
ClientType string // ClientType is the type of WINDOWS http client to use (e.g., WinINet, WinHTTP, etc.)
}

// New instantiates and returns a Client constructed from the passed in Config
func New(config Config) (*Client, error) {
return nil, fmt.Errorf("clients/http.New(): HTTP client not compiled into this program")
}

// Listen waits for incoming data on an established connection, deconstructs the data into a Base messages, and returns them
func (client *Client) Listen() (returnMessages []messages.Base, err error) {
err = fmt.Errorf("clients/http.Listen(): the HTTP client does not support the Listen function")
return
}

// Send takes in a Merlin message structure, performs any encoding or encryption, and sends it to the server.
// The function also decodes and decrypts response messages and returns a Merlin message structure.
// This is where the client's logic is for communicating with the server.
func (client *Client) Send(m messages.Base) (returnMessages []messages.Base, err error) {
err = fmt.Errorf("clients/http.New(): HTTP client not compiled into this program")
return
}

// Set is a generic function used to modify a Client's field values
func (client *Client) Set(key string, value string) (err error) {
err = fmt.Errorf("clients/http.Set(): HTTP client not compiled into this program")
return
}

// Get is a generic function used to retrieve the value of a Client's field
func (client *Client) Get(key string) (value string) {
return fmt.Sprintf("clients/http.Get(): HTTP client not compiled into this program")
}

// Authenticate is the top-level function used to authenticate an agent to server using a specific authentication protocol
// The function must take in a Base message for when the C2 server requests re-authentication through a message
func (client *Client) Authenticate(msg messages.Base) (err error) {
err = fmt.Errorf("clients/http.Authenticate(): HTTP client not compiled into this program")
return
}

// Construct takes in a messages.Base structure that is ready to be sent to the server and runs all the configured transforms
// on it to encode and encrypt it. Transforms will go from last in the slice to first in the slice
func (client *Client) Construct(msg messages.Base) (data []byte, err error) {
err = fmt.Errorf("clients/http.Construct(): HTTP client not compiled into this program")
return
}

// Deconstruct takes in data returned from the server and runs all the Agent's transforms on it until
// a messages.Base structure is returned. The key is used for decryption transforms
func (client *Client) Deconstruct(data []byte) (messages.Base, error) {
return messages.Base{}, fmt.Errorf("clients/http.Deconstruct(): HTTP client not compiled into this program")
}

// Initial contains all the steps the agent and/or the communication profile need to take to set up and initiate
// communication with the server.
// If the agent needs to authenticate before it can send messages, that process will occur here.
func (client *Client) Initial() (err error) {
err = fmt.Errorf("clients/http.Initial(): HTTP client not compiled into this program")
return
}

// Synchronous identifies if the client connection is synchronous or asynchronous, used to determine how and when messages
// can be sent/received.
func (client *Client) Synchronous() bool {
return false
}
37 changes: 10 additions & 27 deletions clients/smb/smb.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !windows
//go:build !smb && (http || http1 || http2 || http3 || mythic || winhttp || tcp || udp || !windows)

/*
Merlin is a post-exploitation command and control framework.
Expand Down Expand Up @@ -26,36 +26,16 @@ package smb
import (
// Standard
"fmt"
"net"
"runtime"
"sync"

// 3rd Party
"github.com/google/uuid"

// Merlin
"github.com/Ne0nd0g/merlin-message"

// Internal
"github.com/Ne0nd0g/merlin-agent/v2/authenticators"
transformer "github.com/Ne0nd0g/merlin-agent/v2/transformers"
)

// Client is a type of MerlinClient that is used to send and receive Merlin messages from the Merlin server
type Client struct {
address string // address is the SMB named pipe the agent will bind to
agentID uuid.UUID // agentID the Agent's UUID
authenticated bool // authenticated tracks if the Agent has successfully authenticated
authenticator authenticators.Authenticator // authenticator the method the Agent will use to authenticate to the server
connection net.Conn // connection the network socket connection used to handle traffic
listener net.Listener // listener the network socket connection listening for traffic
listenerID uuid.UUID // listenerID the UUID of the listener that this Agent is configured to communicate with
paddingMax int // paddingMax the maximum amount of random padding to apply to every Base message
psk string // psk the pre-shared key used for encrypting messages until authentication is complete
secret []byte // secret the key used to encrypt messages
transformers []transformer.Transformer // Transformers an ordered list of transforms (encoding/encryption) to apply when constructing a message
mode int // mode the type of client or communication mode (e.g., BIND or REVERSE)
sync.Mutex // used to lock the Client when changes are being made by one function or routine
}

// Config is a structure used to pass in all necessary information to instantiate a new Client
Expand All @@ -72,41 +52,44 @@ type Config struct {

// New instantiates and returns a Client that is constructed from the passed in Config
func New(Config) (*Client, error) {
if runtime.GOOS == "windows" {

Check warning on line 55 in clients/smb/smb.go

View workflow job for this annotation

GitHub Actions / Qodana for Go

Bool condition

Condition `runtime.GOOS == "windows"` is always `false`
return nil, fmt.Errorf("clients/smb.New(): SMB client not compiled into this program")
}
return nil, fmt.Errorf("clients/smb.New(): this function is not supported by the %s operating system", runtime.GOOS)
}

// Authenticate is the top-level function used to authenticate an agent to server using a specific authentication protocol
// The function must take in a Base message for when the C2 server requests re-authentication through a message
func (client *Client) Authenticate(messages.Base) (err error) {
return fmt.Errorf("clients/smb.Authenticate(): the smb client is not supported for the %s operating system", runtime.GOOS)
return fmt.Errorf("clients/smb.Authenticate(): SMB client not compiled into this program")
}

// Get is a generic function used to retrieve the value of a Client's field
func (client *Client) Get(string) string {
return fmt.Sprintf("clients/smb.Get(): the smb client is not supported for the %s operating system", runtime.GOOS)
return fmt.Sprintf("clients/smb.Get(): SMB client not compiled into this program")
}

// Initial executes the specific steps required to establish a connection with the C2 server and checkin or register an agent
func (client *Client) Initial() error {
return fmt.Errorf("clients/smb.Initial(): the smb client is not supported for the %s operating system", runtime.GOOS)
return fmt.Errorf("clients/smb.Initial(): SMB client not compiled into this program")
}

// Listen waits for incoming data on an established TCP connection, deconstructs the data into a Base messages, and returns them
func (client *Client) Listen() (returnMessages []messages.Base, err error) {
err = fmt.Errorf("clients/smb.LIsten(): the smb client is not supported for the %s operating system", runtime.GOOS)
err = fmt.Errorf("clients/smb.LIsten(): SMB client not compiled into this program")
return
}

// Send takes in a Merlin message structure, performs any encoding or encryption, converts it to a delegate and writes it to the output stream.
// This function DOES not wait or listen for response messages.
func (client *Client) Send(messages.Base) (returnMessages []messages.Base, err error) {
err = fmt.Errorf("clients/smb.Send(): the smb client is not supported for the %s operating system", runtime.GOOS)
err = fmt.Errorf("clients/smb.Send(): SMB client not compiled into this program")
return
}

// Set is a generic function that is used to modify a Client's field values
func (client *Client) Set(key string, value string) error {
return fmt.Errorf("clients/smb.Set(): the smb client is not supported for the %s operating system", runtime.GOOS)
return fmt.Errorf("clients/smb.Set(): SMB client not compiled into this program")
}

// Synchronous identifies if the client connection is synchronous or asynchronous, used to determine how and when messages
Expand Down
2 changes: 1 addition & 1 deletion clients/smb/smb_windows.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build windows
//go:build smb || !(http2 || http3 || mythic || winhttp || tcp || udp)

/*
Merlin is a post-exploitation command and control framework.
Expand Down
2 changes: 2 additions & 0 deletions clients/tcp/tcp.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build tcp || !(http || http1 || http2 || http3 || mythic || winhttp || smb || udp)

/*
Merlin is a post-exploitation command and control framework.
Expand Down
96 changes: 96 additions & 0 deletions clients/tcp/tcp_exclude.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//go:build !tcp && (http || http1 || http2 || http3 || mythic || winhttp || smb || udp)

/*
Merlin is a post-exploitation command and control framework.
This file is part of Merlin.
Copyright (C) 2023 Russel Van Tuyl
Merlin is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.
Merlin is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Merlin. If not, see <http://www.gnu.org/licenses/>.
*/

// Package tcp contains a configurable client used for TCP-based peer-to-peer Agent communications
package tcp

import (
// Standard
"fmt"

// 3rd Party
"github.com/google/uuid"

// Internal
messages "github.com/Ne0nd0g/merlin-message"
)

// Client is a type of MerlinClient that is used to send and receive Merlin messages from the Merlin server
type Client struct {
}

// Config is a structure used to pass in all necessary information to instantiate a new Client
type Config struct {
Address []string // Address the interface and port the agent will bind to
AgentID uuid.UUID // AgentID the Agent's UUID
AuthPackage string // AuthPackage the type of authentication the agent should use when communicating with the server
ListenerID uuid.UUID // ListenerID the UUID of the listener that this Agent is configured to communicate with
Padding string // Padding the max amount of data that will be randomly selected and appended to every message
PSK string // PSK the Pre-Shared Key secret the agent will use to start authentication
Transformers string // Transformers is an ordered comma seperated list of transforms (encoding/encryption) to apply when constructing a message
Mode string // Mode the type of client or communication mode (e.g., BIND or REVERSE)
}

// New instantiates and returns a Client that is constructed from the passed in Config
func New(Config) (*Client, error) {
return nil, fmt.Errorf("clients/tcp.New(): TCP client not compiled into this program")
}

// Authenticate is the top-level function used to authenticate an agent to server using a specific authentication protocol
// The function must take in a Base message for when the C2 server requests re-authentication through a message
func (client *Client) Authenticate(messages.Base) (err error) {
return fmt.Errorf("clients/tcp.Authenticate(): TCP client not compiled into this program")
}

// Get is a generic function used to retrieve the value of a Client's field
func (client *Client) Get(string) string {
return fmt.Sprintf("clients/tcp.Get(): TCP client not compiled into this program")
}

// Initial executes the specific steps required to establish a connection with the C2 server and checkin or register an agent
func (client *Client) Initial() error {
return fmt.Errorf("clients/tcp.Initial(): TCP client not compiled into this program")
}

// Listen waits for incoming data on an established TCP connection, deconstructs the data into a Base messages, and returns them
func (client *Client) Listen() (returnMessages []messages.Base, err error) {
err = fmt.Errorf("clients/tcp.LIsten(): TCP client not compiled into this program")
return
}

// Send takes in a Merlin message structure, performs any encoding or encryption, converts it to a delegate and writes it to the output stream.
// This function DOES not wait or listen for response messages.
func (client *Client) Send(messages.Base) (returnMessages []messages.Base, err error) {
err = fmt.Errorf("clients/tcp.Send(): TCP client not compiled into this program")
return
}

// Set is a generic function that is used to modify a Client's field values
func (client *Client) Set(key string, value string) error {
return fmt.Errorf("clients/tcp.Set(): TCP client not compiled into this program")
}

// Synchronous identifies if the client connection is synchronous or asynchronous, used to determine how and when messages
// can be sent/received.
func (client *Client) Synchronous() bool {
return false
}
2 changes: 2 additions & 0 deletions clients/udp/udp.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build udp || !(http || http1 || http2 || http3 || mythic || winhttp || smb || tcp)

/*
Merlin is a post-exploitation command and control framework.
Expand Down
Loading

0 comments on commit a80c0da

Please sign in to comment.