# DelegateType Reflection

## getDelegationType

```powershell
function getDelegateType {

	Param (
		[Parameter(Position = 0, Mandatory = $True)] [Type[]] $func,
		[Parameter(Position = 1)] [Type] $delType = [Void]
	)

	$type = [AppDomain]::CurrentDomain.
    DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), 
    [System.Reflection.Emit.AssemblyBuilderAccess]::Run).
      DefineDynamicModule('InMemoryModule', $false).
      DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', 
      [System.MulticastDelegate])

  $type.
    DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $func).
      SetImplementationFlags('Runtime, Managed')

  $type.
    DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $delType, $func).
      SetImplementationFlags('Runtime, Managed')

	return $type.CreateType()
}
```

## Notes and other stuff

Creating new delegate type for GetUserName method in Advapi32.dll

{% embed url="<https://www.pinvoke.net/default.aspx/advapi32.getusername>" %}

Getting to understand the parameters in PowerShell. First using Add-Type to create a delegate type for me.

> Add-Type creates the delegation type when the assembly is compiled, but we will need to create this manually.&#x20;

```powershell
# pinvoke C# 
$Advapi32 = @"
using System;
using System.Runtime.InteropServices;

public class Advapi32 {
    [DllImport("advapi32.dll", SetLastError = true)]
    static extern bool GetUserName(System.Text.StringBuilder sb, ref Int32 length);
}
"@

Add-Type $Advapi32
```

Now we can view our current loaded assemblies.

```powershell
# Get loaded assembly
[System.AppDomain]::CurrentDomain.GetAssemblies() | Sort-Object -Property FullName | Format-Table FullName
```

<figure><img src="/files/XcclQyUydVgxd00cnr0D" alt=""><figcaption><p>Output from Get loaded assembly</p></figcaption></figure>

View parameter types for GetUserName method.&#x20;

```powershell
# getting the parameters for delatetype
([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.FullName.Contains('wtw02iqk')}) | ForEach-Object {
    $_.GetTypes() | ForEach-Object {
        $_.GetMethod('GetUserName').GetParameters()
    } 2> $null
}
```

<figure><img src="/files/fSqkCvqmg4aGEIQGewtm" alt=""><figcaption><p>Output from # getting the parameters for delatetype</p></figcaption></figure>

{% hint style="info" %}
System.Int32& --> <https://learn.microsoft.com/en-us/dotnet/api/system.type.makebyreftype?view=net-7.0#remarks>

For Ref need to use \[Int].MakeByRefType()
{% endhint %}

Using getDelegateType function to create new delegate type for GetUserName

```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))
}

function getDelegateType {

	Param (
		[Parameter(Position = 0, Mandatory = $True)] [Type[]] $func,
		[Parameter(Position = 1)] [Type] $delType = [Void]
	)

	$type = [AppDomain]::CurrentDomain.
    DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), 
    [System.Reflection.Emit.AssemblyBuilderAccess]::Run).
      DefineDynamicModule('InMemoryModule', $false).
      DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', 
      [System.MulticastDelegate])

  $type.
    DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $func).
      SetImplementationFlags('Runtime, Managed')

  $type.
    DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $delType, $func).
      SetImplementationFlags('Runtime, Managed')

	return $type.CreateType()
}

$GetUserNameAddr = getProcAddress Advapi32.dll GetUserNameA
$GetUserNameDelegationType = getDelegateType @([System.Text.StringBuilder], [Int].MakeByRefType())

$GetUserName = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetUserNameAddr, $GetUserNameDelegationType)
$size = 64
$str = New-Object System.Text.StringBuilder -ArgumentList $size
$GetUserName.Invoke($str, [Ref]$size)
$str.ToString()
```

## Other examples

### LoadLibrary

Getting to understand the delegate type:

{% hint style="info" %}
Add-Type creates the delegation type when the assembly is compiled, but we will need to create this manually.&#x20;
{% endhint %}

{% code overflow="wrap" %}

```powershell
public class rfc {
 [DllImport("kernel32")]
 public static extern IntPtr LoadLibrary(string name);
}

$n32 = [System.Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($a))
Add-Type $n32

([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.FullName.Contains('h2a3zadd')}) | ForEach-Object {
     $_.GetTypes() | ForEach-Object {
         $_.GetMethod('LoadLibrary').GetParameters()
     } 2> $null
 }
```

{% endcode %}

<figure><img src="/files/02socO553VeLEg9OIND1" alt=""><figcaption></figcaption></figure>

Confirming our delegate type:&#x20;

<figure><img src="/files/3ve9ebaJUJccBgctObS2" alt=""><figcaption></figcaption></figure>

Final code to call LoadLibrary

{% code overflow="wrap" %}

```powershell
$LoadLibraryAddr = getProcAddress 'kernel32.dll' 'LoadLibraryA'
# HMODULE LoadLibraryA(
#    [in] LPCSTR lpLibFileName
#    );
$LoadLibraryDelegate = getDelegateType @([System.String]) IntPtr
$LoadLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LoadLibraryAddr, $LoadLibraryDelegate)

$LoadLibrary.Invoke("a"+"msi."+"dll")
```

{% endcode %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://rfc1918.gitbook.io/offsec/execution/powershell/c-assembly-in-powershell/delegatetype-reflection.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
