forked from HavocFramework/Havoc
-
Notifications
You must be signed in to change notification settings - Fork 1
Profile Reference
laptop tester edited this page Sep 6, 2026
·
2 revisions
The teamserver is configured with an HCL file (a vendored HCL fork called "yaotl", parsed via hclsimple.DecodeFile). Struct definitions: teamserver/pkg/profile/config.go. Examples: profiles/havoc.yaotl, profiles/http_smb.yaotl, data/havoc.yaotl.
Full annotated schema:
Teamserver { # → profile.ServerProfile
Host = "0.0.0.0" # operator-facing listen address (wss)
Port = 40056
Build { # → profile.BuildConfig (toolchain for payload builds)
Compiler64 = "data/x86_64-w64-mingw32-cross-gcc"
Compiler86 = "data/i686-w64-mingw32-cross-gcc"
Nasm = "/usr/bin/nasm"
} # path validation: Compiler64/Compiler86/Nasm are
# interpolated into the compile command and must only
# contain alnum, space, . - _ / \ : ; anything else
# fails the build (shell-injection hardening, #189)
}
Operators { # → profile.OperatorsBlock
user "Neo" { # block label = username
Password = "password1234" # compared as hex SHA3-256
}
user "trinity" {
Password = "password1234"
}
}
Demon { # → profile.Demon (see notes below; most fields are DEAD)
Sleep = 2 # DEAD: parsed but never consumed; per-payload from client only
Jitter = 15 # DEAD: parsed but never consumed
IndirectSyscall = true # DEAD: parsed but never consumed
StackDuplication = false # DEAD: parsed but never consumed
SleepTechnique = "WaitForSingleObjectEx" # DEAD: parsed but never consumed
ProxyLoading = "None" # DEAD: parsed but never consumed
AmsiEtwPatching = "None" # DEAD: parsed but never consumed
DotNetNamePipe = "\\\\.\\pipe\\mojo.5688.8052.18389493978708887773"
# USED: pipe name for the .NET (execute-assembly) mate pipe
TrustXForwardedFor = false # USED: take agent external IP from X-Forwarded-For
# (also enables BehindRedir lenient multi-hop parsing)
Injection { # DEAD: parsed but never consumed
Spawn64 = "C:\\Windows\\System32\\notepad.exe"
Spawn32 = "C:\\Windows\\SysWOW64\\notepad.exe"
}
Binary { # USED: post-build binary patching (applied to every Demon build)
Header {
MagicMz-x64 = "" # hyphenated names are the accepted syntax
MagicMz-x86 = ""
CompileTime = ""
ImageSize-x64 = ""
ImageSize-x86 = ""
}
ReplaceStrings-x64 = [] # string replacement pairs applied to the x64 payload
ReplaceStrings-x86 = [] # string replacement pairs applied to the x86 payload
}
}
Listeners { # → profile.Listeners
Http { # → profile.ListenerHTTP (repeatable)
Name = "Demon Listener"
KillDate = "2024-02-10 14:39:01" # optional; layout "2006-01-02 15:04:05"
WorkingHours = "" # optional
Hosts = ["0.0.0.0", "192.168.2.100"] # callback hosts the agent rotates through
HostBind = "0.0.0.0" # bind address
HostRotation = "round-robin" # or "random"
PortBind = 443
PortConn = 443 # optional; port the agent connects to
Method = "POST" # optional; only POST builds; GET is rejected at build time
UserAgent = "Mozilla/5.0 (...)" # optional
Headers = ["Content-type: */*"] # optional; requests must match
Uris = ["/index.php"] # optional
HostHeader = "www.example.com" # optional; requests whose Host / X-Forwarded-Host
# do not match receive the fake 404
Secure = true # optional; TLS listener
Cert { # optional; else self-signed cert is generated
Cert = "certs/server.crt"
Key = "certs/server.key"
}
Response { # optional; headers added to every response
Headers = ["Server: nginx/1.18.0 (Ubuntu)"]
}
Proxy { # optional; agent-side proxy config
Type = "http" # REQUIRED; "http" or "socks5"
Host = "..."
Port = "..."
Username = "" # optional
Password = "" # optional
}
}
Smb { # → profile.ListenerSMB (named-pipe pivot via an agent)
Name = "Smb listener"
PipeName = "mojo.5688.8052.1838949397870888777.806"
KillDate = "" # optional
WorkingHours = "" # optional
}
External { # → profile.ListenerExternal (ExternalC2 endpoint)
Name = "External Listener"
Endpoint = "endpoint" # exposed as POST /<Endpoint> on the teamserver
}
}
Service { # → profile.ServiceConfig (REQUIRED for third-party agents)
Endpoint = "service-endpoint" # wss://<Teamserver.Host>:<Port>/service-endpoint
Password = "service-password"
}
WebHook { # → profile.WebHookConfig
Discord {
Url = "https://discord.com/api/webhooks/..."
AvatarUrl = "" # optional
User = "" # optional
}
}Notes:
- All blocks except
ServiceandWebHookare effectively required for a normal setup;Demonfields are individually optional (defaults apply). -
KillDateis parsed with layout"2006-01-02 15:04:05"and converted to a Windows FILETIME-style epoch for the implant. -
The
Demonblock is mostly dead config. OnlyBinary(post-build patching),DotNetNamePipeandTrustXForwardedForare actually consumed by the teamserver.Sleep,Jitter,IndirectSyscall,StackDuplication,SleepTechnique,ProxyLoading,AmsiEtwPatchingandInjectionare parsed but never read; build options like sleep obfuscation, AMSI/ETW patching and injection come exclusively from the client's payload-buildConfig(see Payload-Generation). - Multiple
Http/Smb/Externalblocks are allowed; each becomes one listener. -
Binary.Header/ReplaceStringsfield names are hyphenated (MagicMz-x64,ImageSize-x86,ReplaceStrings-x64, …); underscored variants do not parse. - Entries in
HostsandHostBindmay be network interface names (e.g.tun0) instead of IPs; the teamserver resolves them to the interface's first IPv4 address (common.GetInterfaceIpv4Addr,teamserver/pkg/common/util.go). - Entries in
Hostsmay also behost:portpairs; a per-host port overridesPortConnfor that callback host. - HTTP listener requests are validated against
Headers,Uris,UserAgentandHostHeader(if set:Host/X-Forwarded-Hostmust match); mismatches receive a fake nginx 404 (with anX-Havoc: trueheader; seeteamserver/pkg/handlers/404.html). - With
TrustXForwardedFor = true, the HTTP handler enables lenientBehindRedirparsing: multi-hopX-Forwarded-Forchains from redirector relays are handled (teamserver/pkg/handlers/http.go).