-
Notifications
You must be signed in to change notification settings - Fork 1
Listeners
All listener implementations live in teamserver/pkg/handlers/. Constants (types.go):
LISTENER_HTTP = 1
LISTENER_PIVOT_SMB = 2
LISTENER_EXTERNAL = 3
LISTENER_SERVICE = 4
AGENT_HTTPS = "Https"
AGENT_HTTP = "Http"
AGENT_EXTERNAL = "External"
AGENT_PIVOT_SMB = "Smb"-
Start()registersPOST /*endpoint(agent requests) andGET /*endpoint(fake 404) on a dedicated gin engine and serves it onGetInterfaceIpv4Addr(HostBind) + ":" + PortBind. - If
Secureis set, a self-signed RSA cert is generated for the bind IP (stored underdata/loot/<ts>/listener/<Name>/server.crt|.key) unless the profile suppliesCert.Cert/Cert.Key; served withListenAndServeTLS. -
request(ctx):- Reads the POST body.
- Determines the agent's external IP (
X-Forwarded-ForwhenTrustXForwardedFor, elseRemoteAddr). WithTrustXForwardedFor, lenientBehindRedirparsing is enabled: multi-hopX-Forwarded-Forchains left by redirector relays are handled (http.go:105-116). - Validates the profile's
Headers(case-insensitive, ignoringConnection/Accept-Encoding),Uris,UserAgent, and, ifHostHeaderis configured, the request'sHost/X-Forwarded-Host. Any mismatch → fake nginx 404 page (handlers/404.html, setsX-Havoc: true). - Applies
Response.Headers, callsparseAgentRequest(...), and writes the returned raw bytes as the response body.
-
Only
POSTbuilds: requesting an HTTP listener payload withMethod = "get"fails at build time with"GET method is not supported"(teamserver/pkg/common/builder/builder.go:914-917). -
Hostsentries may behost:portpairs; the per-host port overridesPortConnfor that callback host (builder.go:932-952). -
Stop()does a gracefulhttp.Server.Shutdown(5s timeout).
The SMB listener opens no socket on the teamserver. It is a named-pipe pivot channel through an existing agent (SMBConfig{ Name, PipeName, KillDate, WorkingHours }). Start() only logs and emits the ListenerAdd event. Pivot tasking is encoded via COMMAND_PIVOT (2520) / DEMON_PIVOT_SMB_* sub-commands and links are persisted in the TS_Links table. This channel is Demon-only.
ExternalConfig{ Name, Endpoint }. ListenerStart wires an Endpoint{ Endpoint, Function: ExtConfig.Request } into the teamserver's gin engine (POST /<Endpoint>). Request behaves like the HTTP handler minus the header/URI/user-agent validation: the body goes straight into parseAgentRequest, so external C2 integrations can shape traffic however they like.
External listeners can be created two ways:
- Statically via the profile (
Listeners.External { Name, Endpoint }). - Dynamically through the Service API (
Listener/ListenerAddExC2), used by third-party controllers; see Service API Reference.
parseAgentRequest(Teamserver, Body, ExternalIP) (bytes.Buffer, bool) is the single funnel for all implant traffic:
-
agent.ParseHeader(Body)→Header{ Size, MagicValue, AgentID, Data }(12-byte big-endian header + body). -
MagicValue == 0xDEADBEEF→handleDemonAgent(Demon crypto + job dispatch). - Otherwise →
handleServiceAgent: look up the registered third-party agent by magic value (ServiceAgentExist/ServiceAgent) and forward the body to its controller (the Service API connection that registered it); the controller's reply becomes the HTTP response.