# frozen_string_literal: true
#
# ronin-masscan - A Ruby library and CLI for working with masscan.
#
# Copyright (c) 2023-2024 Hal Brodigan (postmodern.mod3@gmail.com)
#
# ronin-masscan 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-masscan 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-masscan. If not, see .
#
require 'ronin/masscan/cli/command'
require 'ronin/masscan/cli/filtering_options'
require 'masscan/output_file'
require 'set'
module Ronin
module Masscan
class CLI
module Commands
#
# Dumps the scanned ports from masscan scan file(s).
#
# ## Usage
#
# ronin-masscan dump [options] MASSCAN_FILE [...]
#
# ## Options
#
# --print-ips Print all IP addresses
# --print-hosts Print all hostnames
# --print-ip-ports Print IP:PORT pairs. (Default)
# --print-host-ports Print HOST:PORT pairs
# --print-uris Print URIs
# -P, --protocol tcp|udp Filters the targets by protocol
# --ip IP Filters the targets by IP
# --ip-range CIDR Filter the targets by IP range
# -p, --ports {PORT | PORT1-PORT2},...
# Filter targets by port number
# -h, --help Print help information
#
# ## Arguments
#
# MASSCAN_FILE ... The masscan scan file(s) to parse
#
# ## Examples
#
# ronin-masscan dump --print-ip-ports masscan.bin
# ronin-masscan dump --print-ip-ports --ports 22,80,443 masscan.bin
# ronin-masscan dump --print-host-ports masscan.bin
# ronin-masscan dump --print-hosts --with-port 22 masscan.bin
# ronin-masscan dump --print-uris masscan.bin
#
class Dump < Command
usage '[options] MASSCAN_FILE [...]'
option :print_ips, desc: 'Print all IP addresses' do
@mode = :ips
end
option :print_hosts, desc: 'Print all hostnames' do
@mode = :hostnames
end
option :print_ip_ports, desc: 'Print IP:PORT pairs. (Default)' do
@mode = :ip_ports
end
option :print_host_ports, desc: 'Print HOST:PORT pairs' do
@mode = :host_ports
end
option :print_uris, desc: 'Print URIs' do
@mode = :uris
end
include FilteringOptions
argument :masscan_file, required: true,
repeats: true,
desc: 'The masscan scan file(s) to parse'
examples [
'--print-ip-ports masscan.bin',
'--print-ip-ports --ports 22,80,443 masscan.bin',
'--print-host-ports masscan.bin',
'--print-hosts --with-port 22 masscan.bin',
'--print-uris masscan.bin'
]
description 'Dumps the scanned ports from masscan scan file(s)'
man_page 'ronin-masscan-dump.1'
#
# Initializes the command.
#
# @param [Hash{Symbol => Object}] kwargs
# Additional keywords for the command.
#
def initialize(**kwargs)
super(**kwargs)
@mode = :ip_ports
end
#
# Runs the `ronin-masscan dump` command.
#
# @param [Array] masscan_files
# The masscan scan file(s) to parse.
#
def run(*masscan_files)
masscan_files.each do |masscan_file|
output_file = begin
::Masscan::OutputFile.new(masscan_file)
rescue ArgumentError => error
print_error(error.message)
exit(1)
end
filter_records(output_file).each do |target|
print_target(target)
end
end
end
#
# Prints the target.
#
# @param [::Masscan::Status, ::Masscan::Banner] host
#
def print_target(host)
case @mode
when :ips then print_ip(host)
when :ip_ports then print_ip_ports(host)
when :uris then print_uri(host)
end
end
#
# Prints the IPs for the target.
#
# @param [::Masscan::Status, ::Masscan::Banner] target
#
def print_ip(target)
puts target.ip
end
#
# Prints the `IP:PORT` pair for the target.
#
# @param [::Masscan::Status, ::Masscan::Banner] target
#
def print_ip_ports(target)
puts "#{target.ip}:#{target.port}"
end
#
# Prints the URIs for the target.
#
# @param [::Masscan::Status, ::Masscan::Banner] target
#
def print_uri(target)
case target.port
when 80
puts URI::HTTP.build(
host: target.ip.to_s,
port: target.port
)
when 443
puts URI::HTTPS.build(
host: target.ip.to_s,
port: target.port
)
end
end
end
end
end
end
end