Skip to content

Conversation

@terrorbyte
Copy link
Collaborator

@terrorbyte terrorbyte commented Oct 10, 2025

This adds support for adding explicit payload support to an exploit. This provides a few things:

  • Bring Your Own Payload (BYOP). Long awaited ability to support user provided payloads.
  • Payload type defined automatic flags
  • Ability to modify exploit flow for corner cases in specific implementation
  • Ability to change behavior for architecture
  • Exploit can define it's effects on the system and behavior that might allow flagging
  • Details output can now contain payload information and effect information

BYOP

Now when a payload adds support via config.AddPayload depending on the supported payloads. The file based (ELF, SO, .exe, .dll, webshell) types will add a -payload option that will automatically read a file from disk and add it to config.CustomPayload if the user uses the flag.

If the user uses one of the new payload.*Command types then -command flag will be available and config.CustomPayload will contain the value provided by that flag (or it can be accessed directly from the normal flag handling for the string type).

An example of how to define the code for this:

supportedPayload := []payload.Supported{
	{
		Types:   payload.GenericCommand,
		Arch:    payload.None,
		Effects: payload.NoEffects,
		Default: true,
	},
	{
		Types:   payload.LinuxELF,
		Arch:    payload.AMD64,
		Effects: payload.NoEffects,
	},
	{
		Types: payload.LinuxELF,
		Arch:  payload.ARM64,
		Effects: payload.Effects{
			payload.FileCreate: []string{"/var/www/html/pwnt", "/var/www/html/pwnt2"},
		},
	},
}
conf := config.NewRemoteExploit(
	config.ImplementedFeatures{AssetDetection: true, VersionScanning: false, Exploitation: true},
	config.CodeExecution, supportedC2,
	"", []string{""},
	[]string{""}, "CVE-2023-28324", "HTTP", 80)
conf.AddPayload(supportedPayload[:]...)

Now when the exploit is run the following options can be seen:

...
  -command string
    	Command to use for the exploit, an empty string will use the exploit default.
...
  -payload string
    	Path to load custom payload from, an empty string will use the exploit default.
  -payload-arch string
    	Payload architecture to use based on supported archs: none, amd64, arm64 (default "none")
  -payload-type string
    	Payload type to use based on supported types: GenericCommand, LinuxELF, LinuxELF (default "GenericCommand")
...

If a payload is defined with only one architecture -payload-arch will not show up and if only one payload type is defined -payload-type will also disappear. For example:

supportedPayload := []payload.Supported{
	{
		Types:   payload.GenericCommand,
		Arch:    payload.None,
		Effects: payload.Effects{
			payload.FileCreate: []string{"/var/www/html/pwnt", "/var/www/html/pwnt2"},
		},
	},
}
conf := config.NewRemoteExploit(
	config.ImplementedFeatures{AssetDetection: true, VersionScanning: false, Exploitation: true},
	config.CodeExecution, supportedC2,
	"", []string{""},
	[]string{""}, "CVE-2023-28324", "HTTP", 80)
conf.AddPayload(supportedPayload[:]...)

will yield the following flags with none of the others:

...
  -command string
    	Command to use for the exploit, an empty string will use the exploit default.
...

The developer can then handle the specific cases:

if conf.HasCustomPayload() {
	if conf.SelectedPayload.Type.IsCommand() {
		output.PrintfStatus("using '%s' in place of default", string(conf.CustomPayload))
	} else {
		output.PrintfStatus("using binary len %d in place of default", len(string(conf.CustomPayload)))
	}
}

Or if there is a complex case where more specificity is required:

switch conf.SelectedPayload.Types {
case payload.GenericCommand:
	output.PrintfStatus("adding GenericCommand")
	if conf.HasCustomPayload() {
                // Handle payload, ie any encoding or exploit specific bad chars
		output.PrintfStatus("using '%s' in place of default", string(conf.CustomPayload))
	}
        // Handle the normal default case
case payload.LinuxELF:
	output.PrintfStatus("adding LinuxELF")
	if conf.HasCustomPayload() {
                // Handle payload, ie any encoding or exploit specific bad chars
		output.PrintfStatus("using binary len %d in place of default", len(string(conf.CustomPayload)))
	}
        // Handle the normal default case
}

Payload and Exploit Effects

You can now define payload effects. The above example adds a list of payload effects if the default payload is used. An example of how this is now available in the details listing from the above example:

poptart:~/src/work/payload-test $ go run byop/byop.go -details
time=2025-10-10T10:38:43.694-06:00 level=SUCCESS msg="Implementation Details" ExploitType=CodeExecution AssetDetection=true VersionScanner=false Exploitation=true SupportedC2=[SimpleShellServer] SupportedPayloads="[GenericCommand (none): Effects -  LinuxELF (amd64): Effects -  LinuxELF (arm64): Effects - (FileCreate: /var/www/html/pwnt, /var/www/html/pwnt2)]" Vendor="" Products=[] CPE=[] CVE=CVE-2023-28324 Protocol=HTTP DefaultPort=80 CustomFlags="[{Name:command Type:string Default:} {Name:payload Type:string Default:} {Name:payload-type Type:string Default:GenericCommand} {Name:payload-arch Type:string Default:none}]"

This is part of #434

Undraft requirements:

  • - Add more docs and examples
  • - Separate out some of the logic to make it less complex in a single function
  • - Add tests
  • - Make the Effects string format better

@terrorbyte terrorbyte self-assigned this Oct 10, 2025
@terrorbyte terrorbyte added enhancement New feature or request proposal go Pull requests that update go code labels Oct 10, 2025
@terrorbyte terrorbyte force-pushed the feature/payload-types branch from ba81611 to c1c00eb Compare October 10, 2025 16:47
@terrorbyte terrorbyte force-pushed the feature/payload-types branch from 47a44c9 to 3f707e1 Compare October 30, 2025 21:47
@terrorbyte terrorbyte marked this pull request as ready for review October 30, 2025 21:55
@terrorbyte
Copy link
Collaborator Author

I'd like some comments on the effects strings formats as those feel very wrong. Something I considered was even turning them directly into JSON, which is nasty but a known format.

@terrorbyte
Copy link
Collaborator Author

I don't like nested JSON documents, but I think I've decided that that format is more reasonable than me reinventing one.

@terrorbyte
Copy link
Collaborator Author

This is a bit more reasonable:

time=2025-12-02T13:34:39.046-07:00 level=SUCCESS msg="Implementation Details" ExploitType=CodeExecution AssetDetection=true VersionScanner=false Exploitation=true SupportedC2=[SimpleShellServer] SupportedPayloads="[GenericCommand (none) - Effects: {} LinuxELF (amd64) - Effects: {} LinuxELF (arm64) - Effects: {\"FileCreate\":[\"/var/www/html/pwnt\",\"/var/www/html/pwnt2\"]}]" Vendor="" Products=[] CPE=[] CVE=CVE-2023-28324 Protocol=HTTP DefaultPort=1337 CustomFlags="[{Name:command Type:string Default:} {Name:payload Type:string Default:} {Name:payload-type Type:string Default:GenericCommand} {Name:payload-arch Type:string Default:none}]"

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a comprehensive payload support system that enables exploits to define supported payload types, architectures, and effects. It establishes a "Bring Your Own Payload" (BYOP) capability allowing users to provide custom commands or binary payloads through new command-line flags.

Key changes include:

  • New payload package defining types, architectures, and effects for payload metadata
  • Automatic generation of -command and -payload flags based on supported payload types
  • Integration of payload selection logic into the framework's command-line parsing
  • Enhanced details output showing supported payloads and their effects

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
payload/payload.go Core payload type system defining Type, Arch, Effect enums and conversion functions
payload/payload_test.go Test coverage for payload type and architecture string conversions
config/config.go Config struct extensions for payload support and AddPayload/HasCustomPayload methods
cli/commandline.go Command-line flag generation logic for payload types and architectures
framework.go Payload metadata processing from command-line flags
c2/channel/channel.go Documentation formatting fixes
dotnet/dotnetgadget.go Documentation formatting fix
payload/dropper/unix.go Documentation formatting fix
payload/reverse/bash.go Whitespace formatting

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@terrorbyte terrorbyte merged commit 9362a98 into main Dec 5, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request go Pull requests that update go code proposal

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants