#!/usr/bin/env ruby ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'patch_finder/core/helper' require 'patch_finder/msu' require 'optparse' class PatchFinderBin include PatchFinder::Helper attr_reader :args def get_parsed_options options = {} parser = OptionParser.new do |opt| opt.separator '' opt.separator 'Specific options:' opt.on('-q', '--query ', 'Find advisories including this keyword') do |v| options[:keyword] = v end opt.on('-s', '--search-engine ', '(Optional) The type of search engine to use (Technet or Google). Default: Technet') do |v| case v.to_s when /^google$/i options[:search_engine] = :google when /^technet$/i options[:search_engine] = :technet else fail OptionParser::InvalidOption, "Invalid search engine: #{v}" end end opt.on('-r', '--regex ', '(Optional) Specify what type of links you want') do |v| options[:regex] = v end opt.on('--apikey ', '(Optional) Google API key.') do |v| options[:google_api_key] = v end opt.on('--cx ', '(Optional) Google search engine ID.') do |v| options[:google_search_engine_id] = v end opt.on('-d', '--dir ', '(Optional) The directory to save the patches') do |v| unless File.directory?(v) fail OptionParser::InvalidOption, "Directory not found: #{v}" end options[:destdir] = v end opt.on_tail('-h', '--help', 'Show this message') do $stderr.puts opt exit end end parser.parse! if options.empty? fail OptionParser::MissingArgument, 'No options set, try -h for usage' elsif options[:keyword].nil? || options[:keyword].empty? fail OptionParser::MissingArgument, '-q is required' end unless options[:search_engine] options[:search_engine] = :technet end if options[:search_engine] == :google if options[:google_api_key].nil? || options[:google_search_engine_id].empty? fail OptionParser::MissingArgument, 'No API key set for Google' elsif options[:google_search_engine_id].nil? || options[:google_search_engine_id].empty? fail OptionParser::MissingArgument, 'No search engine ID set for Google' end end options end def initialize @args = get_parsed_options rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e print_error(e.message) exit end def main cli = PatchFinder::MSU.new(verbose: true) links = cli.find_msu_download_links(args) if args[:destdir] print_status("Download links found: #{links.length}") print_status('Downloading files, please wait...') download_files(links, args[:destdir]) else print_status('Download links found:') print_line(links * "\n") end end end if __FILE__ == $PROGRAM_NAME bin = PatchFinderBin.new bin.main end