Documentation
¶
Overview ¶
The external C2 module extends the C2 functionality and exposes an interface to allow for an exploit to utilize a channel that is defined in an external repository. This enables third-party and non-trivial channels. This module defines an interface and external service type that must be handled by the implementing external module.
The External interface requires the following functions, each of which require the external C2 to define a set of functions:
- Configure - A function to wrap the internal C2 functions and integrate them into the go-exploit expected structure.
- SetFlags - Configure the C2 specific flags used by the exploit.
- SetInit - Sets up the server singleton/C2 representation of the server structs.
- SetChannel` - Creates the go-exploit channel that is the framework representation of an object and allows for channel settings to filter into the external module.
- SetRun - The function that actually runs the external C2.
At this time only one External module can be defined per exploit as the implementation and singleton can not be duplicated.
Creating an external C2 channel ¶
An external module template will generally be structured as follows:
package c2external import ( "flag" "net" "github.com/vulncheck-oss/go-exploit/c2" "github.com/vulncheck-oss/go-exploit/c2/channel" "github.com/vulncheck-oss/go-exploit/c2/external" ) var flagCommand string var ( Name = "ExtServer" ExtServer c2.Impl ) type ExternalC2 struct { Channel *channel.Channel // Example of how you can define variables accessible in the set functions Listener *net.Listener } func New() ExternalC2 { return ExternalC2{} } func (c2 *ExternalC2) ExtServerFlags() { // Flags for the external C2. The run function in the framework handles the parsing and // the options will be available to the exploit. flag.StringVar(&flagCommand, Name+".command", "", "Run a single command and exit the payload.") } func (c2 *ExternalC2) ExtServerInit() { // Any initialization such as key generation or external configuration components can go // here. } func (c2 *ExternalC2) ExtServerChannel(channel *channel.Channel) { // This will generally just be setting the internal channel to match the expected // go-exploit channel and provide access to the framework channel. c2.Channel = channel } func (c2 *ExternalC2) ExtServerRun(timeout int) bool { // Add any servers or connection pooling here // Make sure to handle the timeout! return false } func Configure(externalServer *external.Server) { ExtServer = c2.AddC2(Name) extc2 := New() externalServer.SetFlags(extc2.ExtServerFlags) externalServer.SetChannel(extc2.ExtServerChannel) externalServer.SetInit(extc2.ExtServerInit) externalServer.SetRun(extc2.ExtServerRun) }
Adding an external C2 to an exploit ¶
In order to add an external C2 to an exploit it is required to get a new
package main import ( "flag" "os/exec" "github.com/vulncheck-oss/go-exploit" "github.com/vulncheck-oss/go-exploit/c2" "github.com/vulncheck-oss/go-exploit/c2/external" "github.com/vulncheck-oss/go-exploit/config" "github.com/vulncheck-oss/go-exploit/output" c2example "github.com/vulncheck-oss/external-c2-experiments/example" ) type ExternalTest struct{} var flagPayload string func (sploit ExternalTest) ValidateTarget(_ *config.Config) bool { return false } func (sploit ExternalTest) CheckVersion(_ *config.Config) exploit.VersionCheckType { return exploit.NotImplemented } func (sploit ExternalTest) RunExploit(conf *config.Config) bool { if flagPayload == "" { output.PrintfStatus("Payload argument required") return false } cmd := exec.Command(flagPayload) stdoutStderr, err := cmd.CombinedOutput() if err != nil { output.PrintfError("%s", err.Error()) } output.PrintfError("%s", stdoutStderr) return true } func main() { flag.StringVar(&flagPayload, "payload", "", "Payload to execute") ext2 := external.GetInstance(c2example.ExtServer.Name) c2example.Configure(ext2) supportedC2 := []c2.Implementation{ c2example.ExtServer, c2.SimpleShellServer, } conf := config.NewRemoteExploit( config.ImplementedFeatures{ AssetDetection: false, VersionScanning: false, Exploitation: false }, config.CodeExecution, supportedC2, "Vendor", []string{"Product"}, []string{"cpe:2.3:a:vendor:product"}, "CVE-2024-1270", "HTTP", 8080 ) sploit := ExternalTest{} exploit.RunProgram(sploit, conf) }
It is important to keep in mind that a payload will still need to be written for our newly created external C2, as well as handling said payload in the exploit.
In order to use the above C2 in an exploit the following shows how it could be used:
Index ¶
- type External
- type Server
- func (externalServer *Server) CreateFlags()
- func (externalServer *Server) Init(channel channel.Channel) bool
- func (externalServer *Server) Run(timeout int)
- func (externalServer *Server) SetChannel(f func(*channel.Channel))
- func (externalServer *Server) SetFlags(f func())
- func (externalServer *Server) SetInit(f func())
- func (externalServer *Server) SetRun(f func(int) bool)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type External ¶
type External interface { Configure(*Server) SetChannel(func(*channel.Channel)) SetFlags(func()) SetInit(func()) SetRun(func(int) bool) }
The External interface defines which functions are required to be defined in an external C2 channel in order to function inside the framework properly. These are ordered in generally suggested execution order.
type Server ¶
The Server struct holds the declared external modules internal functions and channel data.
func GetInstance ¶
Gets the singleton instance of the external C2. These are kept track based on their internal names.
func (*Server) CreateFlags ¶
func (externalServer *Server) CreateFlags()
CreateFlags is used by the framework to run the set function for flag management. This is not expected to be implemented by the downstream external C2.
func (*Server) Init ¶
Init triggers the set C2 initialization and passes the channel to the external module.
func (*Server) SetChannel ¶
SetChannel sets the function for channel management. The go-exploit channel represents basic settings that are provided to the frameworks core modules and are regularly used as ergonomic helpers, but may also be required by the external module (ie accessing -lhost or -lport variables without having to resort to passing all flag arguments). This generally does not need to be complex and is often just passing the channel to a C2 side variable, but they can also be used to modify the channel for use in a C2.
func (*Server) SetFlags ¶
func (externalServer *Server) SetFlags(f func())
SetFlags sets the external modules function for command line flag management.
func (*Server) SetInit ¶
func (externalServer *Server) SetInit(f func())
SetInit sets the external C2 initialization function. This function is expected to be used for any database management, configuration parsing, and any other functionality required for the C2 that is not managed by the go-exploit framework channels or command line flags.