ronin-rb/ronin-exploits

View on GitHub
lib/ronin/exploits/cli/commands/new.rb

Summary

Maintainability
A
35 mins
Test Coverage
# frozen_string_literal: true
#
# ronin-exploits - A Ruby library for ronin-rb that provides exploitation and
# payload crafting functionality.
#
# Copyright (c) 2007-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
#
# ronin-exploits is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# ronin-exploits is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with ronin-exploits.  If not, see <https://www.gnu.org/licenses/>.
#

require 'ronin/exploits/cli/command'
require 'ronin/exploits/root'
require 'ronin/payloads/cli/generator/payload_types'
require 'ronin/core/cli/options/values/arches'
require 'ronin/core/cli/options/values/oses'
require 'ronin/core/cli/generator'
require 'ronin/core/cli/generator/options/author'
require 'ronin/core/cli/generator/options/summary'
require 'ronin/core/cli/generator/options/description'
require 'ronin/core/cli/generator/options/reference'

require 'command_kit/inflector'

module Ronin
  module Exploits
    class CLI
      module Commands
        #
        # Creates a new exploit file.
        #
        # ## Usage
        #
        #     ronin-exploit new [options] FILE
        #
        # ## Options
        #
        #     -t exploit|heap_overflow|stack_overflow|web|open_redirect|lfi|rfi|sqli|ssti|xss,
        #         --type                       The type for the new exploit
        #     -a, --author NAME                The name of the author
        #     -e, --author-email EMAIL         The email address of the author
        #     -s, --summary TEXT               One sentence summary
        #     -d, --description TEXT           A longer description
        #     -I CVE-YYYY-NNNN|GHSA-XXXXX|..., Add the advisory ID to the exploit
        #         --advisory-id
        #     -R, --reference URL              Adds a reference URL
        #     -P payload|asm|shellcode|c|command|shell|powershell|html|javascript|typpescript|java|sql|php|nodejs,
        #         --has-payload                The payload type the exploit uses
        #     -N remote_tcp|remote_udp|http,   The networking mixin to use
        #         --networking
        #     -A x86|x86-64|amd64|ia64|ppc|ppc64|arm|armbe|arm64|arm64be|mips|mipsle|mips64|mips64le,
        #         --arch                       The architecture to target
        #     -O linux|macos|windows|freebsd|openbsd|netbsd,
        #         --os                         The Operating System (OS) to target
        #         --os-version VERSION         The OS version to target
        #     -S, --software NAME              The software to target
        #     -V, --software-version ARCH      The software version to target
        #     -L, --loot                       Adds the loot mixin
        #     -h, --help                       Print help information
        #
        # ## Arguments
        #
        #     FILE                             The path to the new exploit file.
        #
        class New < Command

          include Core::CLI::Generator
          include Payloads::CLI::Generator

          # Mapping of exploit types and their file/class names.
          EXPLOIT_TYPES = {
            exploit: {
              file:  'exploit',
              class: 'Exploit'
            },

            heap_overflow: {
              file:  'heap_overflow',
              class: 'HeapOverflow'
            },

            stack_overflow: {
              file:  'stack_overflow',
              class: 'StackOverflow'
            },

            seh_overflow: {
              file:  'seh_overflow',
              class: 'SEHOverflow'
            },

            user_after_free: {
              file:  'use_after_free',
              class: 'UseAfterFree'
            },

            web: {
              file:  'web',
              class: 'Web'
            },

            lfi: {
              file:  'lfi',
              class: 'LFI'
            },

            rfi: {
              file:  'rfi',
              class: 'RFI'
            },

            sqli: {
              file:  'sqli',
              class: 'SQLI'
            },

            ssti: {
              file:  'ssti',
              class: 'SSTI'
            },

            xss: {
              file:  'xss',
              class: 'XSS'
            }
          }

          # Mapping of network mixins and their file/module names.
          NETWORKING_TYPES = {
            remote_tcp: {
              file:   'remote_tcp',
              module: 'RemoteTCP'
            },

            remote_udp: {
              file:   'remote_udp',
              module: 'RemoteUDP'
            },

            http: {
              file:   'http',
              module: 'HTTP'
            }
          }

          template_dir File.join(ROOT,'data','new')

          usage '[options] FILE'

          option :type, short: '-t',
                        value: {
                          type: EXPLOIT_TYPES.keys.compact
                        },
                        desc: 'The type for the new exploit' do |type|
                          @exploit_type = EXPLOIT_TYPES.fetch(type)
                        end

          include Core::CLI::Generator::Options::Author
          include Core::CLI::Generator::Options::Summary
          include Core::CLI::Generator::Options::Description

          option :advisory_id, short: '-I',
                               value: {
                                 type:  String,
                                 usage: 'CVE-YYYY-NNNN|GHSA-XXXXX|...'
                               },
                               desc: 'Add the advisory ID to the exploit' do |id|
                                 @advisories << id
                               end

          include Core::CLI::Generator::Options::Reference

          option :has_payload, short: '-P',
                               value: {type: PAYLOAD_TYPES.keys},
                               desc: 'The payload type the exploit uses' do |type|
                                 @has_payload = PAYLOAD_TYPES.fetch(type)
                               end

          option :networking, short: '-N',
                              value: {
                                type: NETWORKING_TYPES.keys
                              },
                              desc: 'The networking mixin to use' do |type|
                                @networking       = type
                                @networking_mixin = NETWORKING_TYPES.fetch(type)
                              end

          option :arch, short: '-A',
                        value: {
                          type: Core::CLI::Options::Values::ARCHES
                        },
                        desc: 'The architecture to target' do |arch|
                          # lazy initialize @target
                          @target ||= {}

                          @target[:arch] = arch
                        end

          option :os, short: '-O',
                      value: {
                        type: Core::CLI::Options::Values::OSES
                      },
                      desc: 'The Operating System (OS) to target' do |os|
                        # lazy initialize @target
                        @target ||= {}

                        @target[:os] = os
                      end

          option :os_version, value: {
                                type:  String,
                                usage: 'VERSION'
                              },
                              desc: 'The OS version to target' do |ver|
                                # lazy initialize @target
                                @target ||= {}

                                @target[:os_version] = ver
                              end

          option :software, short: '-S',
                            value: {
                              type:  String,
                              usage: 'NAME'
                            },
                            desc: 'The software to target' do |name|
                              # lazy initialize @target
                              @target ||= {}

                              @target[:software] = name
                            end

          option :software_version, short: '-V',
                                    value: {
                                      type:  String,
                                      usage: 'ARCH'
                                    },
                                    desc: 'The software version to target' do |ver|
                                      # lazy initialize @target
                                      @target ||= {}

                                      @target[:version] = ver
                                    end

          option :loot, short: '-L',
                        desc:  'Adds the loot mixin' do
                          @loot = true
                        end

          argument :file, desc: 'The path to the new exploit file'

          description 'Creates a new exploit file'

          man_page 'ronin-exploits-new.1'

          #
          # Initializes the `ronin-exploits new` command.
          #
          # @param [Hash{Symbol => Object}] kwargs
          #   Additional keyword arguments.
          #
          def initialize(**kwargs)
            super(**kwargs)

            @exploit_type = EXPLOIT_TYPES.fetch(:exploit)
            @advisories   = []
          end

          #
          # Runs the `ronin-exploits new` command.
          #
          # @param [String] file
          #   The path to the new exploit file.
          #
          def run(file)
            @directory  = File.dirname(file)
            @file_name  = File.basename(file,File.extname(file))
            @class_name = CommandKit::Inflector.camelize(@file_name)

            mkdir @directory unless @directory == '.'

            erb "exploit.rb.erb", file
            chmod '+x', file
          end

          #
          # Formats a Hash into Ruby keyword arguments.
          #
          # @param [Hash{Symbol => Object}] kwargs
          #
          # @return [String]
          #
          def format_kwargs(kwargs)
            kwargs.map { |key,value|
              "#{key}: #{value.inspect}"
            }.join(', ')
          end

          # Web exploit class names.
          WEB_VULN_EXPLOITS = %w[LFI RFI SQLI]

          #
          # Determines if the exploit type is `stack_overflow`.
          #
          # @return [Boolean]
          #
          def stack_overflow_exploit?
            @exploit_type[:class] == 'StackOverflow'
          end

          #
          # Determines if the exploit type is `seh_overflow`.
          #
          # @return [Boolean]
          #
          def seh_overflow_exploit?
            @exploit_type[:class] == 'SEHOverflow'
          end

          #
          # Determines if the exploit type is a web vuln exploit.
          #
          # @return [Boolean]
          #
          def web_vuln_exploit?
            WEB_VULN_EXPLOITS.include?(@exploit_type[:class])
          end

        end
      end
    end
  end
end