-
Notifications
You must be signed in to change notification settings - Fork 1
Payload Generation
Payloads are built by the teamserver's builder (teamserver/pkg/common/builder/builder.go) when a client sends a Gate/Stageless request (from the Payload dialog, or havoc.GeneratePayload() in Python). For Demon it compiles from source with MinGW; for service agents the request is forwarded to the agent's controller (see Service API Reference → AgentBuild).
Info keys: AgentType, Listener, Arch (x64/x86), Format, Config (JSON string of build options). Results come back as PayloadArray (base64) + FileName, or progress via MessageType/Message.
From builder.go:31:
| Value | Format | Notes |
|---|---|---|
| 1 | Windows Exe |
MainExe.c, -e WinMain -nostdlib -mwindows
|
| 2 | Windows Service Exe |
MainSvc.c, -DSVC_EXE, service name define |
| 3 | Windows Dll |
MainDll.c, -shared -e DllMain
|
| 4 | Windows Reflective Dll |
|
| 5 |
Windows Shellcode (raw binary) |
DLL compiled with -DSHELLCODE, then the payloads/Shellcode.x64.bin (or x86) loader stub is prepended; the stub reflectively loads the appended Demon DLL (KaynLdr-style) |
The builder copies the Demon sources to a temp dir and invokes x86_64-w64-mingw32-gcc / i686-w64-mingw32-gcc (plus nasm for src/asm/*.asm) with flags like -Os -fPIC -masm=intel -s --no-seh --gc-sections. Defines:
-
-DCONFIG_BYTES={...}: the serialized implant configuration (parsed byDemonConfig()at runtime) -
-DTRANSPORT_HTTPor-DTRANSPORT_SMB: transport selection -
-DDEBUGwhen the server runs with--debug-dev;-DSEND_LOGSwith--send-logs(implant streams debug logs over C2)
Keys sent by the Payload dialog (consumed around builder.go:691-727 and PatchConfig, builder.go:561). All four Injection keys are mandatory: the build errors if any is missing.
-
Sleep,Jitter: implant timing -
Sleep Technique:WaitForSingleObjectEx/Foliage/Ekko/Zilean→SLEEPOBF_NO_OBF 0/FOLIAGE 3/EKKO 1/ZILEAN 2(payloads/Demon/include/core/SleepObf.h:7-10) -
Sleep Jmp Gadget:jmp rax/jmp rbx(→SLEEPOBF_BYPASS_JMPRAX 1/SLEEPOBF_BYPASS_JMPRBX 2,SleepObf.h:12-14). Only honored when a real sleep-obfuscation technique (notWaitForSingleObjectEx) is selected; otherwise the option is ignored.⚠️ Known bug:jmp raxcurrently sets the technique constant instead of the bypass constant (builder.go:750-751), corrupting the sleep-obf technique. Usejmp rbxuntil fixed. -
Stack Duplication(bool): only honored when a real sleep-obf technique is selected; silently ignored otherwise -
Injection: an object with four required keys (builder.go:651-712):-
Alloc:"Win32"or"Native"/"Syscall"(memory allocation method) -
Execute:"Win32"or"Native"/"Syscall"(memory execution method) -
Spawn64: sacrificial x64 process path for spawn-and-inject -
Spawn32: sacrificial x86 process path - (APC injection exists in the implant header
inject/Inject.hbut is not selectable via the builder)
-
-
Amsi/Etw Patch: only non-default value is"Hardware breakpoints"(AMSIETW_PATCH_HWBP,builder.go:843-878); anything else means no patching. (There is noMemoryPatchoption.) -
Proxy Loading: value string as shown in the UI, e.g."None (LdrLoadDll)"/RtlRegisterWait/RtlCreateTimer/RtlQueueWorkItemvariants (builder.go:800) -
Service Name: for theWindows Service Exeformat only: the service display name injected as aSERVICE_NAMEdefine (charset-validated, random 6-char fallback;builder.go:622-640) - Proxy settings, kill date, working hours: copied from the chosen listener's config
After compilation, builder.Patch() applies the profile's Demon.Binary block (builder.go:513):
-
Binary.Header.MagicMz-x64/x86: replace the MZ magic bytes (hyphenated names) -
Binary.Header.ImageSize-x64/x86,CompileTime: PE header tweaks -
Binary.ReplaceStrings-x64/x86: string replacement lists (string laundering)
This is per-architecture, keyed by the requested Arch.