179 lines
4.1 KiB
Go
179 lines
4.1 KiB
Go
package main
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"fmt"
|
|
"io"
|
|
"slices"
|
|
"strings"
|
|
|
|
"github.com/chzyer/readline"
|
|
)
|
|
|
|
// Handles operator commands and context switching
|
|
func processOperatorCommand(command string, conn *tls.Conn, rl *readline.Instance, doneChan chan struct{}) bool {
|
|
if command == "" {
|
|
return false
|
|
}
|
|
|
|
// Handle exit and quit commands
|
|
if command == "exit" {
|
|
// Exit from agent context
|
|
if currentAgentContext != "" {
|
|
currentAgentContext = ""
|
|
rl.SetPrompt("\033[31mSigma >\033[0m ")
|
|
// Update tab completion after context change
|
|
rl.Config.AutoComplete = getCompleter()
|
|
return false
|
|
} else {
|
|
// Exit from application
|
|
fmt.Println("Exiting...")
|
|
conn.Write([]byte("exit"))
|
|
close(doneChan) // signal graceful exit
|
|
return true
|
|
}
|
|
} else if command == "quit" { // Exit from application and disregard context
|
|
fmt.Println("Exiting...")
|
|
conn.Write([]byte("exit"))
|
|
close(doneChan) // signal graceful exit
|
|
return true
|
|
}
|
|
|
|
// Receive help message
|
|
if command == "help" {
|
|
if currentAgentContext != "" {
|
|
command = "context_help"
|
|
conn.Write([]byte(command))
|
|
return false
|
|
|
|
} else {
|
|
command = "general_help"
|
|
conn.Write([]byte(command))
|
|
return false
|
|
}
|
|
}
|
|
|
|
// Handle interact command
|
|
if strings.HasPrefix(command, "interact") {
|
|
handleInteractCommand(command, rl)
|
|
return false
|
|
}
|
|
|
|
// Handle command in agent context
|
|
if currentAgentContext != "" && isControlCommand(command) {
|
|
command = "CONTEXT:" + currentAgentContext + " " + command
|
|
|
|
// Handle command in general context
|
|
} else {
|
|
// Double check maybe this is not agent context, but command has agent ID in the beginning
|
|
cmd := strings.Fields(command)
|
|
if slices.Contains(agents, cmd[0]) {
|
|
command = "CONTEXT:" + command
|
|
|
|
// General command
|
|
} else {
|
|
|
|
command = "GENERAL:" + command
|
|
}
|
|
}
|
|
|
|
// Send command to server
|
|
_, err := conn.Write([]byte(command))
|
|
if err != nil {
|
|
fmt.Printf("Error sending command: %v", err)
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// Executes the main command processing loop
|
|
func runCommandLoop(conn *tls.Conn, rl *readline.Instance, exitChan chan struct{}, doneChan chan struct{}) {
|
|
for {
|
|
select {
|
|
case <-exitChan:
|
|
fmt.Println("Exiting due to lost connection.")
|
|
return
|
|
default:
|
|
line, err := rl.Readline()
|
|
if err != nil {
|
|
if err == readline.ErrInterrupt {
|
|
if len(line) == 0 {
|
|
conn.Write([]byte("exit"))
|
|
fmt.Println("\nExiting...")
|
|
close(doneChan) // signal graceful exit
|
|
return
|
|
}
|
|
continue
|
|
} else if err == io.EOF {
|
|
fmt.Println("\nExiting...")
|
|
return
|
|
}
|
|
fmt.Printf("Error reading line: %v", err)
|
|
continue
|
|
}
|
|
|
|
command := strings.TrimSpace(line)
|
|
|
|
// Print the command to terminal history before processing
|
|
if command != "" {
|
|
// Construct the prompt based on current context
|
|
var currentPrompt string
|
|
if currentAgentContext != "" {
|
|
currentPrompt = fmt.Sprintf("\033[31mSigma [%s] >\033[0m ", currentAgentContext)
|
|
} else {
|
|
currentPrompt = "\033[31mSigma >\033[0m "
|
|
}
|
|
rl.Stdout().Write([]byte(currentPrompt + command + "\n"))
|
|
}
|
|
|
|
shouldExit := processOperatorCommand(command, conn, rl, doneChan)
|
|
if shouldExit {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check if command is a task for agent
|
|
func isControlCommand(command string) bool {
|
|
// Split the command into words
|
|
parts := strings.Fields(command)
|
|
if len(parts) == 0 {
|
|
fmt.Println("Empty command :(")
|
|
return false
|
|
}
|
|
|
|
// Check if the first word is a context command
|
|
if slices.Contains(implantCommands, parts[0]) {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
|
|
// Processes the interact command for agent context switching
|
|
func handleInteractCommand(command string, rl *readline.Instance) {
|
|
cmd := strings.Fields(command)
|
|
|
|
if len(cmd) != 2 {
|
|
fmt.Println("Usage: interact <agent_id>")
|
|
return
|
|
}
|
|
|
|
if !slices.Contains(agents, cmd[1]) {
|
|
fmt.Println("Agent not found!")
|
|
return
|
|
}
|
|
|
|
// Set new agent context
|
|
currentAgentContext = cmd[1]
|
|
|
|
// Update tab completion
|
|
rl.Config.AutoComplete = getCompleter()
|
|
|
|
// Update prompt with agent context
|
|
newPrompt := fmt.Sprintf("\033[31mSigma [%s] >\033[0m ", currentAgentContext)
|
|
rl.SetPrompt(newPrompt)
|
|
}
|