Tasks
Each instruction sent over from the server is referred to as a 'task'. Implants receive tasks, interpret and execute them, and return the response.
During development, each task must be assigned a numeric opcode, to discourage the sending of text-based task names over the connection. As these opcodes are specified by the developer, an implant should have a built-in mechanism to efficiently route tasks to their controller. This will be referred to as 'task management'
Task manager
Here is a simple, single-threaded implementation of a task manager from Empress.
package c2
import (
"github.com/pygrum/Empress/config"
"github.com/pygrum/Empress/transport"
"strconv"
)
type Handler func(*transport.Request, *transport.Response)
type Router struct {
handlers map[int32]Handler
}
func NewRouter() *Router {
return &Router{
handlers: make(map[int32]Handler),
}
}
func (r *Router) HandleFunc(opcode int32, handler Handler) {
r.handlers[opcode] = handler
}
func (r *Router) handle(req *transport.Request) *transport.Response {
resp := &transport.Response{
AgentID: config.C.AgentID,
RequestID: req.RequestID,
}
handleFunc, ok := r.handlers[req.Opcode]
if !ok {
resp.Responses = append(resp.Responses, transport.ResponseDetail{
Status: transport.StatusErrorWithMessage,
Dest: transport.DestStdout,
Data: []byte("unknown opcode " + strconv.Itoa(int(req.Opcode))),
})
return resp
}
handleFunc(req, resp)
return resp
}The router has various callback functions registered for each opcode received from the C2. This means that once a client receives a server request (transport.Request), it can simply call the handle function on the router, which will send the request to the appropriate handler and return the response.
Now, whenever a new function is created, the developer simply needs to register the function with the client's internal router. Here is an example of integrating the function ls .
You may notice that CmdLS has the function signature of a router callback. So we can simply go ahead and register it as one of the HandleFunc:
The server integration page goes into more detail about how registration and polling objects are structured.
Last updated