Guest User

SNMP Stalker

a guest
Feb 24th, 2014
204
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 24.25 KB | None | 0 0
  1. #!/usr/bin/env ruby
  2. #
  3. # SNMP Stalker
  4. # By: Hood3dRob1n
  5. #
  6. # This is a tool for enumerating information from devices over SNMP.
  7. # - Community String Bruteforcer
  8. # - Read & Write Options
  9. # - Targeted at Windows, but not limited to Windows
  10. #   - Windows pre-built options for enumerating lots of juicy info
  11. #
  12. # ToDo:
  13. # - Figure out how to fix the process killer
  14. # - Add Common Cisco Options
  15. #   - Config Downloader
  16. #     - Built-in TFTP Server?
  17. #   - Auto-Crack PIX Hashes?
  18. #
  19. # Requires NMAP for Recon & Discovery Scanning
  20. #
  21.  
  22. ###### STD GEMS ######
  23. require 'fileutils'  #
  24. require 'optparse'   #
  25. #### NON-STD GEMS ####
  26. require 'rubygems'   #
  27. require 'colorize'   #
  28. require 'readline'   #
  29. require 'snmp'       #
  30. require 'text-table' #
  31. ######################
  32.  
  33. HOME=File.expand_path(File.dirname(__FILE__))
  34. RESULTS=HOME + '/results/'
  35. include SNMP
  36.  
  37. # Trap Interupts
  38. trap("SIGINT") {puts "\n\nWARNING! CTRL+C Detected, Shutting things down....."; exit 666;}
  39.  
  40. # 31337 Banner
  41. def banner
  42.   puts
  43.   puts "SNMP Stalker".light_yellow
  44.   puts "By".light_yellow + ": Hood3dRob1n".white
  45. end
  46.  
  47. # Clear Terminal
  48. def cls
  49.   system('clear')
  50. end
  51.  
  52. # Exec cmd in separate process we dont have to wait on
  53. def fireNforget(command)
  54.   pid = Process.fork
  55.   if pid.nil?
  56.     sleep(1)
  57.     exec "#{command}"
  58.   else
  59.     Process.detach(pid)
  60.   end
  61. end
  62.  
  63. # Main Menu Help Options
  64. def show_usage
  65.   puts
  66.   puts "Recon & Discovery:".white.underline
  67.   puts "  nmap ".light_yellow + "       => ".white + "Quick NMAP SNMP Scan Builder".light_yellow
  68.   puts "  bruteforce ".light_yellow + " => ".white + "Dictionary Attack SNMP Community String".light_yellow
  69.   puts "  creds ".light_yellow + "      => ".white + "Setup Credentials & SNMP Connection".light_yellow
  70.   puts
  71.   puts "General Options:".white.underline
  72.   puts "  basic ".light_yellow + "      => ".white + "Enumerate Basic Info".light_yellow
  73.   puts "  dump ".light_yellow + "       => ".white + "Dump Full 'MGMT' Tree".light_yellow
  74.   puts "  o2n OID ".light_yellow + "    => ".white + "Convert OID to Symbolic Name".light_yellow
  75.   puts "  n2o NAME ".light_yellow + "   => ".white + "Convert Symbolic Name to OID".light_yellow
  76.   puts "  walk OID ".light_yellow + "   => ".white + "Walk Tree by OID or Symbolic Name".light_yellow
  77.   puts "  setstr OID STRING ".light_yellow + "  => ".white + "Set Value for Specified OID to String value".light_yellow
  78.   puts "  setint OID INTEGER ".light_yellow + " => ".white + "Set Value for Specified OID to Integer Value".light_yellow
  79.   puts
  80.   puts "Windows Specific Options:".white.underline
  81.   puts "  users ".light_yellow + "      => ".white + "Enumerate Usernames".light_yellow
  82.   puts "  netstat ".light_yellow + "    => ".white + "Enumerate Currently Open TCP & UDP Ports".light_yellow
  83.   puts "  services ".light_yellow + "   => ".white + "Enumerate Running Services".light_yellow
  84.   puts "  software ".light_yellow + "   => ".white + "Enumerate Installed Software".light_yellow
  85.   puts "  process ".light_yellow + "    => ".white + "Enumerate Running Processes".light_yellow
  86.   puts "  kill PID ".light_yellow + "   => ".white + "Kill Running Processes by PID (write privs)".light_yellow
  87. end
  88.  
  89. #Core/Main Menu
  90. def core_shell
  91.   puts
  92.   prompt = "(SNMP_Stalker)> "
  93.   while line = Readline.readline("#{prompt}", true)
  94.     cmd = line.chomp
  95.     case cmd
  96.     when /^clear|^cls|^banner/i
  97.       cls
  98.       banner
  99.       core_shell
  100.     when /^help|^h$|^ls$/i
  101.       show_usage
  102.       core_shell
  103.     when /^exit|^quit/i
  104.       puts
  105.       puts "OK".light_red + ",".white + " exiting SNMP Stalker session".light_red + "....".white
  106.       puts
  107.       exit 69;
  108.     when /^nmap|^snmp_nmap/i
  109.       puts
  110.       nmap_snmp
  111.       core_shell
  112.     when /^bruteforce|^snmp_brute|^brute/i
  113.       puts
  114.       snmp_brute
  115.       core_shell
  116.     when /^creds|^credz|^credential/i
  117.       puts
  118.       snmp_creds
  119.       core_shell
  120.     when /^o2n (.+)/i
  121.       oid=$1.chomp
  122.       puts
  123.       o2n(oid)
  124.       puts
  125.       core_shell
  126.     when /^n2o (.+)/i
  127.       name=$1.chomp
  128.       puts
  129.       n2o(name)
  130.       puts
  131.       core_shell
  132.     when /^get (.+)/i
  133.       oidname=$1.chomp
  134.       puts
  135.       get(oidname)
  136.       puts
  137.       core_shell
  138.     when /^walk (.+)/i
  139.       oidname=$1
  140.       puts
  141.       walk(oidname)
  142.       puts
  143.       core_shell
  144.     when /^setstr (.+) (.+)/i
  145.       oid=$1
  146.       string=$2
  147.       puts
  148.       set(oid, string, 's')
  149.       core_shell
  150.     when /^setint (.+) (.+)/i
  151.       oid=$1
  152.       int=$2
  153.       puts
  154.       set(oid, int, 'i')
  155.       core_shell
  156.     when /^basic|^info/i
  157.       puts
  158.       basic
  159.       puts
  160.       core_shell
  161.     when /^dump/i
  162.       puts
  163.       dump
  164.       puts
  165.       core_shell
  166.     when /^users|^usernames/i
  167.       puts
  168.       users
  169.       puts
  170.       core_shell
  171.     when /^software|^sw$/i
  172.       puts
  173.       software
  174.       puts
  175.       core_shell
  176.     when /^services/i
  177.       puts
  178.       services
  179.       puts
  180.       core_shell
  181.     when /^process|^ps$/i
  182.       puts
  183.       processes
  184.       puts
  185.       core_shell
  186.     when /^kill (.+)/i
  187.       pid=$1.chomp
  188.       puts
  189.       kill(pid)
  190.       puts
  191.       core_shell
  192.     when /^netstat/i
  193.       puts
  194.       netstat
  195.       puts
  196.       core_shell
  197.     else
  198.       cls
  199.       puts
  200.       puts "Oops".light_red + ",".white + " Didn".light_red + "'".white + "t quite understand that one".light_red
  201.       puts "Please Choose a Valid Option From Menu Below Next Time".light_red + ".....".white
  202.       puts
  203.       show_usage
  204.       core_shell
  205.     end
  206.   end
  207. end
  208.  
  209. # NMAP SNMP Quick Scan Builder
  210. def nmap_snmp
  211.   puts "NMAP SNMP Quick Scan Builder".white.underline
  212.   line = Readline.readline("(Target IP)> ", true)
  213.   target = line.chomp
  214.   # Launch the scan in a new X-term window so we dont have to wait :)
  215.   scan="xterm -title 'NMAP SNMP Quick Scan' -font -*-fixed-medium-r-*-*-18-*-*-*-*-*-iso8859-* -e \"bash -c 'nmap -sU -p 161 -sV "
  216.   line = Readline.readline("(Enable NSE Scripts (Y/N))> ", true)
  217.   answer=line.chomp
  218.   if answer.upcase == 'YES' or answer.upcase == 'Y'
  219.     scan += '-sC '
  220.   end
  221.   Dir.mkdir(RESULTS) unless File.exists?(RESULTS)
  222.   Dir.mkdir("#{RESULTS}nmap/") unless File.exists?("#{RESULTS}nmap/")
  223.   scan += "#{target} -oX #{RESULTS}nmap/#{target}.xml' && echo && echo '-- Press ENTER to close window --' && read\""
  224.   puts "Launching NMAP Scan in new xterm window".light_yellow + ",".white + " hope you find something interesting".light_yellow + "....".white
  225.   fireNforget(scan)
  226.   puts
  227. end
  228.  
  229. # Dictionary attack to find Community String
  230. # say something gay about using the word bruteforce and you will instantly be banished!
  231. # use your brain power, google and small lists with targeted strings
  232. # Bad Connections and faulty credentials end up causing time-out error
  233. # Simple use this to judge, moving on to next string in list if failed....not overly complex, sorry
  234. def snmp_brute
  235.   puts "SNMP Community String Bruteforcer".white.underline
  236.   line = Readline.readline("(Target IP)> ", true)
  237.   target = line.chomp
  238.   line = Readline.readline("(Standard SNMP Port 161 (Y/N)?)> ", true)
  239.   answer = line.chomp
  240.   if answer.upcase == 'N' or answer.upcase == 'NO'
  241.     line = Readline.readline("(SNMP Port)> ", true)
  242.     zPORT = line.chomp
  243.    else
  244.     zPORT='161'
  245.   end
  246.   puts
  247.   builtins = [ 'public', 'public123', 'private', 'private123', 'internal', 'internet', 'secret', 'write', 'read', 'MyPublicCommunityName', 'MyPrivateCommunityName', 'snmp', 'snmpd', 'all private' ]
  248.   puts "Select Wordlist for Attack".light_yellow + ": ".white
  249.   puts "1".white + ")".light_yellow + " Built-in Wordlist".white
  250.   puts "2".white + ")".light_yellow + " Custom Wordlist".white
  251.   answer=gets.chomp
  252.   if answer == '2'
  253.     line = Readline.readline("(Path to Wordlist)> ", true)
  254.     zlist=line.strip.chomp
  255.     if File.exists?(zlist)
  256.       zWordlist = File.open(zlist).readlines
  257.     else
  258.       puts "Can".light_red + "'".white + "t find provided file".light_red + "!".white
  259.       puts "Proceeding with built-in wordlist".light_red + ".....".white
  260.       zWordlist = builtins
  261.     end
  262.   else
  263.     zWordlist = builtins
  264.   end
  265.   puts "Loaded ".light_yellow + "#{zWordlist.size}".white + " strings from wordlist".light_yellow + ".....".white
  266.   line = Readline.readline("(Stop on Firt Success (Y/N)?)> ", true)
  267.   answer=line.chomp
  268.   if answer.upcase == 'Y' or answer.upcase == 'YES'
  269.     stop=true
  270.   else
  271.     stop=false
  272.   end
  273.   while(true)
  274.     puts "Starting SNMP Bruteforce Attack".light_yellow + ",".white + " hang tight".light_yellow + "....".white
  275.     zWordlist.each do |cs|
  276.       if can_we_connect(target, zPORT.to_i, cs.chomp)
  277.         puts "[".light_green + "*".white + "]".light_green + " Success using".light_yellow + ": #{cs.chomp}".white
  278.         break if stop
  279.       end
  280.     end
  281.     break
  282.   end
  283. end
  284.  
  285. # Test if we can connect with credentials or not
  286. def can_we_connect(target, port, string)
  287.   begin
  288.     manager = SNMP::Manager.new(:Host => target, :Port => port.to_i, :Community => string)
  289.     sys_time = manager.get_value("sysUpTime.0")
  290.     manager.close if manager
  291.     return true
  292.   rescue SNMP::RequestTimeout => e
  293.     return false
  294.   end
  295. end
  296.  
  297. # Establish Valid Credentials
  298. # Creates Instance Variables for use throughout
  299. def snmp_creds
  300.   puts "SNMP Connection Datastore".white.underline
  301.   line = Readline.readline("(Target IP)> ", true)
  302.   snmp_target = line.chomp
  303.   line = Readline.readline("(Standard SNMP Port 161 (Y/N)?)> ", true)
  304.   answer = line.chomp
  305.   if answer.upcase == 'N' or answer.upcase == 'NO'
  306.     line = Readline.readline("(SNMP Port)> ", true)
  307.     snmp_port = line.chomp
  308.   else
  309.     snmp_port='161'
  310.   end
  311.   line = Readline.readline("(Community String)> ", true)
  312.   snmp_string = line.chomp
  313.   puts "SNMP Connection Datastore Complete".light_yellow + "!".white
  314.   puts
  315.   puts "Confirming we can connect now".light_yellow + ".....".white
  316.   if can_we_connect(snmp_target, snmp_port, snmp_string)
  317.     @manager = SNMP::Manager.new(:Host => snmp_target, :Port => snmp_port, :Community => snmp_string)
  318.     if can_we_write
  319.       @wite_access=true
  320.     else
  321.       @wite_access=false
  322.     end
  323.     puts "SNMP Connection Established".light_green + "!".white
  324.     puts "Target".light_yellow + ": #{snmp_target}".white
  325.     puts "Port".light_yellow + ": #{snmp_port}".white
  326.     puts "Community String".light_yellow + ": #{snmp_string}".white
  327.     puts "Read Access".light_yellow + ": Enabled".white
  328.     puts "Write Access".light_yellow + ": Enabled".white if @wite_access
  329.     puts "Write Access".light_yellow + ": Disabled".white unless @wite_access
  330.     @host = snmp_target
  331.     @port = snmp_port
  332.     @string = snmp_string
  333.   else
  334.     puts "Can".light_red + "'".white + "t connect using".light_red + ": #{snmp_string}".white
  335.     puts "Re-run creds command to change and re-set the SNMP connection".light_red + "....".white
  336.     @manager=nil
  337.   end
  338.   puts
  339. end
  340.  
  341. # Check/Confirm Write Access
  342. def can_we_write
  343.   if @manager.nil?
  344.     puts "Set Credentials and try again".light_red + "....".white
  345.   else
  346.     begin
  347.       original = @manager.get_value('SNMPv2-MIB::sysContact.0') # SNMP System Contact String Value
  348.       varbind = VarBind.new('1.3.6.1.2.1.1.4.0', OctetString.new("SNMP_Stalker")) # Write a String Value
  349.       @manager.set(varbind)
  350.       new = @manager.get_value('SNMPv2-MIB::sysContact.0')
  351.       if new == "SNMP_Stalker"
  352.         varbind = VarBind.new('1.3.6.1.2.1.1.4.0', OctetString.new(original)) # Write a String Value
  353.         @manager.set(varbind)
  354.         return true
  355.       else
  356.         return false
  357.       end
  358.     rescue SNMP::RequestTimeout => e
  359.       return false
  360.     rescue SNMP::BER::InvalidObjectId => e
  361.       return false
  362.     rescue ArgumentError => e
  363.       return false
  364.     end
  365.   end
  366. end
  367.  
  368. # Convert OID 2 Symbolic Name
  369. def o2n(oid)
  370.   if @manager.nil?
  371.     puts "Set Credentials and try again".light_red + "....".white
  372.   else
  373.     begin
  374.       name = @manager.mib.name(oid)
  375.       t = [['OID', 'Symbolic Name'], ["#{oid}", "#{name}"]]
  376.       table = t.to_table(:first_row_is_head => true)
  377.       puts table.to_s
  378.     rescue ArgumentError => e
  379.       puts "Problem trying to convert!"
  380.       puts "This is NOT a valid OID!"
  381.     end
  382.   end
  383. end
  384.  
  385. # Convert Symbolic Name to OID
  386. def n2o(name)
  387.   if @manager.nil?
  388.     puts "Set Credentials and try again".light_red + "....".white
  389.   else
  390.     begin
  391.       oid = @manager.mib.oid(name)
  392.       t = [['OID', 'Symbolic Name'], ["#{oid}", "#{name}"]]
  393.       table = t.to_table(:first_row_is_head => true)
  394.       puts table.to_s
  395.     rescue ArgumentError => e
  396.       puts "Problem trying to convert!"
  397.       puts "This is NOT a valid OID Name!"
  398.     end
  399.   end
  400. end
  401.  
  402. # Fetch Value for given OID
  403. def get(oidname)
  404.   if @manager.nil?
  405.     puts "Set Credentials and try again".light_red + "....".white
  406.   else
  407.     begin
  408.       res = @manager.get(oidname)
  409.       res.each_varbind do |vb|
  410.         puts "Name: #{vb.name.to_s}"
  411.         puts "Type: #{vb.value.asn1_type}"
  412.         puts "Value: #{vb.value.to_s}"
  413.       end
  414.     rescue SNMP::BER::InvalidObjectId => e
  415.       puts "Bad OID Value passed!"
  416.       puts "\t=> #{e}"
  417.     end
  418.   end
  419. end
  420.  
  421. # Walk the target OID or OID Symbolic Name tree if available....
  422. def walk(oidname)
  423.   if @manager.nil?
  424.     puts "Set Credentials and try again".light_red + "....".white
  425.   else
  426.     puts "Trying to Walk the '#{oidname}' tree......"
  427.     begin
  428.       @manager.walk(oidname) { |x| puts "#{x}" }
  429.     rescue SNMP::BER::InvalidObjectId => e
  430.       puts "Bad OID Value passed!"
  431.       puts "\t=> #{e}"
  432.     end
  433.   end
  434. end
  435.  
  436. # SET value for specified OID with given integer
  437. # ex: set("1.3.6.1.2.1.25.4.2.1.7.#{pid}", 4) # => would kill windows process where process id = #{pid}
  438. # oid, value to write, and the type of value (s=>String, i=>Integer)
  439. def set(oid, data, type='s')
  440.   if @manager.nil?
  441.     puts "Set Credentials and try again".light_red + "....".white
  442.   else
  443.     puts "Trying to SET value of ".light_yellow + "#{oid}".white + " to ".light_yellow + "#{data}".white
  444.     begin
  445.       old = @manager.get_value(oid)
  446.       puts "Current Value".light_yellow + ": #{old}".white
  447.       if type == 's'
  448.         varbind = VarBind.new(oid, OctetString.new("#{data}")) # Write a String Value
  449.       else
  450.         varbind = VarBind.new(oid, SNMP::Integer.new(data)) # Write an Integer Value
  451.       end
  452.       @manager.set(varbind)
  453.       new = @manager.get_value(oid)
  454.       puts "Updated Value".light_yellow + ": #{new}".white
  455.     rescue SNMP::BER::InvalidObjectId => e
  456.       puts "Bad OID Value passed".light_red + "!".white
  457.       puts "\t=> #{e}".light_red
  458.     rescue ArgumentError => e
  459.       puts "Problem trying to convert".light_red + "!".white
  460.       puts "This is NOT a valid OID Name".light_red + "!".white
  461.     end
  462.   end
  463. end
  464.  
  465. # CEnumerate Some Basic Info
  466. def basic
  467.   if @manager.nil?
  468.     puts "Set Credentials and try again".light_red + "....".white
  469.   else
  470.     # Grab some basic info using OID values which should be fairly generic in nature
  471.     target = "#{@manager.config[:host]}:#{@manager.config[:port]}"
  472.     cstring = @manager.config[:community]
  473.     snmp_version = @manager.config[:version]
  474.     sys_name = @manager.get_value("sysName.0")
  475.     sys_descr = @manager.get_value("sysDescr.0")
  476.     sys_time = @manager.get_value("sysUpTime.0")
  477.  
  478.     # Print out our basic info for user now....
  479.     puts "[*] ".light_green + "Target".light_yellow + ": #{target}".white
  480.     puts "[*] ".light_green + "Community String".light_yellow + ": #{cstring}".white
  481.     puts "[*] ".light_green + "Read Access".light_yellow + ": Enabled".white
  482.     puts "[*] ".light_green + "Write Access".light_yellow + ": Enabled".white if @wite_access
  483.     puts "[*] ".light_green + "Write Access".light_yellow + ": Disabled".white unless @wite_access
  484.     if snmp_version
  485.       puts "[*] ".light_green + "SNMP Version".light_yellow + ": #{snmp_version}".white
  486.     else
  487.       puts "Unable to determine SNMP Version in use".light_red + "?".white
  488.     end
  489.     if sys_name
  490.       puts "[*] ".light_green + "System Name".light_yellow + ": #{sys_name}".white
  491.     else
  492.       puts "Unable to determine system name".light_red + "!".white
  493.     end
  494.     if sys_descr
  495.       puts "[*] ".light_green + "System Description".light_yellow + ": \n#{sys_descr}".white
  496.     else
  497.       puts "Unable to find system description".light_red + "!".white
  498.     end
  499.     if sys_time
  500.       puts "[*] ".light_green + "System Uptime".light_yellow + ": #{sys_time}".white
  501.     else
  502.       puts "Unable to find system uptime".light_red + "!".white
  503.     end
  504.   end
  505. end
  506.  
  507. # Dump the 'MGMT' OID
  508. # Discloses most everything it has stored....
  509. # Nice if you need something random perhaps
  510. def dump
  511.   if @manager.nil?
  512.     puts "Set Credentials and try again".light_red + "....".white
  513.   else
  514.     puts "Dumping a bunch of info from the ".light_yellow + "'mgmt'".white + " OID".light_yellow + "......".white
  515.     dumpz=[]
  516.     @manager.walk('mgmt') { |x| dumpz << x }
  517.     if dumpz.empty?
  518.       puts "No Values Found".light_red + "!".white
  519.     else
  520.       puts "[*] ".light_green + "SNMP MGMT Dump".light_yellow + ": ".white
  521.       dumpz.each do |entry|
  522.         puts "#{entry}"
  523.       end
  524.     end
  525.   end
  526. end
  527.  
  528. # Walk the "SNMPv2-SMI::enterprises.77.1.2.25" or "1.3.6.1.4.1.77.1.2.25" tree
  529. # This will disclose the existing Windows Usernames for valid accounts on box
  530. def users
  531.   if @manager.nil?
  532.     puts "Set Credentials and try again".light_red + "....".white
  533.   else
  534.     puts "Enumerating Usernames".light_yellow + ".....".white
  535.     users=[['Usernames']]
  536.     @manager.walk('enterprises.77.1.2.25') { |x| users << ["#{x.value}"] }
  537.     if users.empty?
  538.       puts "No Values Found".light_red + "!".white
  539.     else
  540.       puts "#{users.size}".white + " Usernames Found".light_green + "!".white
  541.       table = users.to_table(:first_row_is_head => true)
  542.       puts table.to_s
  543.     end
  544.   end
  545. end
  546.  
  547. # Walk the 'SNMPv2-SMI::mib-2.25.6.3.1.2' or '1.3.6.1.2.1.25.6.3.1.2' tree
  548. # This will disclose the currently installed software on system
  549. def software
  550.   if @manager.nil?
  551.     puts "Set Credentials and try again".light_red + "....".white
  552.   else
  553.     puts 'Enumerating Installed Software'.light_yellow + ".....".white
  554.     sw=[['Installed Software']]
  555.     @manager.walk('mib-2.25.6.3.1.2') { |x| sw << ["#{x.value}"] }
  556.     if sw.empty?
  557.       puts "No Values Found".light_red + "!".white
  558.     else
  559.       table = sw.to_table(:first_row_is_head => true)
  560.       puts table.to_s
  561.     end
  562.   end
  563. end
  564.  
  565. # Enumerate Running Services (Windows)
  566. # Walk the 'SNMPv2-SMI::enterprises.77.1.2.3.1.1' or '1.3.6.1.4.1.77.1.2.3.1.1' tree
  567. # This will disclose the currently running windows services
  568. def services
  569.   if @manager.nil?
  570.     puts "Set Credentials and try again".light_red + "....".white
  571.   else
  572.     puts 'Enumerating Running Services'.light_yellow + '.....'.white
  573.     services=[['Running Services']]
  574.     @manager.walk('enterprises.77.1.2.3.1.1') { |x| services << ["#{x.value}"] }
  575.     if services.empty?
  576.       puts "No Values Found".light_red + "!".white
  577.     else
  578.       table = services.to_table(:first_row_is_head => true)
  579.       puts table.to_s
  580.     end
  581.   end
  582. end
  583.  
  584. # Enumerate Open TCP & UDP Ports, similar to Netstat
  585. def netstat
  586.   if @manager.nil?
  587.     puts "Set Credentials and try again".light_red + "....".white
  588.   else
  589.     netstat_tcp
  590.     puts
  591.     netstat_udp
  592.   end
  593. end
  594.  
  595. # Enumerate Listening and Open TCP Ports (a.k.a. Netstat Output)
  596. # Walk the tcpConnState or 1.3.6.1.2.1.6.13.1.1 oid names (not values)
  597. # Results needs some formatting to make like netstat....
  598. def netstat_tcp
  599.   if @manager.nil?
  600.     puts "Set Credentials and try again".light_red + ".....".white
  601.   else
  602.     tcp=[]
  603.     @manager.walk('tcpConnState') {|x| tcp << x.to_s.split(", ")[0].sub('[name=TCP-MIB::tcpConnState.', '') }
  604.     if not tcp.empty?
  605.       puts "[*] ".light_green + "OPEN TCP PORTS".light_yellow + ": ".white
  606.       tcp.each do |entry|
  607.         if entry =~ /(\d+.\d+.\d+.\d+).(\d+).(\d+.\d+.\d+.\d+).(\d+)/ or entry =~ /(\d+.\d+.\d+.\d+).(\d+)/
  608.           ip=$1
  609.           port=$2
  610.           ip2=$3
  611.           port2=$4
  612.           puts "#{ip}:#{port}".white
  613.           if ip2 and port2
  614.             puts "#{ip2}:#{port2}".white
  615.           end
  616.         else
  617.           puts "#{entry}".white
  618.         end
  619.       end
  620.     else
  621.       puts "No Values Found".light_red + "!".white
  622.     end
  623.   end
  624. end
  625.  
  626. # Enumerate Listening and Open UDP Ports (a.k.a. Netstat Output)
  627. # Walk the udpLocalAddress or 1.3.6.1.2.1.7.5.1.1 oid names (not values)
  628. # Results needs some formatting to make like netstat....
  629. def netstat_udp
  630.   if @manager.nil?
  631.     puts "Set Credentials and try again".light_red + ".....".white
  632.   else
  633.     udp=[]
  634.     @manager.walk('udpLocalAddress') {|x| udp << x.to_s.split(", ")[0].sub('[name=UDP-MIB::udpLocalAddress.', '') }
  635.     if not udp.empty?
  636.       puts "[*] ".light_green + "OPEN UDP PORTS".light_yellow + ": ".white
  637.       udp.each do |entry|
  638.         if entry =~ /(\d+.\d+.\d+.\d+).(\d+)/
  639.           ip=$1
  640.           port=$2
  641.           puts "#{ip}:#{port}"
  642.         else
  643.           puts "#{entry}"
  644.         end
  645.       end
  646.     else
  647.       puts "No Values Found".light_red + "!".white
  648.     end
  649.   end
  650. end
  651.  
  652. # Enumerate the Currently Running Processes
  653. # Process Name, PID, and PATH returned
  654. # PROCESS: Symbolic Name: mib-2.25.4.2.1.2 or OID: 1.3.6.1.2.1.25.4.2.1.2
  655. # PID: Symbolic Name: mib-2.25.4.2.1.1 or OID: 1.3.6.1.2.1.25.4.2.1.1
  656. # PATH: Symbolic Name: mib-2.25.4.2.1.4 or OID: 1.3.6.1.2.1.25.4.2.1.4
  657. def processes
  658.   if @manager.nil?
  659.     puts "Set Credentials and try again".light_red + ".....".white
  660.   else
  661.     puts 'Enumerating Running Process'.light_yellow + '.....'.white
  662.     psz=[] #process name
  663.     @manager.walk('mib-2.25.4.2.1.2') { |x| psz << x.value }
  664.     if psz.empty?
  665.       puts "No Values Found".light_red + "!".white
  666.     else
  667.       ps_present = [['PID', 'Process', 'Path']]
  668.       pidz=[] #PID valud
  669.       @manager.walk('mib-2.25.4.2.1.1') { |x| pidz << x.value }
  670.       pathz=[] #Path of process
  671.       @manager.walk('mib-2.25.4.2.1.4') do |path|
  672.         if path.value.chomp != '' and not path.nil?
  673.           pathz << path.value
  674.         else
  675.           pathz << " - "
  676.         end
  677.       end
  678.       count=0
  679.       while count.to_i < psz.size
  680.         ps_present << [[ "#{pidz[count]}", "#{psz[count]}", "#{pathz[count]}" ]]
  681.         count = count.to_i + 1
  682.       end
  683.       table = ps_present.to_table(:first_row_is_head => true)
  684.       puts table.to_s
  685.     end
  686.   end
  687. end
  688.  
  689. # Kill Running Process Identified by PID
  690. # Requires Community Write String Access
  691. def kill(pid)
  692.   if @manager.nil?
  693.     puts "Set Credentials and try again".light_red + ".....".white
  694.   else
  695.     pidz=[] # PID values
  696.     @manager.walk('mib-2.25.4.2.1.1') { |x| pidz << x.value }
  697.     if pidz.include?(pid)
  698.       puts "Sending Kill request to PID#".light_yellow + "#{pid}".white
  699.       set("1.3.6.1.2.1.25.4.2.1.7.#{pid}", 2, 'i')
  700.     else
  701.       puts "Not finding Process ID ".light_red + "#{pid}".white + " in active process list".light_red + "!".white
  702.     end
  703.   end
  704. end
  705.  
  706. # Close the SNMP Connection cleanly
  707. def close
  708.   @manager.close
  709. end
  710.  
  711. ## Main --
  712. options = {}
  713. optparse = OptionParser.new do |opts|
  714.   opts.banner = "Usage: #{$0} [OPTIONS]"
  715.   opts.separator ""
  716.   opts.separator "EX: #{$0} -i 192.168.2.43 -p 161 --main"
  717.   opts.separator "EX: #{$0} -i 192.168.2.43 -p 161 --recon"
  718.   opts.separator "EX: #{$0} -i 192.168.2.43 -p 161 --brute"
  719.   opts.separator ""
  720.   opts.separator "Options: "
  721.   # Assisted Modes
  722.   opts.on('-m', '--main', "\n\tStart in Main Menu".white) do |method|
  723.     options[:method] = 1
  724.   end
  725.   opts.on('-r', '--recon', "\n\tSNMP Recon & Discovery".white) do |method|
  726.     options[:method] = 2
  727.   end
  728.   opts.on('-b', '--brute', "\n\tCommunity String Bruteforcer".white) do |method|
  729.     options[:method] = 3
  730.   end
  731.   opts.on('-h', '--help', "\n\tHelp Menu") do
  732.     cls
  733.     banner
  734.     puts
  735.     puts opts
  736.     puts
  737.     exit 69;
  738.   end
  739. end
  740. begin
  741.   foo = ARGV[0] || ARGV[0] = "-m"
  742.   optparse.parse!
  743.   mandatory = [:method]
  744.   missing = mandatory.select{ |param| options[param].nil? }
  745.   if not missing.empty?
  746.     cls
  747.     banner
  748.     puts
  749.     puts "Missing options: #{missing.join(', ')}"
  750.     puts optparse
  751.     exit 666;
  752.   end
  753. rescue OptionParser::InvalidOption, OptionParser::MissingArgument
  754.   cls
  755.   banner
  756.   puts
  757.   puts $!.to_s
  758.   puts
  759.   puts optparse
  760.   puts
  761.   exit 666;  
  762. end
  763. cls
  764. banner
  765. @manager=nil
  766. case options[:method].to_i
  767. when 1
  768.   core_shell
  769. when 2
  770.   nmap_snmp
  771. when 3
  772.   snmp_brute
  773. end
  774. puts
  775. puts
  776. #EOF
Advertisement
Add Comment
Please, Sign In to add comment