# 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="https://1029482190-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVonnsWh96xLbzU5ncJWZ%2Fuploads%2FMLcV4wPFH30jCNAOnFXn%2Fimage.png?alt=media&#x26;token=5504ca97-7738-4e9d-aca4-2c4cbfff022e" 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="https://1029482190-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVonnsWh96xLbzU5ncJWZ%2Fuploads%2FPxOAR8tLETDDy1Gyfhvt%2Fimage.png?alt=media&#x26;token=c7117dbe-becd-4995-8325-2e96afe17281" 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="https://1029482190-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVonnsWh96xLbzU5ncJWZ%2Fuploads%2FPPdFaXhZAyFQnMkMRGt3%2Fimage.png?alt=media&#x26;token=df27a402-6b06-4926-8a23-f0238dd3248f" alt=""><figcaption></figcaption></figure>

Confirming our delegate type:&#x20;

<figure><img src="https://1029482190-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVonnsWh96xLbzU5ncJWZ%2Fuploads%2Fs5im8qLPHq56sVm3bbrw%2Fimage.png?alt=media&#x26;token=37217e82-2907-4a00-8da0-24f2952cc150" 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 %}
