# 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 .
#
require 'ronin/exploits/cli/exploit_command'
require 'ronin/payloads/cli/printing'
require 'ronin/core/cli/printing/metadata'
require 'ronin/core/cli/printing/arch'
require 'ronin/core/cli/printing/os'
require 'ronin/core/cli/printing/params'
require 'ronin/core/metadata/version'
require 'command_kit/printing/fields'
module Ronin
module Exploits
class CLI
module Commands
#
# Prints information about an exploit.
#
# ## Usage
#
# ronin-exploits show [options] {NAME | --file FILE}
#
# ## Options
#
# -f, --file FILE The exploit file to load
# -v, --verbose Enables verbose output
# -h, --help Print help information
#
# ## Arguments
#
# [NAME] The exploit name to load
#
class Show < ExploitCommand
include Core::CLI::Printing::Metadata
include Core::CLI::Printing::Arch
include Core::CLI::Printing::OS
include Core::CLI::Printing::Params
include CommandKit::Printing::Fields
include Payloads::CLI::Printing
description 'Prints information about an exploit'
man_page 'ronin-exploits-show.1'
#
# Runs the `ronin-exploits show` command.
#
# @param [String] name
# The optional name of the exploit to load and print metadata about.
#
def run(name=nil)
super(name)
print_exploit(exploit_class)
end
#
# Prints the exploit class'es metadata.
#
# @param [Class] exploit
# The loaded exploit class.
#
def print_exploit(exploit)
puts "[ #{exploit.id} ]"
puts
indent do
print_metadata(exploit)
print_advisories(exploit)
print_authors(exploit)
print_description(exploit)
print_references(exploit)
if defined?(Mixins::HasTargets) &&
exploit.include?(Mixins::HasTargets)
unless exploit.targets.empty?
exploit.targets.each_with_index do |target,index|
puts "[ Target ##{index + 1} ]"
puts
indent { print_target(target) }
end
end
end
print_shouts(exploit)
end
print_params(exploit)
end
#
# Print the main metadata fields for the exploit.
#
# @param [Class] exploit
# The loaded exploit class.
#
def print_metadata(exploit)
fields = {
'Type' => exploit_type(exploit)
}
if defined?(Core::Metadata::Version) &&
exploit.include?(Core::Metadata::Version)
fields['Version'] = exploit.version if exploit.version
end
fields['Quality'] = exploit.quality if exploit.quality
fields['Released'] = exploit.release_date if exploit.release_date
fields['Disclosed'] = exploit.disclosure_date if exploit.disclosure_date
if defined?(Metadata::Arch) && exploit.include?(Metadata::Arch)
if (arch = target.arch)
fields['Arch'] = arch
end
end
if defined?(Metadata::OS) && exploit.include?(Metadata::OS)
if (os = exploit.os)
fields['OS'] = if (os_version = exploit.os_version)
"#{os} #{os_version}"
else
os
end
end
end
if (software = exploit.software)
fields['Software'] = software
end
if (versions = exploit.software_versions)
case versions
when Array
fields['Software Versions'] = versions.join(', ')
when Range
fields['Software Versions'] = "#{versions.begin} - #{versions.end}"
end
end
if defined?(Mixins::HasPayload) &&
exploit.include?(Mixins::HasPayload)
fields['Payload Type'] = payload_type(exploit.payload_class)
end
fields['Summary'] = exploit.summary if exploit.summary
print_fields(fields)
end
#
# Prints any advisories defined by an exploit class.
#
# @param [Class] exploit
# The loaded exploit class.
#
def print_advisories(exploit)
unless exploit.advisories.empty?
puts "Advisories:"
puts
indent do
exploit.advisories.each do |advisory|
print_advisory(advisory)
end
end
puts
end
end
#
# Prints the shouts section.
#
# @param [Class] exploit
# The loaded exploit class.
#
def print_shouts(exploit)
if defined?(Metadata::Shouts) && exploit.include?(Metadata::Shouts)
puts "Shouts: #{exploit.shouts.join(', ')}"
end
end
# Known exploit types and their printable names.
EXPLOIT_TYPES = {
exploit: 'Custom',
# memory corruption exploits
memory_corruption: 'Memory Corruption',
stack_overflow: 'Stack Overflow',
seh_overflow: 'SEH Overflow',
heap_overflow: 'Heap Overflow',
use_after_free: 'Use After Free',
# web exploits
web: 'Web',
lfi: 'Local File Inclusion (LFI)',
rfi: 'Remote File Inclusion (RFI)',
sqli: 'SQL injection (SQLI)',
xss: 'Cross-Site Scripting (XSS)',
open_redirect: 'Open Redirect',
ssti: 'Server-Side Template Injection (SSTI)'
}
#
# Returns the printable exploit type for the exploit class.
#
# @param [Class] exploit_class
#
# @return [String]
#
def exploit_type(exploit_class)
EXPLOIT_TYPES.fetch(exploit_class.exploit_type,'unknown')
end
#
# Prints an advisory.
#
# @param [Advisory] advisory
# The advisory to print.
#
def print_advisory(advisory)
if advisory.url then puts "* #{advisory.id} (#{advisory.url})"
else puts "* #{advisory.id}"
end
end
#
# Prints an exploit target.
#
# @param [Target] target
# A target defined on the exploit.
#
def print_target(target)
fields = {}
fields['Arch'] = target.arch if target.arch
if target.os
fields['OS'] = if target.os_version
"#{target.os} #{target.os_version}"
else
target.os
end
end
if target.software
fields['Software'] = if target.software_version
"#{target.software} #{target.software_version}"
else
target.software
end
end
print_fields(fields)
if verbose?
unless target.empty?
puts "Params:"
indent { print_fields(target.to_h) }
end
end
puts
end
end
end
end
end
end