Skip to content
This repository has been archived by the owner on Jan 21, 2021. It is now read-only.

Add support for Windows 10 v1803 to Invoke-ReflectivePEInjection #289

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from

Conversation

tonymeehan
Copy link

Summary

This change adds support for Windows 10 v1803 April 2018 Update to Invoke-ReflectivePEInjection.

Description

The latest update to Windows 10, RS4 (also called Windows 10 1803 or Windows 10 build 17134), introduced some changes that breaks Invoke-ReflectivePEInjection.

First, the GetMethod() lookup here to find GetProcAddress in kernel32.dll no longer works. It fails with the following error:

Exception calling "GetMethod" with "1" argument(s): "Ambiguous match found."

If you run GetMethods() on $UnsafeNativeMethods, you'll see there are two GetProcAddress results on Windows 10 v1803.

$UnsafeNativeMethods.GetMethods() | Out-File methods.txt
...
Name                       : GetProcAddress
DeclaringType              : Microsoft.Win32.UnsafeNativeMethods
ReflectedType              : Microsoft.Win32.UnsafeNativeMethods
MemberType                 : Method
MetadataToken              : 100663839
Module                     : System.dll
IsSecurityCritical         : True
IsSecuritySafeCritical     : True
IsSecurityTransparent      : False
MethodHandle               : System.RuntimeMethodHandle
Attributes                 : PrivateScope, Public, Static, HideBySig, PinvokeImpl
CallingConvention          : Standard
ReturnType                 : System.IntPtr
ReturnTypeCustomAttributes : IntPtr 
ReturnParameter            : IntPtr 
IsGenericMethod            : False
IsGenericMethodDefinition  : False
ContainsGenericParameters  : False
MethodImplementationFlags  : PreserveSig
IsPublic                   : True
IsPrivate                  : False
IsFamily                   : False
IsAssembly                 : False
IsFamilyAndAssembly        : False
IsFamilyOrAssembly         : False
IsStatic                   : True
IsFinal                    : False
IsVirtual                  : False
IsHideBySig                : True
IsAbstract                 : False
IsSpecialName              : False
IsConstructor              : False
CustomAttributes           : {[System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint = 
                             "GetProcAddress", CharSet = 2, ExactSpelling = True, SetLastError = True, PreserveSig = True, 
                             CallingConvention = 1, BestFitMapping = False, ThrowOnUnmappableChar = False)], 
                             [System.Runtime.InteropServices.PreserveSigAttribute()]}

Name                       : GetProcAddress
DeclaringType              : Microsoft.Win32.UnsafeNativeMethods
ReflectedType              : Microsoft.Win32.UnsafeNativeMethods
MemberType                 : Method
MetadataToken              : 100663864
Module                     : System.dll
IsSecurityCritical         : True
IsSecuritySafeCritical     : True
IsSecurityTransparent      : False
MethodHandle               : System.RuntimeMethodHandle
Attributes                 : PrivateScope, Public, Static, HideBySig, PinvokeImpl
CallingConvention          : Standard
ReturnType                 : System.IntPtr
ReturnTypeCustomAttributes : IntPtr 
ReturnParameter            : IntPtr 
IsGenericMethod            : False
IsGenericMethodDefinition  : False
ContainsGenericParameters  : False
MethodImplementationFlags  : PreserveSig
IsPublic                   : True
IsPrivate                  : False
IsFamily                   : False
IsAssembly                 : False
IsFamilyAndAssembly        : False
IsFamilyOrAssembly         : False
IsStatic                   : True
IsFinal                    : False
IsVirtual                  : False
IsHideBySig                : True
IsAbstract                 : False
IsSpecialName              : False
IsConstructor              : False
CustomAttributes           : {[System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint = 
                             "GetProcAddress", CharSet = 2, ExactSpelling = False, SetLastError = False, PreserveSig = 
                             True, CallingConvention = 1, BestFitMapping = False, ThrowOnUnmappableChar = False)], 
                             [System.Runtime.InteropServices.PreserveSigAttribute()]}

The only apparent difference between the two is ExactSpelling. The solution here that appears to work on Windows 7 SP1 and newer and Windows Server 2k8 R2 and newer is to always select the first method to avoid the ambiguous match exception.

$GetProcAddress = $UnsafeNativeMethods.GetMethods() | Where {$_.Name -eq "GetProcAddress"} | Select-Object -first 1

The second issue is here. $Kern32Handle must be of type System.IntPtr instead of System.Runtime.InteropServices.HandleRef. This can be observed in the following exception:

Exception calling "Invoke" with "2" argument(s): "Object of type 'System.Runtime.InteropServices.HandleRef' cannot be
converted to type 'System.IntPtr'."

The solution to this problem is to try System.Runtime.InteropServices.HandleRef and fall back to System.IntPtr if there's an exception.

How was it tested?

I tested this on the following versions of Windows, but would definitely welcome more testing and validation that this is the best solution.

  • Windows 10 v1803 x64 (build 17134)
  • Windows 10 v1709 x64
  • Windows 10 v1607 x64
  • Windows 10 v1607 x86
  • Windows Server 2016 x64
  • Windows Server 2012 R2 x64
  • Windows Server 2008 R2 x64
  • Windows 8.1 x86
  • Windows 8.1 x64
  • Windows 7 SP1 x64
  • Windows 7 SP1 x86

@mr64bit
Copy link

mr64bit commented May 27, 2018

GetMethod has an overload that lets you tell it which function overload you want by supplying an array of types.

Changing line #1002 to this is a better fix.
$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress', [Type[]]@([System.Runtime.InteropServices.HandleRef], [String]))

@tonymeehan
Copy link
Author

Thanks @mr64bit I'll update the PR with your suggestion.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants