> For the complete documentation index, see [llms.txt](https://rfc1918.gitbook.io/offsec/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://rfc1918.gitbook.io/offsec/execution/powershell/c-assembly-in-powershell/unsafenativemethods.md).

# UnsafeNativeMethods

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

{% hint style="info" %}
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.
{% endhint %}

## Searching preload assemblies with GetModuleHandle and GetProcAddress

```powershell
$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 
    }
```

<figure><img src="/files/y0r70LUht1diMSYWwQ8f" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
The code does not run in *PowerShell Core* as`System.dll` isn't installed into the Global Assembly Cache (GAC) there by default.
{% endhint %}

## Lookup function address

```powershell
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

{% content-ref url="/pages/RABbZsHcpwpaeXvJA0Li" %}
[DelegateType Reflection](/offsec/execution/powershell/c-assembly-in-powershell/delegatetype-reflection.md)
{% endcontent-ref %}
