package server import ( "encoding/json" "errors" "fmt" "strconv" "strings" "time" "Havoc/pkg/agent" "Havoc/pkg/common/builder" "Havoc/pkg/events" "Havoc/pkg/handlers" "Havoc/pkg/logger" "Havoc/pkg/logr" "Havoc/pkg/packager" ) func (t *Teamserver) DispatchEvent(pk packager.Package) { switch pk.Head.Event { case packager.Type.Session.Type: switch pk.Body.SubEvent { case packager.Type.Session.MarkAsDead: if AgentID, ok := pk.Body.Info["AgentID"]; ok { for i := range t.Agents.Agents { if t.Agents.Agents[i].NameID == AgentID { if val, ok := pk.Body.Info["Marked"]; ok { if val == "Dead" { t.Died(t.Agents.Agents[i]) } else if val == "Alive" { t.Agents.Agents[i].Active = true } t.AgentUpdate(t.Agents.Agents[i]) } } } } break case packager.Type.Session.Input: var ( job *agent.Job command = 0 AgentType = "Demon" err error DemonID string found = false ) if agentID, ok := pk.Body.Info["DemonID"].(string); ok { DemonID = agentID } else { logger.Debug("AgentID [" + agentID + "] not found") return } for i := range t.Agents.Agents { if t.Agents.Agents[i].NameID == DemonID { found = true // handle demon session input // TODO: maybe move to own function ? if t.Agents.Agents[i].Info.MagicValue == agent.DEMON_MAGIC_VALUE { var ( Message = new(map[string]string) Console = func(AgentID string, Message map[string]string) { var ( out, _ = json.Marshal(Message) pk = events.Demons.DemonOutput(DemonID, agent.HAVOC_CONSOLE_MESSAGE, string(out)) ) t.EventAppend(pk) t.EventBroadcast("", pk) } ) if val, ok := pk.Body.Info["CommandID"]; ok { if pk.Body.Info["CommandID"] == "Python Plugin" { // TODO: move to own function. logr.LogrInstance.AddAgentInput("Demon", pk.Body.Info["DemonID"].(string), pk.Head.User, pk.Body.Info["TaskID"].(string), pk.Body.Info["CommandLine"].(string), time.Now().UTC().Format("02/01/2006 15:04:05")) if pk.Head.OneTime == "true" { return } var backups = map[string]interface{}{ "TaskID": pk.Body.Info["TaskID"].(string), "DemonID": DemonID, "CommandID": "", "CommandLine": pk.Body.Info["CommandLine"].(string), "AgentType": AgentType, } if _, ok := pk.Body.Info["CommandID"].(string); ok { backups["CommandID"] = pk.Body.Info["CommandID"] } if _, ok := pk.Body.Info["TaskMessage"].(string); ok { backups["TaskMessage"] = pk.Body.Info["TaskMessage"] } for k := range pk.Body.Info { delete(pk.Body.Info, k) } pk.Body.Info = backups t.EventAppend(pk) t.EventBroadcast(pk.Head.User, pk) return } else if pk.Body.Info["CommandID"] == "Teamserver" { // TODO: move to own function. logr.LogrInstance.AddAgentInput("Demon", pk.Body.Info["DemonID"].(string), pk.Head.User, pk.Body.Info["TaskID"].(string), pk.Body.Info["CommandLine"].(string), time.Now().UTC().Format("02/01/2006 15:04:05")) var Command = pk.Body.Info["Command"].(string) if pk.Head.OneTime == "true" { return } var backups = map[string]interface{}{ "TaskID": pk.Body.Info["TaskID"].(string), "DemonID": DemonID, "CommandID": "", "CommandLine": pk.Body.Info["CommandLine"].(string), "AgentType": AgentType, } if _, ok := pk.Body.Info["CommandID"].(string); ok { backups["CommandID"] = pk.Body.Info["CommandID"] } for k := range pk.Body.Info { delete(pk.Body.Info, k) } pk.Body.Info = backups t.EventAppend(pk) t.EventBroadcast(pk.Head.User, pk) if err = t.Agents.Agents[i].TeamserverTaskPrepare(Command, Console); err != nil { Console(t.Agents.Agents[i].NameID, map[string]string{ "Type": "Error", "Message": "Failed to create Task: " + err.Error(), }) return } return } else { // TODO: move to own function. command, err = strconv.Atoi(val.(string)) if err != nil { logger.Error("Failed to convert CommandID to integer: " + err.Error()) command = 0 } else { *Message = make(map[string]string) var ClientID string ClientID = "" t.Clients.Range(func(key, value any) bool { client := value.(*Client) if client.Username == pk.Head.User { ClientID = client.ClientID return false } return true }) job, err = t.Agents.Agents[i].TaskPrepare(command, pk.Body.Info, Message, ClientID, t) if err != nil { Console(t.Agents.Agents[i].NameID, map[string]string{ "Type": "Error", "Message": "Failed to create Task: " + err.Error(), }) return } if job != nil { t.Agents.Agents[i].AddJobToQueue(*job) } if t.Agents.Agents[i].Pivots.Parent != nil { logr.LogrInstance.AddAgentInput("Demon", t.Agents.Agents[i].NameID, pk.Head.User, pk.Body.Info["TaskID"].(string), pk.Body.Info["CommandLine"].(string), time.Now().UTC().Format("02/01/2006 15:04:05")) } else { logr.LogrInstance.AddAgentInput("Demon", pk.Body.Info["DemonID"].(string), pk.Head.User, pk.Body.Info["TaskID"].(string), pk.Body.Info["CommandLine"].(string), time.Now().UTC().Format("02/01/2006 15:04:05")) } if pk.Head.OneTime == "true" { return } var backups = map[string]interface{}{ "TaskID": pk.Body.Info["TaskID"].(string), "DemonID": DemonID, "CommandID": "", "CommandLine": pk.Body.Info["CommandLine"].(string), "AgentType": AgentType, } if _, ok := pk.Body.Info["CommandID"].(string); ok { backups["CommandID"] = pk.Body.Info["CommandID"] } for k := range pk.Body.Info { delete(pk.Body.Info, k) } pk.Body.Info = backups t.EventAppend(pk) t.EventBroadcast(pk.Head.User, pk) if Message != nil { Console(t.Agents.Agents[i].NameID, *Message) } return } } } } else { for _, a := range t.Service.Agents { if a.MagicValue == fmt.Sprintf("0x%x", t.Agents.Agents[i].Info.MagicValue) { // Set agent type AgentType = a.Name if pk.Body.Info["CommandID"] == "Python Plugin" { logr.LogrInstance.AddAgentInput(AgentType, pk.Body.Info["DemonID"].(string), pk.Head.User, pk.Body.Info["TaskID"].(string), pk.Body.Info["CommandLine"].(string), time.Now().UTC().Format("02/01/2006 15:04:05")) if pk.Head.OneTime == "true" { return } var backups = map[string]interface{}{ "TaskID": pk.Body.Info["TaskID"].(string), "DemonID": DemonID, "CommandID": "", "CommandLine": pk.Body.Info["CommandLine"].(string), "AgentType": AgentType, } if _, ok := pk.Body.Info["CommandID"].(string); ok { backups["CommandID"] = pk.Body.Info["CommandID"] } if _, ok := pk.Body.Info["TaskMessage"].(string); ok { backups["TaskMessage"] = pk.Body.Info["TaskMessage"] } for k := range pk.Body.Info { delete(pk.Body.Info, k) } pk.Body.Info = backups t.EventAppend(pk) t.EventBroadcast(pk.Head.User, pk) return } else { // Send command to agent service a.SendTask(pk.Body.Info, t.Agents.Agents[i].ToMap()) // log agent input logr.LogrInstance.AddAgentInput(a.Name, pk.Body.Info["DemonID"].(string), pk.Head.User, pk.Body.Info["TaskID"].(string), pk.Body.Info["CommandLine"].(string), time.Now().UTC().Format("02/01/2006 15:04:05")) } } } } break } } if found == false { logger.Error(fmt.Sprintf("The AgentID %s was not found", DemonID)) return } if pk.Head.OneTime == "true" { return } var backups = map[string]interface{}{ "TaskID": pk.Body.Info["TaskID"].(string), "DemonID": DemonID, "CommandID": "", "CommandLine": pk.Body.Info["CommandLine"].(string), "AgentType": AgentType, } if _, ok := pk.Body.Info["CommandID"].(string); ok { backups["CommandID"] = pk.Body.Info["CommandID"] } for k := range pk.Body.Info { delete(pk.Body.Info, k) } pk.Body.Info = backups t.EventAppend(pk) t.EventBroadcast(pk.Head.User, pk) } case packager.Type.Chat.Type: switch pk.Body.SubEvent { case packager.Type.Chat.NewMessage: t.EventBroadcast("", pk) break case packager.Type.Chat.NewSession: t.EventBroadcast("", pk) break case packager.Type.Chat.NewListener: t.EventBroadcast("", pk) break } case packager.Type.Listener.Type: switch pk.Body.SubEvent { case packager.Type.Listener.Add: var Protocol = pk.Body.Info["Protocol"].(string) switch Protocol { case handlers.AGENT_HTTP, handlers.AGENT_HTTPS: var ( HostBind string Hosts []string Headers []string Uris []string ) HostBind = pk.Body.Info["HostBind"].(string) for _, s := range strings.Split(pk.Body.Info["Hosts"].(string), ", ") { if len(s) > 0 { Hosts = append(Hosts, s) } } for _, s := range strings.Split(pk.Body.Info["Headers"].(string), "\r\n") { if len(s) > 0 { Headers = append(Headers, s) } } for _, s := range strings.Split(pk.Body.Info["Uris"].(string), ", ") { if len(s) > 0 { Uris = append(Uris, s) } } var Config = handlers.HTTPConfig{ Name: pk.Body.Info["Name"].(string), Hosts: Hosts, HostBind: HostBind, HostRotation: pk.Body.Info["HostRotation"].(string), PortBind: pk.Body.Info["PortBind"].(string), PortConn: pk.Body.Info["PortConn"].(string), Headers: Headers, Uris: Uris, HostHeader: pk.Body.Info["HostHeader"].(string), UserAgent: pk.Body.Info["UserAgent"].(string), BehindRedir: t.Profile.Config.Demon.TrustXForwardedFor, } if val, ok := pk.Body.Info["Proxy Enabled"].(string); ok { Config.Proxy.Enabled = false if val == "true" { Config.Proxy.Enabled = true if val, ok = pk.Body.Info["Proxy Type"].(string); ok { Config.Proxy.Type = val } else { t.Clients.Range(func(key, value any) bool { id := key.(string) client := value.(*Client) if client.Username == pk.Head.User { err := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info["Name"].(string), errors.New("proxy type not specified"))) if err != nil { logger.Error("Failed to send Event: " + err.Error()) } return false } return true }) } if val, ok = pk.Body.Info["Proxy Host"].(string); ok { Config.Proxy.Host = val } else { t.Clients.Range(func(key, value any) bool { id := key.(string) client := value.(*Client) if client.Username == pk.Head.User { err := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info["Name"].(string), errors.New("proxy host not specified"))) if err != nil { logger.Error("Failed to send Event: " + err.Error()) } return false } return true }) } if val, ok = pk.Body.Info["Proxy Port"].(string); ok { Config.Proxy.Port = val } else { t.Clients.Range(func(key, value any) bool { id := key.(string) client := value.(*Client) if client.Username == pk.Head.User { err := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info["Name"].(string), errors.New("proxy port not specified"))) if err != nil { logger.Error("Failed to send Event: " + err.Error()) } return false } return true }) return } if val, ok = pk.Body.Info["Proxy Username"].(string); ok { Config.Proxy.Username = val } else { t.Clients.Range(func(key, value any) bool { id := key.(string) client := value.(*Client) if client.Username == pk.Head.User { err := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info["Name"].(string), errors.New("proxy username not specified"))) if err != nil { logger.Error("Failed to send Event: " + err.Error()) } return false } return true }) return } if val, ok = pk.Body.Info["Proxy Password"].(string); ok { Config.Proxy.Password = val } else { t.Clients.Range(func(key, value any) bool { id := key.(string) client := value.(*Client) if client.Username == pk.Head.User { err := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info["Name"].(string), errors.New("proxy password not specified"))) if err != nil { logger.Error("Failed to send Event: " + err.Error()) } return false } return true }) return } } } if pk.Body.Info["Secure"].(string) == "true" { Config.Secure = true } if err := t.ListenerStart(handlers.LISTENER_HTTP, Config); err != nil { t.Clients.Range(func(key, value any) bool { id := key.(string) client := value.(*Client) if client.Username == pk.Head.User { err := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info["Name"].(string), err)) if err != nil { logger.Error("Failed to send Event: " + err.Error()) } return false } return true }) } break case handlers.AGENT_PIVOT_SMB: var ( SmdConfig handlers.SMBConfig found bool ) SmdConfig.Name, found = pk.Body.Info["Name"].(string) if !found { SmdConfig.Name = "" } SmdConfig.PipeName, found = pk.Body.Info["PipeName"].(string) if !found { SmdConfig.Name = "" } if err := t.ListenerStart(handlers.LISTENER_PIVOT_SMB, SmdConfig); err != nil { t.Clients.Range(func(key, value any) bool { id := key.(string) client := value.(*Client) if client.Username == pk.Head.User { err := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info["Name"].(string), err)) if err != nil { logger.Error("Failed to send Event: " + err.Error()) } return false } return true }) } break case handlers.AGENT_EXTERNAL: var ( ExtConfig handlers.ExternalConfig found bool ) ExtConfig.Name, found = pk.Body.Info["Name"].(string) if !found { ExtConfig.Name = "" } ExtConfig.Endpoint, found = pk.Body.Info["Endpoint"].(string) if !found { logger.Error("Listener SMB Pivot: Endpoint not specified") return } if err := t.ListenerStart(handlers.LISTENER_EXTERNAL, ExtConfig); err != nil { t.Clients.Range(func(key, value any) bool { id := key.(string) client := value.(*Client) if client.Username == pk.Head.User { err := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info["Name"].(string), err)) if err != nil { logger.Error("Failed to send Event: " + err.Error()) } return false } return true }) } break default: // check if the service endpoint is up and available if t.Service != nil { for _, listener := range t.Service.Listeners { if Protocol == listener.Name { var ( ListenerName string err error ) // retrieve the listener name if val, ok := pk.Body.Info["Name"]; ok { ListenerName = val.(string) } // try to start the listener. if err = listener.Start(pk.Body.Info); err != nil { t.EventListenerError(ListenerName, err) } // append the listener to the teamserver listener array t.Listeners = append(t.Listeners, &Listener{ Name: ListenerName, Type: handlers.LISTENER_SERVICE, Config: handlers.Service{ Service: listener, Info: pk.Body.Info, }, }) // break from this switch return } } } // didn't found the protocol type so just abort logger.Error("Listener Type not found: ", Protocol) break } break case packager.Type.Listener.Remove: if val, ok := pk.Body.Info["Name"]; ok { t.ListenerRemove(val.(string)) var p = events.Listener.ListenerRemove(val.(string)) t.EventAppend(p) t.EventBroadcast("", p) } break case packager.Type.Listener.Edit: var Protocol = pk.Body.Info["Protocol"].(string) switch Protocol { case handlers.AGENT_HTTP, handlers.AGENT_HTTPS: var ( HostBind string Hosts []string Headers []string Uris []string ) HostBind = pk.Body.Info["HostBind"].(string) for _, s := range strings.Split(pk.Body.Info["Hosts"].(string), ", ") { if len(s) > 0 { Hosts = append(Hosts, s) } } for _, s := range strings.Split(pk.Body.Info["Headers"].(string), "\r\n") { if len(s) > 0 { Headers = append(Headers, s) } } for _, s := range strings.Split(pk.Body.Info["Uris"].(string), ", ") { if len(s) > 0 { Uris = append(Uris, s) } } var Config = handlers.HTTPConfig{ Name: pk.Body.Info["Name"].(string), Hosts: Hosts, HostBind: HostBind, HostRotation: pk.Body.Info["HostRotation"].(string), PortBind: pk.Body.Info["PortBind"].(string), PortConn: pk.Body.Info["PortConn"].(string), Headers: Headers, Uris: Uris, HostHeader: pk.Body.Info["HostHeader"].(string), UserAgent: pk.Body.Info["UserAgent"].(string), } if val, ok := pk.Body.Info["Proxy Enabled"].(string); ok { Config.Proxy.Enabled = false if val == "true" { Config.Proxy.Enabled = true if val, ok = pk.Body.Info["Proxy Type"].(string); ok { Config.Proxy.Type = val } else { t.Clients.Range(func(key, value any) bool { id := key.(string) client := value.(*Client) if client.Username == pk.Head.User { err := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info["Name"].(string), errors.New("proxy type not specified"))) if err != nil { logger.Error("Failed to send Event: " + err.Error()) } return false } return true }) } if val, ok = pk.Body.Info["Proxy Host"].(string); ok { Config.Proxy.Host = val } else { t.Clients.Range(func(key, value any) bool { id := key.(string) client := value.(*Client) if client.Username == pk.Head.User { err := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info["Name"].(string), errors.New("proxy host not specified"))) if err != nil { logger.Error("Failed to send Event: " + err.Error()) } return false } return true }) } if val, ok = pk.Body.Info["Proxy Port"].(string); ok { Config.Proxy.Port = val } else { t.Clients.Range(func(key, value any) bool { id := key.(string) client := value.(*Client) if client.Username == pk.Head.User { err := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info["Name"].(string), errors.New("proxy port not specified"))) if err != nil { logger.Error("Failed to send Event: " + err.Error()) } return false } return true }) return } if val, ok = pk.Body.Info["Proxy Username"].(string); ok { Config.Proxy.Username = val } else { t.Clients.Range(func(key, value any) bool { id := key.(string) client := value.(*Client) if client.Username == pk.Head.User { err := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info["Name"].(string), errors.New("proxy username not specified"))) if err != nil { logger.Error("Failed to send Event: " + err.Error()) } return false } return true }) return } if val, ok = pk.Body.Info["Proxy Password"].(string); ok { Config.Proxy.Password = val } else { t.Clients.Range(func(key, value any) bool { id := key.(string) client := value.(*Client) if client.Username == pk.Head.User { err := t.SendEvent(id, events.Listener.ListenerError(pk.Head.User, pk.Body.Info["Name"].(string), errors.New("proxy password not specified"))) if err != nil { logger.Error("Failed to send Event: " + err.Error()) } return false } return true }) return } } } if pk.Body.Info["Secure"].(string) == "true" { Config.Secure = true } t.ListenerEdit(handlers.LISTENER_HTTP, Config) var p = events.Listener.ListenerEdit(handlers.LISTENER_HTTP, &Config) t.EventAppend(p) t.EventBroadcast("", p) break } break } case packager.Type.Gate.Type: switch pk.Body.SubEvent { case packager.Type.Gate.Stageless: var ( AgentType = pk.Body.Info["AgentType"].(string) ListenerName = pk.Body.Info["Listener"].(string) Arch = pk.Body.Info["Arch"].(string) Format = pk.Body.Info["Format"].(string) Config = pk.Body.Info["Config"].(string) SendConsoleMsg func(MsgType, Message string) ClientID string ) t.Clients.Range(func(key, value any) bool { Client := value.(*Client) if Client.Username == pk.Head.User { ClientID = Client.ClientID return false } return true }) SendConsoleMsg = func(MsgType, Message string) { err := t.SendEvent(ClientID, events.Gate.SendConsoleMessage(MsgType, Message)) if err != nil { logger.Error("Couldn't send Event: " + err.Error()) return } } if AgentType == "Demon" { go func() { var ConfigMap = make(map[string]any) err := json.Unmarshal([]byte(Config), &ConfigMap) if err != nil { logger.Error("Failed to Unmarshal json to object: " + err.Error()) return } var PayloadBuilder = builder.NewBuilder(builder.BuilderConfig{ Compiler64: t.Settings.Compiler64, Compiler86: t.Settings.Compiler32, Nasm: t.Settings.Nasm, DebugDev: t.Flags.Server.DebugDev, SendLogs: t.Flags.Server.SendLogs, }) PayloadBuilder.ClientId = ClientID if PayloadBuilder.ClientId == "" { logger.Error("Couldn't find the Client") return } PayloadBuilder.SendConsoleMessage = SendConsoleMsg err = PayloadBuilder.SetConfig(Config) if err != nil { return } if Arch == "x64" { PayloadBuilder.SetArch(builder.ARCHITECTURE_X64) } else { PayloadBuilder.SetArch(builder.ARCHITECTURE_X86) } var Ext string if Arch == "x64" { Ext = ".x64" } else { Ext = ".x86" } logger.Debug(Format) if Format == "Windows Exe" { PayloadBuilder.SetFormat(builder.FILETYPE_WINDOWS_EXE) Ext += ".exe" } else if Format == "Windows Service Exe" { PayloadBuilder.SetFormat(builder.FILETYPE_WINDOWS_SERVICE_EXE) Ext += ".exe" } else if Format == "Windows Dll" { PayloadBuilder.SetFormat(builder.FILETYPE_WINDOWS_DLL) Ext += ".dll" } else if Format == "Windows Reflective Dll" { PayloadBuilder.SetFormat(builder.FILETYPE_WINDOWS_REFLECTIVE_DLL) Ext += ".dll" } else if Format == "Windows Shellcode" { PayloadBuilder.SetFormat(builder.FILETYPE_WINDOWS_RAW_BINARY) Ext += ".bin" } else { logger.Error("Unknown Format: " + Format) return } for i := 0; i < len(t.Listeners); i++ { if t.Listeners[i].Name == ListenerName { PayloadBuilder.SetListener(t.Listeners[i].Type, t.Listeners[i].Config) } } PayloadBuilder.SetExtension(Ext) if t.Profile.Config.Demon != nil && t.Profile.Config.Demon.Binary != nil { PayloadBuilder.SetPatchConfig(t.Profile.Config.Demon.Binary) } if PayloadBuilder.Build() { pal := PayloadBuilder.GetPayloadBytes() if len(pal) > 0 { err := t.SendEvent(PayloadBuilder.ClientId, events.Gate.SendStageless("demon"+Ext, pal)) if err != nil { logger.Error("Error while sending event: " + err.Error()) return } PayloadBuilder.DeletePayload() } } }() } else { // send to Services for _, Agent := range t.Service.Agents { if Agent.Name == AgentType { var ConfigMap = make(map[string]any) err := json.Unmarshal([]byte(Config), &ConfigMap) if err != nil { logger.Error("Failed to Unmarshal json to object: " + err.Error()) SendConsoleMsg("Error", "Failed to Unmarshal json to object: "+err.Error()) return } var Options = map[string]any{ "Listener": t.ListenerGetInfo(ListenerName), "Arch": Arch, "Format": Format, } Agent.SendAgentBuildRequest(ClientID, ConfigMap, Options) } } } } } }