Created
November 2, 2015 04:44
-
-
Save franklesniak/3fe7c80f93193521c5d5 to your computer and use it in GitHub Desktop.
I was hoping to use reflection to invoke the native DhcpRequestParams function, but I am getting an error: Exception calling "LoadFile" with "1" argument(s): "The module was expected to contain an assembly manifest.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
############################################################################## | |
## | |
## Invoke-WindowsApi.ps1 | |
## | |
## Invoke a native Windows API call that takes and returns simple data types. | |
## | |
## ie: | |
## | |
## | |
## Prepare the parameter types and parameters for the | |
## CreateHardLink function | |
## $parameterTypes = [string], [string], [IntPtr] | |
## $parameters = [string] $filename, [string] $existingFilename, $null | |
## | |
## | |
## Call the CreateHardLink method in the Kernel32 DLL | |
## $result = Invoke-WindowsApi "kernel32" ([bool]) "CreateHardLink" ` | |
## $parameterTypes $parameters | |
## | |
############################################################################## | |
function Invoke-WindowsAPI | |
{ | |
param | |
( | |
[string] $dllName, | |
[Type] $returnType, | |
[string] $methodName, | |
[Type[]] $parameterTypes, | |
[Object[]] $parameters | |
) | |
## Begin to build the dynamic assembly | |
$domain = [AppDomain]::CurrentDomain | |
$name = New-Object Reflection.AssemblyName 'PInvokeAssembly' | |
$assembly = $domain.DefineDynamicAssembly($name, 'Run') | |
$module = $assembly.DefineDynamicModule('PInvokeModule') | |
$type = $module.DefineType('PInvokeType', "Public,BeforeFieldInit") | |
## Go through all of the parameters passed to us. As we do this, | |
## we clone the user's inputs into another array that we will use for | |
## the P/Invoke call. | |
$inputParameters = @() | |
$refParameters = @() | |
for ($counter = 1; $counter -le $parameterTypes.Length; $counter++) | |
{ | |
## If an item is a PSReference, then the user | |
## wants an [out] parameter. | |
if ($parameterTypes[$counter - 1] -eq [Ref]) | |
{ | |
## Remember which parameters are used for [Out] parameters | |
$refParameters += $counter | |
## On the cloned array, we replace the PSReference type with the | |
## .Net reference type that represents the value of the PSReference, | |
## and the value with the value held by the PSReference. | |
$parameterTypes[$counter - 1] = $parameters[$counter - 1].Value.GetType().MakeByRefType() | |
$inputParameters += $parameters[$counter - 1].Value | |
} | |
else | |
{ | |
## Otherwise, just add their actual parameter to the | |
## input array. | |
$inputParameters += $parameters[$counter - 1] | |
} | |
} | |
## Define the actual P/Invoke method, adding the [Out] | |
## attribute for any parameters that were originally [Ref] | |
## parameters. | |
$method = $type.DefineMethod($methodName, 'Public,HideBySig,Static,PinvokeImpl', $returnType, $parameterTypes) | |
foreach($refParameter in $refParameters) | |
{ | |
[void] $method.DefineParameter($refParameter, "Out", $null) | |
} | |
## Apply the P/Invoke constructor | |
$ctor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([string]) | |
$attr = New-Object Reflection.Emit.CustomAttributeBuilder $ctor, $dllName | |
$method.SetCustomAttribute($attr) | |
## Create the temporary type, and invoke the method. | |
$realType = $type.CreateType() | |
$realType.InvokeMember($methodName, 'Public,Static,InvokeMethod', $null, $null, $inputParameters) | |
## Finally, go through all of the reference parameters, and update the | |
## values of the PSReference objects that the user passed in. | |
foreach ($refParameter in $refParameters) | |
{ | |
$parameters[$refParameter - 1].Value = $inputParameters[$refParameter - 1] | |
} | |
} | |
# See http://www.exploit-monday.com/2012/07/structs-and-enums-using-reflection.html | |
# See http://poshcode.org/2189 | |
$Domain = [AppDomain]::CurrentDomain | |
$DynAssembly = New-Object System.Reflection.AssemblyName('DHCPClientAPI') | |
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) | |
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('DHCPClientAPIModule', $False) | |
#################################################################################### | |
# Create DhcpRequestFlags enum | |
$EnumBuilder = $ModuleBuilder.DefineEnum('DhcpRequestFlags', 'Public', [UInt32]) | |
# Define values of the enum | |
$EnumBuilder.DefineLiteral('DHCPCAPI_REQUEST_PERSISTENT', [UInt32] 0x01) | Out-Null | |
$EnumBuilder.DefineLiteral('DHCPCAPI_REQUEST_SYNCHRONOUS', [UInt32] 0x02) | Out-Null | |
$EnumBuilder.DefineLiteral('DHCPCAPI_REQUEST_ASYNCHRONOUS', [UInt32] 0x04) | Out-Null | |
$EnumBuilder.DefineLiteral('DHCPCAPI_REQUEST_CANCEL', [UInt32] 0x08) | Out-Null | |
$EnumBuilder.DefineLiteral('DHCPCAPI_REQUEST_MASK', [UInt32] 0x0F) | Out-Null | |
$DhcpRequestFlagsType = $EnumBuilder.CreateType() | |
#################################################################################### | |
# Create DHCPCAPI_PARAMS struct | |
$Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' | |
# There is no such thing as a DefineStruct type. So define a type with the attributes of a struct. | |
# A struct is essentially a class with no methods. | |
$TypeBuilder = $ModuleBuilder.DefineType('DHCPCAPI_PARAMS', $Attributes, [System.ValueType], 1, 0x40) | |
$TypeBuilder.DefineField('Flags', [UInt32], 'Public') | Out-Null | |
$TypeBuilder.DefineField('OptionId', [UInt32], 'Public') | Out-Null | |
$IsVendorField = $TypeBuilder.DefineField('IsVendor', [Bool], 'Public, HasFieldMarshal') | |
$ConstructorInfo = [System.Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0] | |
$ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::Bool | |
$AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue) | |
$IsVendorField.SetCustomAttribute($AttribBuilder) | |
#$TypeBuilder.DefineField('Data', [IntPtr], 'Public') | Out-Null | |
$TypeBuilder.DefineField('Data', [Byte], 'Public') | Out-Null | |
$TypeBuilder.DefineField('nBytesData', [UInt32], 'Public') | Out-Null | |
$DHCPCAPI_PARAMSType = $TypeBuilder.CreateType() | |
#################################################################################### | |
# Create DHCPCAPI_PARAMS_ARRAY struct | |
$Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' | |
# There is no such thing as a DefineStruct type. So define a type with the attributes of a struct. | |
# A struct is essentially a class with no methods. | |
$TypeBuilder = $ModuleBuilder.DefineType('DHCPCAPI_PARAMS_ARRAY', $Attributes, [System.ValueType], 1, 0x40) | |
$TypeBuilder.DefineField('nParams', [UInt32], 'Public') | Out-Null | |
$TypeBuilder.DefineField('Params', [DHCPCAPI_PARAMS], 'Public') | Out-Null | |
$DHCPCAPI_PARAMS_ARRAYType = $TypeBuilder.CreateType() | |
#################################################################################### | |
$sendParams = New-Object DHCPCAPI_PARAMS_ARRAY | |
$sendParams.nParams = 0 | |
$recv = New-Object DHCPCAPI_PARAMS | |
$recv.Flags = 0x0 | |
$recv.OptionId = 245 | |
$recv.IsVendor = $false | |
$recv.nBytesData = 0 | |
$recdParams = New-Object DHCPCAPI_PARAMS_ARRAY | |
$recdParams.nParams = 1 | |
$recdParams.Params = $recv | |
[UInt32]$flags = $DhcpRequestFlagsType::DHCPCAPI_REQUEST_SYNCHRONOUS.value__ | |
$buffer = New-Object byte[] 1024 | |
$types = @([UInt32], [IntPtr], [string], [IntPtr], [DHCPCAPI_PARAMS_ARRAY], [DHCPCAPI_PARAMS_ARRAY], [Byte[]], [uint32], [IntPtr]) | |
$params = @($flags, [IntPtr]::Zero, "{6362DADD-53D1-48DB-83B8-F1C79B3D1036}", [IntPtr]::Zero, $sendParams, $recdParams, $buffer, 1024, [IntPtr]::Zero) | |
$result = Invoke-WindowsAPI "dhcpcsvc" ([int32]) "DhcpRequestParams" $types $params |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment