Skip to content

Instantly share code, notes, and snippets.

@mcharo
Last active September 3, 2019 22:49
Show Gist options
  • Save mcharo/8f97259ceaca89c3e00e316ece1032f9 to your computer and use it in GitHub Desktop.
Save mcharo/8f97259ceaca89c3e00e316ece1032f9 to your computer and use it in GitHub Desktop.
PowerShell Reflection
function Get-NativeMethods
{
[CmdletBinding()]
param(
[switch]$Unsafe
)
$Type = 'Microsoft.Win32.NativeMethods'
if ($Unsafe)
{
$Type = 'Microsoft.Win32.UnsafeNativeMethods'
}
$SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }
$SystemAssembly.GetType($Type)
}
function Get-ProcedureAddress
{
[CmdletBinding()]
param(
[OutputType([IntPtr])]
[Parameter(Position = 0, Mandatory = $True)]
[String]$Module,
[Parameter(Position = 1, Mandatory = $True)]
[String]$Procedure
)
$UnsafeNativeMethods = Get-NativeMethods -Unsafe
$ModuleHandle = $UnsafeNativeMethods::GetModuleHandle($Module)
$tmpPtr = New-Object IntPtr
$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $ModuleHandle)
# Return the address of the function
Write-Output $UnsafeNativeMethods::GetProcAddress([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure)
}
function Get-DelegateType
{
param(
[OutputType([Type])]
[Parameter(Position = 0)]
[Type[]]$Parameters = (New-Object Type[](0)),
[Parameter(Position = 1)]
[Type]$ReturnType = [Void]
)
$Domain = [AppDomain]::CurrentDomain
$DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate')
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
$TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
$ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
Write-Output $TypeBuilder.CreateType()
}
function Get-PinvokeMethod
{
[CmdletBinding()]
param(
$Module,
$Method,
$Parameters,
$ReturnType
)
$MethodAddr = Get-ProcedureAddress -Module $Module -Procedure $Method
$MethodDelegate = Get-DelegateType -Parameters $Parameters -ReturnType $ReturnType
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($MethodAddr, $MethodDelegate)
}
function ConvertTo-Enum
{
[CmdletBinding()]
param(
[string]$Name,
[Parameter(ValueFromPipeline = $true)]
[hashtable]$Hashtable
)
$Domain = [AppDomain]::CurrentDomain
$DynamicAssembly = New-Object System.Reflection.AssemblyName('DynamicAssembly')
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynamicAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('DynamicModule', $false)
$ConstructorInfo = [System.Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0]
$TypeBuilder = $ModuleBuilder.DefineEnum($Name, 'Public', [UInt16])
ForEach ($Key in $Hashtable.Keys)
{
Write-Verbose "Attempting to add $Key = $($Hashtable[$Key])"
$TypeBuilder.DefineLiteral($Key, $Hashtable[$Key]) | Out-Null
}
$TypeBuilder.CreateType()
}
$NativeMethods = Get-NativeMethods
$UnsafeNativeMethods = Get-NativeMethods -Unsafe
$ShowWindowAsync = Get-PinvokeMethod -Module user32.dll -Method ShowWindowAsync -Parameters IntPtr, Int32 -ReturnType Bool
$VirtualAlloc = Get-PinvokeMethod -Module kernel32.dll -Method VirtualAlloc -Parameters IntPtr, UInt32, UInt32, UInt32 -ReturnType IntPtr
$MachineType = @{
Native = [UInt16]0
I386 = [UInt16]0x014c
Itanium = [UInt16]0x0200
x64 = [UInt16]0x8664
} | ConvertTo-Enum -Name MachineType -Verbose
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment