lib/ronin/exploits/cli/commands/new.rb
# 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