UnsafeNativeMethods

To perform a dynamic lookup of function addresses, the operating system provides two special Win32 APIs called GetModuleHandle and GetProcAddress.

GetModuleHandle obtains a handle to the specified DLL, which is the memory address of the DLL.

To find the address of a specific function we’ll pass the DLL handle, and the function name to GetProcAddress, which will return the function address.

Searching preload assemblies with GetModuleHandle and GetProcAddress

$assemblies = [AppDomain]::CurrentDomain.GetAssemblies()

$assemblies | 
    ForEach-Object {
        $_.GlobalAssemblyCache
        $_.Location
        $_.GetTypes() | 
            ForEach-Object {
                $_ | Get-Member -static | Where-Object {
                    $_.TypeName.Contains('Unsafe') -and $_.Name.Contains('GetProcAddress') -or $_.Name.Contains('GetModuleHandle')
                } | Format-Table *
            } 2> $null 
    }

The code does not run in PowerShell Core asSystem.dll isn't installed into the Global Assembly Cache (GAC) there by default.

Lookup function address

function GetProcAddress {
    Param (
        [OutputType([IntPtr])]

        [Parameter( Position = 0, Mandatory = $true)]
        [String]
        $moduleName, 

        [Parameter( Position = 1, Mandatory = $true)]
        [String]
        $functionName
    )

    # Get reference to System.dll in the GAC
    $sysassembly = [System.AppDomain]::CurrentDomain.GetAssemblies() | Where-Object {
        $_.GlobalAssemblyCache -and $_.Location.Split('\\')[-1] -eq 'System.dll'
    }

    $types = $sysassembly.GetTypes()
    $unsafenativemethods = ForEach ($type in $types) {
        $type | Where-Object {$_.FullName -like '*NativeMethods' -and $_.Fullname -like '*Win32*' -and $_.Fullname -like '*Un*'}
    }

    # Get reference to GetModuleHandle and GetProcAddress methods
    $modulehandle = $unsafenativemethods.GetMethods() | Where-Object {$_.Name -like '*Handle' -and $_.Name -like '*Module*'}
    $procaddress = $unsafenativemethods.GetMethods() | Where-Object {$_.Name -like '*Address' -and $_.Name -like '*Proc*'} | Select-Object -First 1

    # Get handle on module specified
    $module = $modulehandle.Invoke($null, @($moduleName))
    $procaddress.Invoke($null, @($module, $functionName))
}

Next steps

pageDelegateType Reflection

Last updated