Skip to content
This repository was archived by the owner on Oct 22, 2020. It is now read-only.

Introduction to writing payloads

Rob edited this page Jan 24, 2016 · 2 revisions

What are payloads?

Exploit modules support (and require) the use of payloads to function. A payload, in WPXF, is simply the arbitrary PHP code that we intend to run on the target system via the vulnerability that the module exploits.

Naming a payload

The naming scheme for payloads is the same as the Module Naming Scheme, except they always appear in the Wpxf::Payloads namespace.

Example payload

The below example illustrates how to register an option and use it when generating the payload.

module Wpxf::Payloads
  class YourPayload < Wpxf::Payload
    include Wpxf
    include Wpxf::Options

    def initialize
      super

      register_options([
        StringOption.new(
          name: 'greeting',
          desc: 'A greeting to display',
          required: true,
          default: 'Hello, world!',
        )
      ])
    end

    def greeting
      escape_single_quotes(datastore['greeting'])
    end

    def raw
      "echo '#{greeting}';"
    end
  end
end

When this payload is generated in WPXF, assuming encoding is disabled, the final PHP script would look like this (assuming the user didn't change the greeting option):

<?php echo 'Hello, world!'; ?>

Using random variable names

In most (if not all) of the existing payloads, the majority of variable names are generated randomly at runtime in order to make fingerprinting the payload more difficult. A helper method, generate_vars exists to aid in doing this, by accepting an array of keys and generating a random and unique variable name for each one and returning them in a hash.

If you want to contribute a payload to the project, it's encouraged you use this technique. An example can be seen below of how to do this:

module Wpxf::Payloads
  class YourPayload < Wpxf::Payload
    include Wpxf
    include Wpxf::Options

    def initialize
      super

      register_options([
        StringOption.new(
          name: 'greeting',
          desc: 'A greeting to display',
          required: true,
          default: 'Hello, world!',
        )
      ])
    end

    def greeting
      escape_single_quotes(datastore['greeting'])
    end

    def raw
      vars = generate_vars([:greeting])

      <<-END_OF_PHP_CODE
        $#{vars[:greeting]} = '#{greeting}'
        echo $#{vars[:greeting]};"
      END_OF_PHP_CODE
    end
  end
end

Checking for potential issues when loading a payload

In some cases, it may be a good idea to run checks when the user loads the payload to make sure that there are no conflicts or to simply provide information to the user about the payload. An example of this can be found in the bind_php payload:

def check(mod)
  if mod.get_option('proxy')
    mod.emit_warning 'The proxy option for this module is only used for '\
                     'HTTP connections and will NOT be used for the TCP '\
                     'connection that the payload establishes'
  end
end

As the TCP connection that is made via the payload does not go through the proxy set in the proxy option, we raise a warning to the user if there is a proxy option present in the module that the payload has been loaded into.

Pre and post exploit actions

In some scenarios, some preparation will be required to be taken before we execute the payload; such as starting a TCP server in the reverse_tcp payload.

To implement pre-exploit actions, override the prepare method in your payload and return true if the preparation was successful. This will be executed prior to Module#run being invoked.

By the same token, there may be resources associated with the payload that need to be cleaned up once we have finished running the module. To achieve this, override the post_exploit method and again return true if the cleanup was successful.

Clone this wiki locally