# Leveraging UnsafeNativeMethods

**Using Dynamic Lookup**

* This approach dynamically resolves function addresses in memory.
* It relies on two key **Win32 API functions**:
  * **`GetModuleHandle`** – Obtains a handle (base address) to a loaded DLL.
  * **`GetProcAddress`** – Resolves a function’s memory address within a DLL.
* By using these APIs, we can locate functions **without Add-Type**, allowing pure in-memory execution.

#### **Finding Preloaded Assemblies in PowerShell**

Instead of creating a new assembly, we attempt to **reuse existing ones**. The following PowerShell script lists **preloaded assemblies** that may already contain the necessary methods:

```powershell
$Assemblies = [AppDomain]::CurrentDomain.GetAssemblies() 
 
$Assemblies | 
  ForEach-Object { 
    $_.GetTypes() | 
      ForEach-Object { 
          $_ | Get-Member -Static | Where-Object { 
            $_.TypeName.Contains('Unsafe') 
          } 
      } 2> $null 
    } 
```

* This script **iterates through all loaded assemblies** and filters for types containing `Unsafe`.
* The goal is to identify an existing assembly that **already contains** `GetModuleHandle` and `GetProcAddress`.

#### **Extracting Functions from System.dll**

From the analysis, we discover that `GetModuleHandle` and `GetProcAddress` exist inside **`Microsoft.Win32.UnsafeNativeMethods`**, which is part of **System.dll**.

We retrieve a reference to this assembly dynamically:

```powershell
$systemdll = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object {  
  $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }) 
   
$unsafeObj = $systemdll.GetType('Microsoft.Win32.UnsafeNativeMethods') 
```

* **Step 1**: Filters assemblies from the **Global Assembly Cache (GAC)**.
* **Step 2**: Identifies `System.dll` as the assembly containing `UnsafeNativeMethods`.
* **Step 3**: Retrieves a reference to `Microsoft.Win32.UnsafeNativeMethods` using `GetType()`.

#### **Resolving Function Addresses**

**Here we are finding the address of the user32.dll using GetModuleHandle**

```powershell
$systemdll = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object {  
$_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }) 
$unsafeObj = $systemdll.GetType('Microsoft.Win32.UnsafeNativeMethods') 
$GetModuleHandle = $unsafeObj.GetMethod('GetModuleHandle') 

$GetModuleHandle.Invoke($null, @("user32.dll")) 
```

Now we try to find GetProcAddress

```
$GetModuleHandle = $unsafeObj.GetMethod('GetProcAddress')

 # this wont work due to a error
 
 
 # But when we use t search. 
$unsafeObj.GetMethods() | ForEach-Object {If($_.Name -eq "GetProcAddress") {$_}} 


Name                       : GetProcAddress
DeclaringType              : Microsoft.Win32.UnsafeNativeMethods
ReflectedType              : Microsoft.Win32.UnsafeNativeMethods
MemberType                 : Method
MetadataToken              : 100663840
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 
```

Combining all together

```powershell
$systemdll = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object {  
$_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }) 
$unsafeObj = $systemdll.GetType('Microsoft.Win32.UnsafeNativeMethods') 
$GetModuleHandle = $unsafeObj.GetMethod('GetModuleHandle') 

$user32 = $GetModuleHandle.Invoke($null, @("user32.dll"))

$tmp=@() 
$unsafeObj.GetMethods() | ForEach-Object {If($_.Name -eq "GetProcAddress") {$tmp+=$_}} 
$GetProcAddress = $tmp[0] 
$GetProcAddress.Invoke($null, @($user32, "MessageBoxA"))

```

Powershell Function to find a module.

```powershell
function LookupFunc { 
Param ($moduleName, $functionName) 
$assem = ([AppDomain]::CurrentDomain.GetAssemblies() |  
Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1]. 
Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods') 
$tmp=@() 
$assem.GetMethods() | ForEach-Object {If($_.Name -eq "GetProcAddress") {$tmp+=$_}} 
return $tmp[0].Invoke($null, @(($assem.GetMethod('GetModuleHandle')).Invoke($null, 
@($moduleName)), $functionName)) 
} 
```

#### **Creating a Delegate Type Using Reflection**

Since PowerShell does not support `delegate`, we manually **define an assembly, module, and type in memory**.

**Step 1: Create an Assembly Object**

We first create an in-memory assembly:

```powershell
$MyAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate')
```

* This assembly will hold our dynamically created delegate type​.

**Step 2: Define a Dynamic Module**

We set up the assembly to run in memory:

