2026-04-06 00:20:51 -05:00

385 lines
9.6 KiB
Go

package server
import (
"AdaptixServer/core/eventing"
"AdaptixServer/core/utils/krypt"
"AdaptixServer/core/utils/logs"
"fmt"
"time"
"github.com/Adaptix-Framework/axc2"
)
type TaskHandler interface {
Create(tm *TaskManager, agent *Agent, taskData *adaptix.TaskData)
Update(tm *TaskManager, agent *Agent, task *adaptix.TaskData, updateData *adaptix.TaskData)
PostHook(tm *TaskManager, agent *Agent, task *adaptix.TaskData, hookData *adaptix.TaskData, jobIndex int) error
OnClientDisconnect(tm *TaskManager, agent *Agent, task *adaptix.TaskData, clientName string)
}
type TaskManager struct {
ts *Teamserver
handlers map[int]TaskHandler
}
func NewTaskManager(ts *Teamserver) *TaskManager {
tm := &TaskManager{
ts: ts,
handlers: make(map[int]TaskHandler),
}
taskHandler := &TaskTaskHandler{}
tm.handlers[adaptix.TASK_TYPE_TASK] = taskHandler
tm.handlers[adaptix.TASK_TYPE_BROWSER] = taskHandler
tm.handlers[adaptix.TASK_TYPE_JOB] = &JobTaskHandler{}
tm.handlers[adaptix.TASK_TYPE_TUNNEL] = &TunnelTaskHandler{}
return tm
}
func (tm *TaskManager) getAgent(agentId string) (*Agent, error) {
value, ok := tm.ts.Agents.Get(agentId)
if !ok {
return nil, fmt.Errorf("agent %v not found", agentId)
}
agent, ok := value.(*Agent)
if !ok {
return nil, fmt.Errorf("invalid agent type for %v", agentId)
}
return agent, nil
}
func (tm *TaskManager) prepareTaskData(agent *Agent, cmdline string, client string, taskData *adaptix.TaskData) {
agentData := agent.GetData()
if taskData.TaskId == "" {
taskData.TaskId, _ = krypt.GenerateUID(8)
}
taskData.AgentId = agentData.Id
taskData.CommandLine = cmdline
taskData.Client = client
taskData.Computer = agentData.Computer
taskData.StartDate = time.Now().Unix()
if taskData.Completed {
taskData.FinishDate = taskData.StartDate
}
taskData.User = agentData.Username
if agentData.Impersonated != "" {
taskData.User += fmt.Sprintf(" [%s]", agentData.Impersonated)
}
}
func (tm *TaskManager) syncTaskCreate(agentId string, agent *Agent, taskData *adaptix.TaskData) {
packet_task := CreateSpAgentTaskSync(*taskData)
tm.ts.TsSyncAllClientsWithCategory(packet_task, SyncCategoryTasksManager)
if taskData.Type != adaptix.TASK_TYPE_BROWSER {
packet_console := CreateSpAgentConsoleTaskSync(*taskData)
tm.ts.TsSyncConsole(packet_console, taskData.Client)
_ = tm.ts.DBMS.DbConsoleInsert(agentId, packet_console)
}
}
func (tm *TaskManager) syncTaskUpdate(agentId string, agent *Agent, taskData *adaptix.TaskData) {
packet_task := CreateSpAgentTaskUpdate(*taskData)
if taskData.HandlerId == "" {
tm.ts.TsSyncAllClientsWithCategory(packet_task, SyncCategoryTasksManager)
} else {
handlerClient := taskData.Client
tm.ts.TsSyncExcludeClientWithCategory(handlerClient, packet_task, SyncCategoryTasksManager)
packet_task.HandlerId = taskData.HandlerId
tm.ts.TsSyncClient(handlerClient, packet_task)
}
if taskData.Type != adaptix.TASK_TYPE_BROWSER {
packet_console := CreateSpAgentConsoleTaskUpd(*taskData)
tm.ts.TsSyncConsole(packet_console, taskData.Client)
_ = tm.ts.DBMS.DbConsoleInsert(agentId, packet_console)
}
}
func (tm *TaskManager) completeTask(agent *Agent, taskData *adaptix.TaskData) {
_ = tm.ts.DBMS.DbTaskInsert(*taskData)
// --- POST HOOK ---
postEvent := &eventing.EventDataTaskComplete{
AgentId: taskData.AgentId,
Task: *taskData,
}
tm.ts.EventManager.EmitAsync(eventing.EventTaskComplete, postEvent)
// -----------------
}
func (tm *TaskManager) executeServerHandler(taskData *adaptix.TaskData) {
if taskData.HandlerId == "" {
return
}
if !tm.ts.TsAxScriptIsServerHook(taskData.HandlerId) {
return
}
handlerData := map[string]interface{}{
"agent": taskData.AgentId,
"task_id": taskData.TaskId,
"cmdline": taskData.CommandLine,
"message": taskData.Message,
"text": taskData.ClearText,
"type": taskData.MessageType,
}
_ = tm.ts.TsAxScriptExecHandler(taskData.HandlerId, handlerData)
taskData.HandlerId = ""
}
func (tm *TaskManager) Create(agentId string, cmdline string, client string, taskData adaptix.TaskData) {
agent, err := tm.getAgent(agentId)
if err != nil {
logs.Error("", "TsTaskCreate: %v", err)
return
}
if !agent.Active {
return
}
tm.prepareTaskData(agent, cmdline, client, &taskData)
// --- PRE HOOK ---
preEvent := &eventing.EventDataTaskCreate{
AgentId: agentId,
Task: taskData,
Cmdline: cmdline,
Client: client,
}
if !tm.ts.EventManager.Emit(eventing.EventTaskCreate, eventing.HookPre, preEvent) {
return
}
// ----------------
handler, ok := tm.handlers[taskData.Type]
if !ok {
logs.Debug("", "Unknown task type: %d", taskData.Type)
return
}
handler.Create(tm, agent, &taskData)
// --- POST HOOK ---
postEvent := &eventing.EventDataTaskCreate{
AgentId: agentId,
Task: taskData,
Cmdline: cmdline,
Client: client,
}
tm.ts.EventManager.EmitAsync(eventing.EventTaskCreate, postEvent)
// -----------------
}
func (tm *TaskManager) Update(agentId string, updateData adaptix.TaskData) {
agent, err := tm.getAgent(agentId)
if err != nil {
logs.Error("", "TsTaskUpdate: %v", err)
return
}
value, ok := agent.RunningTasks.Get(updateData.TaskId)
if !ok {
return
}
task, ok := value.(adaptix.TaskData)
if !ok {
logs.Error("", "TsTaskUpdate: invalid task type for %v", updateData.TaskId)
return
}
task.Data = []byte("")
handler, ok := tm.handlers[task.Type]
if !ok {
logs.Debug("", "Unknown task type: %d", task.Type)
return
}
handler.Update(tm, agent, &task, &updateData)
}
func (tm *TaskManager) PostHook(hookData adaptix.TaskData, jobIndex int) error {
agent, err := tm.getAgent(hookData.AgentId)
if err != nil {
return err
}
value, ok := agent.RunningTasks.Get(hookData.TaskId)
if !ok {
return fmt.Errorf("task %v not found", hookData.TaskId)
}
task, ok := value.(adaptix.TaskData)
if !ok {
return fmt.Errorf("invalid task type for %v", hookData.TaskId)
}
if task.HookId == "" || task.HookId != hookData.HookId || task.Client != hookData.Client || !tm.ts.TsClientConnected(task.Client) {
return fmt.Errorf("operation not available")
}
handler, ok := tm.handlers[task.Type]
if !ok {
return fmt.Errorf("unknown task type: %d", task.Type)
}
return handler.PostHook(tm, agent, &task, &hookData, jobIndex)
}
func (tm *TaskManager) Cancel(agentId string, taskId string) error {
agent, err := tm.getAgent(agentId)
if err != nil {
return err
}
found, retTask := agent.HostedTasks.RemoveIf(func(v interface{}) bool {
task, ok := v.(adaptix.TaskData)
return ok && task.TaskId == taskId
})
if found {
task, ok := retTask.(adaptix.TaskData)
if ok {
if task.HookId != "" && tm.ts.TsAxScriptIsServerHook(task.HookId) {
tm.ts.TsAxScriptRemovePostHook(task.HookId)
}
if task.HandlerId != "" && tm.ts.TsAxScriptIsServerHook(task.HandlerId) {
tm.ts.TsAxScriptRemoveHandler(task.HandlerId)
}
packet := CreateSpAgentTaskRemove(task)
tm.ts.TsSyncAllClients(packet)
}
}
return nil
}
func (tm *TaskManager) Delete(agentId string, taskId string) error {
agent, err := tm.getAgent(agentId)
if err != nil {
return err
}
found, _ := agent.HostedTasks.FindIf(func(v interface{}) bool {
task, ok := v.(adaptix.TaskData)
return ok && task.TaskId == taskId
})
if found {
return fmt.Errorf("task %v in process", taskId)
}
_, ok := agent.RunningTasks.Get(taskId)
if ok {
return fmt.Errorf("task %v in process", taskId)
}
task, err := tm.ts.DBMS.DbTaskGet(taskId)
if err != nil {
return fmt.Errorf("task %v not found", taskId)
}
_ = tm.ts.DBMS.DbTaskDelete(task.TaskId, "")
packet := CreateSpAgentTaskRemove(task)
tm.ts.TsSyncAllClients(packet)
return nil
}
func (tm *TaskManager) Save(taskData adaptix.TaskData) error {
agent, err := tm.getAgent(taskData.AgentId)
if err != nil {
return err
}
agentData := agent.GetData()
taskData.Type = adaptix.TASK_TYPE_TASK
taskData.TaskId, _ = krypt.GenerateUID(8)
taskData.Computer = agentData.Computer
taskData.User = agentData.Username
taskData.StartDate = time.Now().Unix()
taskData.FinishDate = taskData.StartDate
taskData.Sync = true
taskData.Completed = true
packet_task := CreateSpAgentTaskSync(taskData)
tm.ts.TsSyncAllClients(packet_task)
_ = tm.ts.DBMS.DbTaskInsert(taskData)
return nil
}
func (tm *TaskManager) ProcessDisconnectedClient(clientName string) {
tm.ts.Agents.ForEach(func(agentId string, agentValue interface{}) bool {
agent, ok := agentValue.(*Agent)
if !ok {
return true
}
var tasksToProcess []string
agent.RunningTasks.ForEach(func(taskId string, taskValue interface{}) bool {
task, ok := taskValue.(adaptix.TaskData)
if !ok {
return true
}
if task.HookId != "" && task.Client == clientName {
tasksToProcess = append(tasksToProcess, taskId)
return true
}
if task.Type == adaptix.TASK_TYPE_TUNNEL && task.Client == clientName {
clientHostedTunnel := false
tm.ts.TunnelManager.ForEachTunnel(func(_ string, tunnel *Tunnel) bool {
if tunnel != nil && tunnel.TaskId == task.TaskId && tunnel.Data.Client == clientName {
clientHostedTunnel = true
return false
}
return true
})
if clientHostedTunnel {
tasksToProcess = append(tasksToProcess, taskId)
}
}
return true
})
for _, taskId := range tasksToProcess {
value, ok := agent.RunningTasks.Get(taskId)
if !ok {
continue
}
task, ok := value.(adaptix.TaskData)
if !ok {
continue
}
handler, ok := tm.handlers[task.Type]
if !ok {
continue
}
handler.OnClientDisconnect(tm, agent, &task, clientName)
}
return true
})
}
func (tm *TaskManager) RunningExists(agentId string, taskId string) bool {
agent, err := tm.getAgent(agentId)
if err != nil {
return false
}
return agent.RunningTasks.Contains(taskId)
}