diff --git a/bindings/powershell/Invoke-Keystone.ps1 b/bindings/powershell/Invoke-Keystone.ps1 deleted file mode 100644 index e3f4226b8c978eddd4ec806ddc5a251a80da5f77..0000000000000000000000000000000000000000 --- a/bindings/powershell/Invoke-Keystone.ps1 +++ /dev/null @@ -1,327 +0,0 @@ -function Invoke-Keystone { -<# -.SYNOPSIS - Powershell wrapper for Keystone (using inline C#). - - In effect the function directly parses the Keystone dll so it can support any - features implemented by Keystone so long as function calls are prototyped in C#. - -.DESCRIPTION - Author: Ruben Boonen (@FuzzySec) - License: BSD 3-Clause - Required Dependencies: None - Optional Dependencies: None - -.EXAMPLE - - # Support for multi-line code blocks - PS C:\> $Code = @" - >> sub esp, 200 - >> pop eax - >> pop ecx - >> ret - >> "@ - PS C:\> Invoke-Keystone -Architecture X86 -Mode 32 -Code $Code - - Bytes : 9 - Instructions : 4 - PSArray : {0x81, 0xEC, 0xC8, 0x00...} - CArray : {\x81, \xEC, \xC8, \x00...} - RawArray : {81, EC, C8, 00...} - -.EXAMPLE - - # Invoke-Keystone emits objects - PS C:\> $Code = @" - >> sub esp, 200 - >> pop eax - >> pop ecx - >> ret - >> "@ - PS C:\> $Object = Invoke-Keystone -Architecture X86 -Mode 32 -Code $Code - PS C:\> $Object.RawArray -join "" - 81ECC80000005859C3 - PS C:\> $Object.CArray -join "" - \x81\xEC\xC8\x00\x00\x00\x58\x59\xC3 - PS C:\> "`$Shellcode = {" + $($Object.PSArray -join ", ") + "}" - $Shellcode = {0x81, 0xEC, 0xC8, 0x00, 0x00, 0x00, 0x58, 0x59, 0xC3} - -#> - - param( - [Parameter(Mandatory = $True)] - [ValidateSet( - 'ARM', - 'ARM64', - 'MIPS', - 'X86', - 'PPC', - 'SPARC', - 'SYSZ', - 'HEXAGON', - 'MAX') - ] - [String]$Architecture, - - [Parameter(Mandatory = $True)] - [ValidateSet( - 'Little_Endian', - 'Big_Endian', - 'ARM', - 'THUMB', - 'V8', - 'MICRO', - 'MIPS3', - 'MIPS32R6', - 'MIPS32', - 'MIPS64', - '16', - '32', - '64', - 'PPC32', - 'PPC64', - 'QPX', - 'SPARC32', - 'SPARC64', - 'V9') - ] - [String]$Mode, - - [Parameter(Mandatory = $True)] - [string]$Code, - - [Parameter(Mandatory = $False)] - [String]$Syntax = "Intel" - ) - - Add-Type -TypeDefinition @" - using System; - using System.Diagnostics; - using System.Runtime.InteropServices; - using System.Security.Principal; - - [Flags] - public enum ks_err : int - { - KS_ERR_OK = 0, /// No error: everything was fine - KS_ERR_NOMEM, /// Out-Of-Memory error: ks_open(), ks_emulate() - KS_ERR_ARCH, /// Unsupported architecture: ks_open() - KS_ERR_HANDLE, /// Invalid handle - KS_ERR_MODE, /// Invalid/unsupported mode: ks_open() - KS_ERR_VERSION, /// Unsupported version (bindings) - KS_ERR_OPT_INVALID, /// Unsupported option - - /// generic input assembly errors - parser specific - KS_ERR_ASM_EXPR_TOKEN = 128, /// unknown token in expression - KS_ERR_ASM_DIRECTIVE_VALUE_RANGE, /// literal value out of range for directive - KS_ERR_ASM_DIRECTIVE_ID, /// expected identifier in directive - KS_ERR_ASM_DIRECTIVE_TOKEN, /// unexpected token in directive - KS_ERR_ASM_DIRECTIVE_STR, /// expected string in directive - KS_ERR_ASM_DIRECTIVE_COMMA, /// expected comma in directive - KS_ERR_ASM_DIRECTIVE_RELOC_NAME, /// expected relocation name in directive - KS_ERR_ASM_DIRECTIVE_RELOC_TOKEN, /// unexpected token in .reloc directive - KS_ERR_ASM_DIRECTIVE_FPOINT, /// invalid floating point in directive - KS_ERR_ASM_DIRECTIVE_UNKNOWN, /// unknown directive - KS_ERR_ASM_DIRECTIVE_EQU, /// invalid equal directive - KS_ERR_ASM_DIRECTIVE_INVALID, /// (generic) invalid directive - KS_ERR_ASM_VARIANT_INVALID, /// invalid variant - KS_ERR_ASM_EXPR_BRACKET, /// brackets expression not supported on this target - KS_ERR_ASM_SYMBOL_MODIFIER, /// unexpected symbol modifier following '@' - KS_ERR_ASM_SYMBOL_REDEFINED, /// invalid symbol redefinition - KS_ERR_ASM_SYMBOL_MISSING, /// cannot find a symbol - KS_ERR_ASM_RPAREN, /// expected ')' in parentheses expression - KS_ERR_ASM_STAT_TOKEN, /// unexpected token at start of statement - KS_ERR_ASM_UNSUPPORTED, /// unsupported token yet - KS_ERR_ASM_MACRO_TOKEN, /// unexpected token in macro instantiation - KS_ERR_ASM_MACRO_PAREN, /// unbalanced parentheses in macro argument - KS_ERR_ASM_MACRO_EQU, /// expected '=' after formal parameter identifier - KS_ERR_ASM_MACRO_ARGS, /// too many positional arguments - KS_ERR_ASM_MACRO_LEVELS_EXCEED, /// macros cannot be nested more than 20 levels deep - KS_ERR_ASM_MACRO_STR, /// invalid macro string - KS_ERR_ASM_MACRO_INVALID, /// invalid macro (generic error) - KS_ERR_ASM_ESC_BACKSLASH, /// unexpected backslash at end of escaped string - KS_ERR_ASM_ESC_OCTAL, /// invalid octal escape sequence (out of range) - KS_ERR_ASM_ESC_SEQUENCE, /// invalid escape sequence (unrecognized character) - KS_ERR_ASM_ESC_STR, /// broken escape string - KS_ERR_ASM_TOKEN_INVALID, /// invalid token - KS_ERR_ASM_INSN_UNSUPPORTED, /// this instruction is unsupported in this mode - KS_ERR_ASM_FIXUP_INVALID, /// invalid fixup - KS_ERR_ASM_LABEL_INVALID, /// invalid label - KS_ERR_ASM_FRAGMENT_INVALID, /// invalid fragment - - /// generic input assembly errors - architecture specific - KS_ERR_ASM_INVALIDOPERAND = 512, - KS_ERR_ASM_MISSINGFEATURE, - KS_ERR_ASM_MNEMONICFAIL, - } - - public static class Keystone - { - [DllImport("keystone.dll")] - public static extern ks_err ks_open( - int arch, - int mode, - ref IntPtr handle); - - [DllImport("keystone.dll")] - public static extern ks_err ks_option( - IntPtr handle, - int mode, - uint value); - - [DllImport("keystone.dll")] - public static extern int ks_asm( - IntPtr handle, - String assembly, - ulong address, - ref IntPtr encoding, - ref uint encoding_size, - ref uint stat_count); - - [DllImport("keystone.dll")] - public static extern ks_err ks_errno( - IntPtr handle); - - [DllImport("keystone.dll")] - public static extern ks_err ks_close( - IntPtr handle); - - [DllImport("keystone.dll")] - public static extern void ks_free( - IntPtr handle); - } -"@ - - # Architecture -> int - New-Variable -Option Constant -Name ks_arch -Value @{ - "ARM" = 1 - "ARM64" = 2 - "MIPS" = 3 - "X86" = 4 - # unsupported -> keystone.h - "PPC" = 5 - "SPARC" = 6 - "SYSZ" = 7 - "HEXAGON" = 8 - "MAX" = 9 - } - - # Mode -> int - New-Variable -Option Constant -Name ks_mode -Value @{ - "Little_Endian" = 0 - "Big_Endian" = 1073741824 - "ARM" = 1 - "THUMB" = 16 - "V8" = 64 - "MICRO" = 16 - "MIPS3" = 32 - "MIPS32R6" = 64 - "MIPS32" = 4 - "MIPS64" = 8 - "16" = 2 - "32" = 4 - "64" = 8 - "PPC32" = 4 - "PPC64" = 8 - "QPX" = 16 - "SPARC32" = 4 - "SPARC64" = 8 - "V9" = 16 - } - - New-Variable -Option Constant -Name ks_opt_value -Value @{ - "Intel" = 1 - "ATT" = 2 - "NASM" = 4 - # unsupported -> keystone.h - "MASM" = 8 - "GAS" = 16 - } - - # Asm Handle - $AsmHandle = [IntPtr]::Zero - - # Initialize Keystone with ks_open() - # Add a try/catch here to handle missing DLL - try { - $CallResult = [Keystone]::ks_open($ks_arch[$Architecture],$ks_mode[$Mode],[ref]$AsmHandle) - } catch { - if ($Error[0].FullyQualifiedErrorId -eq "DllNotFoundException") { - echo "`n[!] Missing Keystone DLL" - } else { - echo "`n[!] Exception: $($Error[0].FullyQualifiedErrorId)" - } - echo "[>] Quitting..`n" - Return - } - if ($CallResult -ne "KS_ERR_OK") { - if ($CallResult -eq "KS_ERR_MODE"){ - echo "`n[!] Invalid Architecture/Mode combination" - echo "[>] Quitting..`n" - } else { - echo "`n[!] cs_open error: $CallResult" - echo "[>] Quitting..`n" - } - Return - } - - # Only one ks_opt_type -> KS_OPT_SYNTAX = 1 - $CallResult = [Keystone]::ks_option($AsmHandle, 1, $ks_opt_value[$Syntax]) - if ($CallResult -ne "KS_ERR_OK") { - echo "`n[!] ks_option error: $CallResult" - echo "[>] Quitting..`n" - $CallResult = [Keystone]::ks_close($AsmHandle) - Return - } - - # Result variables - $Encoded = [IntPtr]::Zero - [int]$Encoded_size = 0 - [int]$Stat_count = 0 - - # Assemble instructions - $CallResult = [Keystone]::ks_asm($AsmHandle, $Code, 0, [ref]$Encoded, [ref]$Encoded_size, [ref]$stat_count) - - if ($CallResult -ne 0) { - echo "`n[!] ks_asm error: $([Keystone]::ks_errno($AsmHandle))" - echo "[>] Quitting..`n" - $CallResult = [Keystone]::ks_close($AsmHandle) - Return - } else { - $BufferOffset = $Encoded.ToInt64() - - if ($Encoded_size -gt 0) { - # PS/C# hex array - $PSArray = @() - # C-style hex array - $CArray = @() - # Raw hex array - $RawArray = @() - for ($i=0; $i -lt $Encoded_size; $i++) { - $PSArray += echo "0x$("{0:X2}" -f $([Runtime.InteropServices.Marshal]::ReadByte($BufferOffset)))" - $CArray += echo "\x$("{0:X2}" -f $([Runtime.InteropServices.Marshal]::ReadByte($BufferOffset)))" - $RawArray += echo "$("{0:X2}" -f $([Runtime.InteropServices.Marshal]::ReadByte($BufferOffset)))" - $BufferOffset = $BufferOffset+1 - } - # Result Object - $HashTable = @{ - Bytes = $Encoded_size - Instructions = $stat_count - PSArray = $PSArray - CArray = $CArray - RawArray = $RawArray - } - New-Object PSObject -Property $HashTable |Select-Object Bytes,Instructions,PSArray,CArray,RawArray - - # Clean up! - [Keystone]::ks_free($Encoded) - $CallResult = [Keystone]::ks_close($AsmHandle) - } else { - echo "`n[!] No bytes assembled" - echo "[>] Quitting..`n" - $CallResult = [Keystone]::ks_close($AsmHandle) - Return - } - } - -} \ No newline at end of file diff --git a/bindings/powershell/Keystone/Const/ks_arch_cons.cs b/bindings/powershell/Keystone/Const/ks_arch_cons.cs new file mode 100755 index 0000000000000000000000000000000000000000..fa1055fb3502a7d1b3f303e535e3d604ff620129 --- /dev/null +++ b/bindings/powershell/Keystone/Const/ks_arch_cons.cs @@ -0,0 +1,9 @@ +KS_ARCH_ARM = 1, +KS_ARCH_ARM64, +KS_ARCH_MIPS, +KS_ARCH_X86, +KS_ARCH_PPC, +KS_ARCH_SPARC, +KS_ARCH_SYSTEMZ, +KS_ARCH_HEXAGON, +KS_ARCH_MAX, \ No newline at end of file diff --git a/bindings/powershell/Keystone/Const/ks_err_cons.cs b/bindings/powershell/Keystone/Const/ks_err_cons.cs new file mode 100755 index 0000000000000000000000000000000000000000..6387facf2e61b58d4b06424a56f5e2be4adbefcf --- /dev/null +++ b/bindings/powershell/Keystone/Const/ks_err_cons.cs @@ -0,0 +1,46 @@ +KS_ERR_OK = 0, +KS_ERR_NOMEM, +KS_ERR_ARCH, +KS_ERR_HANDLE, +KS_ERR_MODE, +KS_ERR_VERSION, +KS_ERR_OPT_INVALID, +KS_ERR_ASM_EXPR_TOKEN = 128, +KS_ERR_ASM_DIRECTIVE_VALUE_RANGE, +KS_ERR_ASM_DIRECTIVE_ID, +KS_ERR_ASM_DIRECTIVE_TOKEN, +KS_ERR_ASM_DIRECTIVE_STR, +KS_ERR_ASM_DIRECTIVE_COMMA, +KS_ERR_ASM_DIRECTIVE_RELOC_NAME, +KS_ERR_ASM_DIRECTIVE_RELOC_TOKEN, +KS_ERR_ASM_DIRECTIVE_FPOINT, +KS_ERR_ASM_DIRECTIVE_UNKNOWN, +KS_ERR_ASM_DIRECTIVE_EQU, +KS_ERR_ASM_DIRECTIVE_INVALID, +KS_ERR_ASM_VARIANT_INVALID, +KS_ERR_ASM_EXPR_BRACKET, +KS_ERR_ASM_SYMBOL_MODIFIER, +KS_ERR_ASM_SYMBOL_REDEFINED, +KS_ERR_ASM_SYMBOL_MISSING, +KS_ERR_ASM_RPAREN, +KS_ERR_ASM_STAT_TOKEN, +KS_ERR_ASM_UNSUPPORTED, +KS_ERR_ASM_MACRO_TOKEN, +KS_ERR_ASM_MACRO_PAREN, +KS_ERR_ASM_MACRO_EQU, +KS_ERR_ASM_MACRO_ARGS, +KS_ERR_ASM_MACRO_LEVELS_EXCEED, +KS_ERR_ASM_MACRO_STR, +KS_ERR_ASM_MACRO_INVALID, +KS_ERR_ASM_ESC_BACKSLASH, +KS_ERR_ASM_ESC_OCTAL, +KS_ERR_ASM_ESC_SEQUENCE, +KS_ERR_ASM_ESC_STR, +KS_ERR_ASM_TOKEN_INVALID, +KS_ERR_ASM_INSN_UNSUPPORTED, +KS_ERR_ASM_FIXUP_INVALID, +KS_ERR_ASM_LABEL_INVALID, +KS_ERR_ASM_FRAGMENT_INVALID, +KS_ERR_ASM_INVALIDOPERAND = 512, +KS_ERR_ASM_MISSINGFEATURE, +KS_ERR_ASM_MNEMONICFAIL, \ No newline at end of file diff --git a/bindings/powershell/Keystone/Const/ks_mode_cons.cs b/bindings/powershell/Keystone/Const/ks_mode_cons.cs new file mode 100755 index 0000000000000000000000000000000000000000..97f64f561ef47eee4770faff83f2f4a4493d2cf5 --- /dev/null +++ b/bindings/powershell/Keystone/Const/ks_mode_cons.cs @@ -0,0 +1,19 @@ +KS_MODE_LITTLE_ENDIAN = 0, +KS_MODE_BIG_ENDIAN = 1 << 30, +KS_MODE_ARM = 1 << 0, +KS_MODE_THUMB = 1 << 4, +KS_MODE_V8 = 1 << 6, +KS_MODE_MICRO = 1 << 4, +KS_MODE_MIPS3 = 1 << 5, +KS_MODE_MIPS32R6 = 1 << 6, +KS_MODE_MIPS32 = 1 << 2, +KS_MODE_MIPS64 = 1 << 3, +KS_MODE_16 = 1 << 1, +KS_MODE_32 = 1 << 2, +KS_MODE_64 = 1 << 3, +KS_MODE_PPC32 = 1 << 2, +KS_MODE_PPC64 = 1 << 3, +KS_MODE_QPX = 1 << 4, +KS_MODE_SPARC32 = 1 << 2, +KS_MODE_SPARC64 = 1 << 3, +KS_MODE_V9 = 1 << 4, \ No newline at end of file diff --git a/bindings/powershell/Keystone/Const/ks_opt_value_cons.cs b/bindings/powershell/Keystone/Const/ks_opt_value_cons.cs new file mode 100755 index 0000000000000000000000000000000000000000..f904ad2e9e01f37d639f2a1ccbec3be0de30b118 --- /dev/null +++ b/bindings/powershell/Keystone/Const/ks_opt_value_cons.cs @@ -0,0 +1,5 @@ +KS_OPT_SYNTAX_INTEL = 1 << 0, +KS_OPT_SYNTAX_ATT = 1 << 1, +KS_OPT_SYNTAX_NASM = 1 << 2, +KS_OPT_SYNTAX_MASM = 1 << 3, +KS_OPT_SYNTAX_GAS = 1 << 4, \ No newline at end of file diff --git a/bindings/powershell/Keystone/Keystone.psd1 b/bindings/powershell/Keystone/Keystone.psd1 new file mode 100755 index 0000000000000000000000000000000000000000..be0172d56c26a970dfe7021a02cd04c51e9daa13 --- /dev/null +++ b/bindings/powershell/Keystone/Keystone.psd1 @@ -0,0 +1,25 @@ +@{ +# Script module or binary module file associated with this manifest. +ModuleToProcess = 'Keystone.psm1' + +# Version number of this module. +ModuleVersion = '0.0.0.1' + +# ID used to uniquely identify this module +GUID = 'd34db33f-7f65-4681-9cfb-0cf4929a8e68' + +# Author of this module +Author = 'Ruben Boonen' + +# Copyright statement for this module +Copyright = 'see COPYING' + +# Description of the functionality provided by this module +Description = 'Keystone Engine Binding Module' + +# Minimum version of the Windows PowerShell engine required by this module +PowerShellVersion = '2.0' + +# Functions to export from this module +FunctionsToExport = '*' +} diff --git a/bindings/powershell/Keystone/Keystone.psm1 b/bindings/powershell/Keystone/Keystone.psm1 new file mode 100755 index 0000000000000000000000000000000000000000..a34bfefe1924c7d23e6cf24917e59a31b44133a5 --- /dev/null +++ b/bindings/powershell/Keystone/Keystone.psm1 @@ -0,0 +1,304 @@ +function Get-KeystoneAssembly { +<# +.SYNOPSIS + Powershell wrapper for Keystone (using inline C#). + +.DESCRIPTION + Author: Ruben Boonen (@FuzzySec) + License: BSD 3-Clause + Required Dependencies: None + Optional Dependencies: None + +.PARAMETER Architecture + Architecture type. + +.PARAMETER Mode + Mode type. + +.PARAMETER Code + Assembly string, use ";" or multi-line variables for instruction separation. + +.PARAMETER Syntax + Syntax for input assembly. + +.PARAMETER Version + Print ASCII version banner. + +.EXAMPLE + + # Support for multi-line code blocks + PS C:\> $Code = @" + >> sub esp, 200 + >> pop eax + >> pop ecx + >> ret + >> "@ + PS C:\> Get-KeystoneAssembly -Architecture X86 -Mode 32 -Code $Code + + Bytes : 9 + Instructions : 4 + PSArray : {0x81, 0xEC, 0xC8, 0x00...} + CArray : {\x81, \xEC, \xC8, \x00...} + RawArray : {81, EC, C8, 00...} + +.EXAMPLE + + # Get-KeystoneAssembly emits objects + PS C:\> $Code = @" + >> sub esp, 200 + >> pop eax + >> pop ecx + >> ret + >> "@ + PS C:\> $Object = Get-KeystoneAssembly -Architecture X86 -Mode 32 -Code $Code + PS C:\> $Object.RawArray -join "" + 81ECC80000005859C3 + PS C:\> $Object.CArray -join "" + \x81\xEC\xC8\x00\x00\x00\x58\x59\xC3 + PS C:\> "`$Shellcode = {" + $($Object.PSArray -join ", ") + "}" + $Shellcode = {0x81, 0xEC, 0xC8, 0x00, 0x00, 0x00, 0x58, 0x59, 0xC3} + +#> + + param( + [Parameter(ParameterSetName='Keystone', Mandatory = $True)] + [ValidateSet( + 'KS_ARCH_ARM', + 'KS_ARCH_ARM64', + 'KS_ARCH_MIPS', + 'KS_ARCH_X86', + 'KS_ARCH_PPC', + 'KS_ARCH_SPARC', + 'KS_ARCH_SYSTEMZ', + 'KS_ARCH_HEXAGON', + 'KS_ARCH_MAX') + ] + [String]$Architecture, + + [Parameter(ParameterSetName='Keystone', Mandatory = $True)] + [ValidateSet( + 'KS_MODE_LITTLE_ENDIAN', + 'KS_MODE_BIG_ENDIAN', + 'KS_MODE_ARM', + 'KS_MODE_THUMB', + 'KS_MODE_V8', + 'KS_MODE_MICRO', + 'KS_MODE_MIPS3', + 'KS_MODE_MIPS32R6', + 'KS_MODE_MIPS32', + 'KS_MODE_MIPS64', + 'KS_MODE_16', + 'KS_MODE_32', + 'KS_MODE_64', + 'KS_MODE_PPC32', + 'KS_MODE_PPC64', + 'KS_MODE_QPX', + 'KS_MODE_SPARC32', + 'KS_MODE_SPARC64', + 'KS_MODE_V9') + ] + [String]$Mode, + + [Parameter(ParameterSetName='Keystone', Mandatory = $True)] + [ValidateNotNullOrEmpty()] + [string]$Code, + + [Parameter(ParameterSetName='Keystone', Mandatory = $False)] + [ValidateSet( + 'KS_OPT_SYNTAX_INTEL', + 'KS_OPT_SYNTAX_ATT', + 'KS_OPT_SYNTAX_NASM', + 'KS_OPT_SYNTAX_MASM', + 'KS_OPT_SYNTAX_GAS') + ] + [String]$Syntax = "KS_OPT_SYNTAX_INTEL", + + [Parameter(ParameterSetName='Version', Mandatory = $False)] + [switch]$Version = $null + ) + + if ($Version){ + $Banner = @" + + ;# + ######### + ######"" ;; + ###";#### ;############## + ##### ### ##"" "## ""###### + #### ### ""### "### + #### ## "### "# + "### \# ; #### + "### " ##"#### + ## \### ## #### + #### "###; ### #### + ######## "#" ;### ###"##### + "#############" ####"/##" + " ;####### + "#######" + # + + -=[Keystone Engine v0.9.1]=- + +"@ + # Mmm ASCII version banner! + $Banner + Return + } + + # Compatibility for PS v2 / PS v3+ + if(!$PSScriptRoot) { + $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent + } + + # Set the keystone DLL path + if ([IntPtr]::Size -eq 4){ + $DllPath = $($PSScriptRoot + '\Lib\Keystone-0.9.1\x86\keystone.dll').Replace('\','\\') + } else { + $DllPath = $($PSScriptRoot + '\Lib\Keystone-0.9.1\x64\keystone.dll').Replace('\','\\') + } + + # Load C# constants + $ks_err = Get-Content $($PSScriptRoot + '\Const\ks_err_cons.cs') + $ks_arch = Get-Content $($PSScriptRoot + '\Const\ks_arch_cons.cs') + $ks_mode = Get-Content $($PSScriptRoot + '\Const\ks_mode_cons.cs') + $ks_opt_value = Get-Content $($PSScriptRoot + '\Const\ks_opt_value_cons.cs') + + # Inline C# to parse the unmanaged keystone DLL + Add-Type -TypeDefinition @" + using System; + using System.Diagnostics; + using System.Runtime.InteropServices; + using System.Security.Principal; + + public enum ks_err : int + { + $ks_err + } + + public enum ks_arch : int + { + $ks_arch + } + + public enum ks_mode : int + { + $ks_mode + } + + public enum ks_opt_value : uint + { + $ks_opt_value + } + + public static class Keystone + { + [DllImport("$DllPath")] + public static extern ks_err ks_open( + ks_arch arch, + ks_mode mode, + ref IntPtr handle); + + [DllImport("$DllPath")] + public static extern ks_err ks_option( + IntPtr handle, + int mode, + ks_opt_value value); + + [DllImport("$DllPath")] + public static extern int ks_asm( + IntPtr handle, + String assembly, + ulong address, + ref IntPtr encoding, + ref uint encoding_size, + ref uint stat_count); + + [DllImport("$DllPath")] + public static extern ks_err ks_errno( + IntPtr handle); + + [DllImport("$DllPath")] + public static extern ks_err ks_close( + IntPtr handle); + + [DllImport("$DllPath")] + public static extern void ks_free( + IntPtr handle); + } +"@ + + # Asm Handle + $AsmHandle = [IntPtr]::Zero + + # Initialize Keystone with ks_open() + $CallResult = [Keystone]::ks_open($Architecture,$Mode,[ref]$AsmHandle) + if ($CallResult -ne "KS_ERR_OK") { + if ($CallResult -eq "KS_ERR_MODE"){ + echo "`n[!] Invalid Architecture/Mode combination" + echo "[>] Quitting..`n" + } else { + echo "`n[!] cs_open error: $CallResult" + echo "[>] Quitting..`n" + } + Return + } + + # Only one ks_opt_type -> KS_OPT_SYNTAX = 1 + $CallResult = [Keystone]::ks_option($AsmHandle, 1, $Syntax) + if ($CallResult -ne "KS_ERR_OK") { + echo "`n[!] ks_option error: $CallResult" + echo "[>] Quitting..`n" + $CallResult = [Keystone]::ks_close($AsmHandle) + Return + } + + # Result variables + $Encoded = [IntPtr]::Zero + [int]$Encoded_size = 0 + [int]$Stat_count = 0 + + # Assemble instructions + $CallResult = [Keystone]::ks_asm($AsmHandle, $Code, 0, [ref]$Encoded, [ref]$Encoded_size, [ref]$stat_count) + + if ($CallResult -ne 0) { + echo "`n[!] ks_asm error: $([Keystone]::ks_errno($AsmHandle))" + echo "[>] Quitting..`n" + $CallResult = [Keystone]::ks_close($AsmHandle) + Return + } else { + $BufferOffset = $Encoded.ToInt64() + + if ($Encoded_size -gt 0) { + # PS/C# hex array + $PSArray = @() + # C-style hex array + $CArray = @() + # Raw hex array + $RawArray = @() + for ($i=0; $i -lt $Encoded_size; $i++) { + $PSArray += echo "0x$("{0:X2}" -f $([Runtime.InteropServices.Marshal]::ReadByte($BufferOffset)))" + $CArray += echo "\x$("{0:X2}" -f $([Runtime.InteropServices.Marshal]::ReadByte($BufferOffset)))" + $RawArray += echo "$("{0:X2}" -f $([Runtime.InteropServices.Marshal]::ReadByte($BufferOffset)))" + $BufferOffset = $BufferOffset+1 + } + # Result Object + $HashTable = @{ + Bytes = $Encoded_size + Instructions = $stat_count + PSArray = $PSArray + CArray = $CArray + RawArray = $RawArray + } + New-Object PSObject -Property $HashTable |Select-Object Bytes,Instructions,PSArray,CArray,RawArray + + # Clean up! + [Keystone]::ks_free($Encoded) + $CallResult = [Keystone]::ks_close($AsmHandle) + } else { + echo "`n[!] No bytes assembled" + echo "[>] Quitting..`n" + $CallResult = [Keystone]::ks_close($AsmHandle) + Return + } + } +} \ No newline at end of file diff --git a/bindings/powershell/README b/bindings/powershell/README index b01dd43e54cb7a8ce1db5f66a9c79e67c2840869..06ef4fb93c7c3af7af964c59428d53313723d07f 100644 --- a/bindings/powershell/README +++ b/bindings/powershell/README @@ -1,26 +1,16 @@ Usage -Invoke-Keystone requires an architecture appropriate (x32/64) compiled Keystone DLL. -A pre-compiled version can be found on the Keystone download page at the following -URL: - - * http://www.keystone-engine.org/download/ - -Once downloaded, the DLL should be placed in a directory which is part of the SafeDllSearchMode search order. In practice, any folder which is part of the Windows PATH environment variable will work. - -The Invoke-Keystone function itself can be initialized using one of the following methods: - - * Script dot sourcing: +To use the PowerShell binding, the Keystone folder should be added to one of the PowerShell module directories: - PS C:\> . .\Invoke-Keystone.ps1 + # Global PSModulePath path + %Windir%\System32\WindowsPowerShell\v1.0\Modules - * Adding the script to one of the PowerShell module directories: + # User PSModulePath path + %UserProfile%\Documents\WindowsPowerShell\Modules - # Global PSModulePath path - %Windir%\System32\WindowsPowerShell\v1.0\Modules +Once this is done the module can be initialized by typing “Import-Module Keystone†in a new PowerShell terminal. Further information on the usage of the binding can be obtained with the following command: - # User PSModulePath path - %UserProfile%\Documents\WindowsPowerShell\Modules + Get-Help Get-KeystoneAssembly -Full Notes