```powershell
$Domain = [AppDomain]::CurrentDomain
$MyAssemblyBuilder = $Domain.DefineDynamicAssembly($MyAssembly,  
  [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
$MyModuleBuilder = $MyAssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
```

* **No disk artifacts** are created, increasing stealth​.

**Step 3: Define a Custom Delegate Type**

To match `MessageBoxA`'s function signature, we create a **custom type** inheriting from `MulticastDelegate`:

```powershell
$MyTypeBuilder = $MyModuleBuilder.DefineType('MyDelegateType',  
  'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
```

* `MulticastDelegate` is used because it allows multiple parameters​.

**Step 4: Define the Constructor**

We now specify the function's **expected arguments**:

```powershell
$MyConstructorBuilder = $MyTypeBuilder.DefineConstructor( 
  'RTSpecialName, HideBySig, Public',  
    [System.Reflection.CallingConventions]::Standard,  
      @([IntPtr], [String], [String], [int]))
$MyConstructorBuilder.SetImplementationFlags('Runtime, Managed')
```

* This constructor defines `MessageBoxA`'s expected arguments​.

**Step 5: Define the Invoke Method**

Next, we define the actual **Invoke** method to match `MessageBoxA`:

```powershell
$MyMethodBuilder = $MyTypeBuilder.DefineMethod('Invoke',  
  'Public, HideBySig, NewSlot, Virtual',  
    [int],  
      @([IntPtr], [String], [String], [int]))
$MyMethodBuilder.SetImplementationFlags('Runtime, Managed')
```

* This ensures that our delegate can be **invoked just like a normal function**​.

**Step 6: Instantiate the Delegate Type**

Finally, we create the delegate type:

```powershell
$MyDelegateType = $MyTypeBuilder.CreateType()
```

* This **dynamically generates a new delegate** without writing to disk​.

***

#### **Using the Delegate Type to Call `MessageBoxA`**

Now that we have a custom delegate, we can **map the function pointer to it**:

```powershell
$MessageBoxA = LookupFunc user32.dll MessageBoxA
$MyFunction = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer(
    $MessageBoxA, $MyDelegateType)
```

* `GetDelegateForFunctionPointer` takes:
  1. **Resolved memory address of `MessageBoxA`**.
  2. **Custom delegate type defining its argument structure**.

To call `MessageBoxA`, we invoke our delegate:

```powershell
$MyFunction.Invoke([IntPtr]::Zero, "Hello World", "This is My MessageBox", 0)
```

* This produces a **MessageBox popup**, confirming that the function was invoked successfully​.

## Final Code

```powershell
function LookupFunc { 
 
    Param ($moduleName, $functionName) 
 
    $assem = ([AppDomain]::CurrentDomain.GetAssemblies() |  
    Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1]. 
      Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods') 
    $tmp=@() 
    $assem.GetMethods() | ForEach-Object {If($_.Name -eq "GetProcAddress") {$tmp+=$_}} 
    return $tmp[0].Invoke($null, @(($assem.GetMethod('GetModuleHandle')).Invoke($null, 
@($moduleName)), $functionName)) 
} 
 
$MessageBoxA = LookupFunc user32.dll MessageBoxA 
$MyAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate') 
$Domain = [AppDomain]::CurrentDomain 
$MyAssemblyBuilder = $Domain.DefineDynamicAssembly($MyAssembly,  
  [System.Reflection.Emit.AssemblyBuilderAccess]::Run) 
$MyModuleBuilder = $MyAssemblyBuilder.DefineDynamicModule('InMemoryModule', $false) 
$MyTypeBuilder = $MyModuleBuilder.DefineType('MyDelegateType',  
  'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate]) 
 
$MyConstructorBuilder = $MyTypeBuilder.DefineConstructor( 
  'RTSpecialName, HideBySig, Public',  
    [System.Reflection.CallingConventions]::Standard,  
      @([IntPtr], [String], [String], [int])) 
$MyConstructorBuilder.SetImplementationFlags('Runtime, Managed') 
$MyMethodBuilder = $MyTypeBuilder.DefineMethod('Invoke',  
  'Public, HideBySig, NewSlot, Virtual',  
    [int],  
      @([IntPtr], [String], [String], [int])) 
$MyMethodBuilder.SetImplementationFlags('Runtime, Managed') 
$MyDelegateType = $MyTypeBuilder.CreateType() 
 
$MyFunction = [System.Runtime.InteropServices.Marshal]:: 
    GetDelegateForFunctionPointer($MessageBoxA, $MyDelegateType) 
$MyFunction.Invoke([IntPtr]::Zero,"Hello World","This is My MessageBox",0)
```
