├── Capstone ├── Lib │ └── Capstone-3.0.4 │ │ ├── x64 │ │ └── capstone.dll │ │ └── x86 │ │ └── capstone.dll ├── Capstone.psd1 └── Capstone.psm1 ├── Keystone ├── Lib │ └── Keystone-0.9.1 │ │ ├── x64 │ │ └── keystone.dll │ │ └── x86 │ │ └── keystone.dll ├── Keystone.psd1 └── Keystone.psm1 └── README.md /Capstone/Lib/Capstone-3.0.4/x64/capstone.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuzzySecurity/CapstoneKeystone-PowerShell/HEAD/Capstone/Lib/Capstone-3.0.4/x64/capstone.dll -------------------------------------------------------------------------------- /Capstone/Lib/Capstone-3.0.4/x86/capstone.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuzzySecurity/CapstoneKeystone-PowerShell/HEAD/Capstone/Lib/Capstone-3.0.4/x86/capstone.dll -------------------------------------------------------------------------------- /Keystone/Lib/Keystone-0.9.1/x64/keystone.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuzzySecurity/CapstoneKeystone-PowerShell/HEAD/Keystone/Lib/Keystone-0.9.1/x64/keystone.dll -------------------------------------------------------------------------------- /Keystone/Lib/Keystone-0.9.1/x86/keystone.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuzzySecurity/CapstoneKeystone-PowerShell/HEAD/Keystone/Lib/Keystone-0.9.1/x86/keystone.dll -------------------------------------------------------------------------------- /Capstone/Capstone.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | # Script module or binary module file associated with this manifest. 3 | ModuleToProcess = 'Capstone.psm1' 4 | 5 | # Version number of this module. 6 | ModuleVersion = '0.0.0.1' 7 | 8 | # ID used to uniquely identify this module 9 | GUID = 'd34db33f-9958-436d-a2d8-a77844a2bda5' 10 | 11 | # Author of this module 12 | Author = 'Ruben Boonen' 13 | 14 | # Copyright statement for this module 15 | Copyright = 'BSD 3-Clause' 16 | 17 | # Description of the functionality provided by this module 18 | Description = 'Capstone Engine Binding Module' 19 | 20 | # Minimum version of the Windows PowerShell engine required by this module 21 | PowerShellVersion = '2.0' 22 | 23 | # Functions to export from this module 24 | FunctionsToExport = '*' 25 | } 26 | -------------------------------------------------------------------------------- /Keystone/Keystone.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | # Script module or binary module file associated with this manifest. 3 | ModuleToProcess = 'Keystone.psm1' 4 | 5 | # Version number of this module. 6 | ModuleVersion = '0.0.0.1' 7 | 8 | # ID used to uniquely identify this module 9 | GUID = 'd34db33f-e454-4d6d-947c-04a6f02728ad' 10 | 11 | # Author of this module 12 | Author = 'Ruben Boonen' 13 | 14 | # Copyright statement for this module 15 | Copyright = 'BSD 3-Clause' 16 | 17 | # Description of the functionality provided by this module 18 | Description = 'Keystone Engine Binding Module' 19 | 20 | # Minimum version of the Windows PowerShell engine required by this module 21 | PowerShellVersion = '2.0' 22 | 23 | # Functions to export from this module 24 | FunctionsToExport = '*' 25 | } 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Usage 2 | ----- 3 | 4 | To use the PowerShell bindings, the entire Capstone/Keystone folders should be 5 | added to one of the PowerShell module directories: 6 | 7 | # Global PSModulePath path 8 | %Windir%\System32\WindowsPowerShell\v1.0\Modules 9 | 10 | # User PSModulePath path 11 | %UserProfile%\Documents\WindowsPowerShell\Modules 12 | 13 | Once this is done the modules can be initialized by using "Import-Module" 14 | in a new PowerShell terminal. Further information on the usage of the bindings 15 | can be obtained with the following commands: 16 | 17 | Get-Help Get-KeystoneAssembly -Full 18 | Get-Help Get-CapstoneDisassembly -Full 19 | 20 | 21 | Notes 22 | ----- 23 | 24 | The Keystone engine requires the Visual C++ Redistributable Packages for Visual 25 | Studio 2013. The architecture relevant installer can be downloaded at the 26 | following URL https://www.microsoft.com/en-gb/download/confirmation.aspx?id=40784 27 | 28 | 29 | Library Integration 30 | ------------------- 31 | 32 | * A modified version of Get-KeystoneAssembly has been integrated into the 33 | official Keystone Engine project. 34 | 35 | -> https://github.com/keystone-engine/keystone/tree/master/bindings 36 | 37 | * A modified version of Get-CapstoneDisassembly has been integrated into the 38 | official Capstone Engine project. 39 | 40 | -> https://github.com/aquynh/capstone/tree/master/bindings 41 | 42 | 43 | Examples 44 | -------- 45 | 46 | #### Get-KeystoneAssembly 47 | 48 | ``` 49 | # Support for multi-line code blocks 50 | PS C:\> $Code = @" 51 | >> sub esp, 200 52 | >> pop eax 53 | >> pop ecx 54 | >> ret 55 | >> "@ 56 | PS C:\> Get-KeystoneAssembly -Architecture KS_ARCH_X86 -Mode KS_MODE_32 -Code $Code 57 | 58 | Bytes : 9 59 | Instructions : 4 60 | PSArray : {0x81, 0xEC, 0xC8, 0x00...} 61 | CArray : {\x81, \xEC, \xC8, \x00...} 62 | RawArray : {81, EC, C8, 00...} 63 | 64 | # Get-KeystoneAssembly emits objects 65 | PS C:\> $Code = @" 66 | >> sub esp, 200 67 | >> pop eax 68 | >> pop ecx 69 | >> ret 70 | >> "@ 71 | PS C:\> $Object = Get-KeystoneAssembly -Architecture KS_ARCH_X86 -Mode KS_MODE_32 -Code $Code 72 | PS C:\> $Object.RawArray -join "" 73 | 81ECC80000005859C3 74 | PS C:\> $Object.CArray -join "" 75 | \x81\xEC\xC8\x00\x00\x00\x58\x59\xC3 76 | PS C:\> "`$Shellcode = {" + $($Object.PSArray -join ", ") + "}" 77 | $Shellcode = {0x81, 0xEC, 0xC8, 0x00, 0x00, 0x00, 0x58, 0x59, 0xC3} 78 | ``` 79 | 80 | #### Get-CapstoneDisassembly 81 | 82 | ``` 83 | # ARM simple disassembly 84 | C:\PS> $Bytes = [Byte[]] @( 0x10, 0xf1, 0x10, 0xe7, 0x11, 0xf2, 0x31, 0xe7, 0xdc, 0xa1, 0x2e, 0xf3, 0xe8, 0x4e, 0x62, 0xf3 ) 85 | C:\PS> Get-CapstoneDisassembly -Architecture CS_ARCH_ARM -Mode CS_MODE_ARM -Bytes $Bytes 86 | 87 | sdiv r0, r0, r1 88 | udiv r1, r1, r2 89 | vbit q5, q15, q6 90 | vcgt.f32 q10, q9, q12 91 | 92 | # X86 detailed disassembly, ATT syntax 93 | C:\PS> $Bytes = [Byte[]] @( 0xB8, 0x0A, 0x00, 0x00, 0x00, 0xF7, 0xF3 ) 94 | C:\PS> Get-CapstoneDisassembly -Architecture CS_ARCH_X86 -Mode CS_MODE_32 -Bytes $Bytes -Syntax ATT -Detailed 95 | 96 | Size : 5 97 | Address : 0x100000 98 | Mnemonic : movl 99 | Operands : $0xa, %eax 100 | Bytes : {184, 10, 0, 0...} 101 | RegRead : 102 | RegWrite : 103 | 104 | Size : 2 105 | Address : 0x100005 106 | Mnemonic : divl 107 | Operands : %ebx 108 | Bytes : {247, 243, 0, 0...} 109 | RegRead : {eax, edx} 110 | RegWrite : {eax, edx, eflags} 111 | ``` -------------------------------------------------------------------------------- /Keystone/Keystone.psm1: -------------------------------------------------------------------------------- 1 | function Get-KeystoneAssembly { 2 | <# 3 | .SYNOPSIS 4 | Powershell wrapper for Keystone (using inline C#). 5 | 6 | .DESCRIPTION 7 | Author: Ruben Boonen (@FuzzySec) 8 | License: BSD 3-Clause 9 | Required Dependencies: None 10 | Optional Dependencies: None 11 | 12 | .PARAMETER Architecture 13 | Architecture type. 14 | 15 | .PARAMETER Mode 16 | Mode type. 17 | 18 | .PARAMETER Code 19 | Assembly string, use ";" or multi-line variables for instruction separation. 20 | 21 | .PARAMETER Syntax 22 | Syntax for input assembly. 23 | 24 | .PARAMETER Version 25 | Print ASCII version banner. 26 | 27 | .EXAMPLE 28 | 29 | # Support for multi-line code blocks 30 | PS C:\> $Code = @" 31 | >> sub esp, 200 32 | >> pop eax 33 | >> pop ecx 34 | >> ret 35 | >> "@ 36 | PS C:\> Get-KeystoneAssembly -Architecture KS_ARCH_X86 -Mode KS_MODE_32 -Code $Code 37 | 38 | Bytes : 9 39 | Instructions : 4 40 | PSArray : {0x81, 0xEC, 0xC8, 0x00...} 41 | CArray : {\x81, \xEC, \xC8, \x00...} 42 | RawArray : {81, EC, C8, 00...} 43 | 44 | .EXAMPLE 45 | 46 | # Get-KeystoneAssembly emits objects 47 | PS C:\> $Code = @" 48 | >> sub esp, 200 49 | >> pop eax 50 | >> pop ecx 51 | >> ret 52 | >> "@ 53 | PS C:\> $Object = Get-KeystoneAssembly -Architecture KS_ARCH_X86 -Mode KS_MODE_32 -Code $Code 54 | PS C:\> $Object.RawArray -join "" 55 | 81ECC80000005859C3 56 | PS C:\> $Object.CArray -join "" 57 | \x81\xEC\xC8\x00\x00\x00\x58\x59\xC3 58 | PS C:\> "`$Shellcode = {" + $($Object.PSArray -join ", ") + "}" 59 | $Shellcode = {0x81, 0xEC, 0xC8, 0x00, 0x00, 0x00, 0x58, 0x59, 0xC3} 60 | 61 | #> 62 | 63 | param( 64 | [Parameter(ParameterSetName='Keystone', Mandatory = $True)] 65 | [ValidateSet( 66 | 'KS_ARCH_ARM', 67 | 'KS_ARCH_ARM64', 68 | 'KS_ARCH_MIPS', 69 | 'KS_ARCH_X86', 70 | 'KS_ARCH_PPC', 71 | 'KS_ARCH_SPARC', 72 | 'KS_ARCH_SYSTEMZ', 73 | 'KS_ARCH_HEXAGON', 74 | 'KS_ARCH_MAX') 75 | ] 76 | [String]$Architecture, 77 | 78 | [Parameter(ParameterSetName='Keystone', Mandatory = $True)] 79 | [ValidateSet( 80 | 'KS_MODE_LITTLE_ENDIAN', 81 | 'KS_MODE_BIG_ENDIAN', 82 | 'KS_MODE_ARM', 83 | 'KS_MODE_THUMB', 84 | 'KS_MODE_V8', 85 | 'KS_MODE_MICRO', 86 | 'KS_MODE_MIPS3', 87 | 'KS_MODE_MIPS32R6', 88 | 'KS_MODE_MIPS32', 89 | 'KS_MODE_MIPS64', 90 | 'KS_MODE_16', 91 | 'KS_MODE_32', 92 | 'KS_MODE_64', 93 | 'KS_MODE_PPC32', 94 | 'KS_MODE_PPC64', 95 | 'KS_MODE_QPX', 96 | 'KS_MODE_SPARC32', 97 | 'KS_MODE_SPARC64', 98 | 'KS_MODE_V9') 99 | ] 100 | [String]$Mode, 101 | 102 | [Parameter(ParameterSetName='Keystone', Mandatory = $True)] 103 | [ValidateNotNullOrEmpty()] 104 | [string]$Code, 105 | 106 | [Parameter(ParameterSetName='Keystone', Mandatory = $False)] 107 | [ValidateSet( 108 | 'KS_OPT_SYNTAX_INTEL', 109 | 'KS_OPT_SYNTAX_ATT', 110 | 'KS_OPT_SYNTAX_NASM', 111 | 'KS_OPT_SYNTAX_MASM', 112 | 'KS_OPT_SYNTAX_GAS') 113 | ] 114 | [String]$Syntax = "KS_OPT_SYNTAX_INTEL", 115 | 116 | [Parameter(ParameterSetName='Version', Mandatory = $False)] 117 | [switch]$Version = $null 118 | ) 119 | 120 | # Compatibility for PS v2 / PS v3+ 121 | if(!$PSScriptRoot) { 122 | $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent 123 | } 124 | 125 | # Set the keystone DLL path 126 | if ([IntPtr]::Size -eq 4){ 127 | $DllPath = $($PSScriptRoot + '\Lib\Keystone-0.9.1\x86\keystone.dll').Replace('\','\\') 128 | } else { 129 | $DllPath = $($PSScriptRoot + '\Lib\Keystone-0.9.1\x64\keystone.dll').Replace('\','\\') 130 | } 131 | 132 | # Inline C# to parse the unmanaged keystone DLL 133 | Add-Type -TypeDefinition @" 134 | using System; 135 | using System.Diagnostics; 136 | using System.Runtime.InteropServices; 137 | using System.Security.Principal; 138 | 139 | public enum ks_err : int 140 | { 141 | KS_ERR_OK = 0, /// No error: everything was fine 142 | KS_ERR_NOMEM, /// Out-Of-Memory error: ks_open(), ks_emulate() 143 | KS_ERR_ARCH, /// Unsupported architecture: ks_open() 144 | KS_ERR_HANDLE, /// Invalid handle 145 | KS_ERR_MODE, /// Invalid/unsupported mode: ks_open() 146 | KS_ERR_VERSION, /// Unsupported version (bindings) 147 | KS_ERR_OPT_INVALID, /// Unsupported option 148 | 149 | /// generic input assembly errors - parser specific 150 | KS_ERR_ASM_EXPR_TOKEN = 128, /// unknown token in expression 151 | KS_ERR_ASM_DIRECTIVE_VALUE_RANGE, /// literal value out of range for directive 152 | KS_ERR_ASM_DIRECTIVE_ID, /// expected identifier in directive 153 | KS_ERR_ASM_DIRECTIVE_TOKEN, /// unexpected token in directive 154 | KS_ERR_ASM_DIRECTIVE_STR, /// expected string in directive 155 | KS_ERR_ASM_DIRECTIVE_COMMA, /// expected comma in directive 156 | KS_ERR_ASM_DIRECTIVE_RELOC_NAME, /// expected relocation name in directive 157 | KS_ERR_ASM_DIRECTIVE_RELOC_TOKEN, /// unexpected token in .reloc directive 158 | KS_ERR_ASM_DIRECTIVE_FPOINT, /// invalid floating point in directive 159 | KS_ERR_ASM_DIRECTIVE_UNKNOWN, /// unknown directive 160 | KS_ERR_ASM_DIRECTIVE_EQU, /// invalid equal directive 161 | KS_ERR_ASM_DIRECTIVE_INVALID, /// (generic) invalid directive 162 | KS_ERR_ASM_VARIANT_INVALID, /// invalid variant 163 | KS_ERR_ASM_EXPR_BRACKET, /// brackets expression not supported on this target 164 | KS_ERR_ASM_SYMBOL_MODIFIER, /// unexpected symbol modifier following '@' 165 | KS_ERR_ASM_SYMBOL_REDEFINED, /// invalid symbol redefinition 166 | KS_ERR_ASM_SYMBOL_MISSING, /// cannot find a symbol 167 | KS_ERR_ASM_RPAREN, /// expected ')' in parentheses expression 168 | KS_ERR_ASM_STAT_TOKEN, /// unexpected token at start of statement 169 | KS_ERR_ASM_UNSUPPORTED, /// unsupported token yet 170 | KS_ERR_ASM_MACRO_TOKEN, /// unexpected token in macro instantiation 171 | KS_ERR_ASM_MACRO_PAREN, /// unbalanced parentheses in macro argument 172 | KS_ERR_ASM_MACRO_EQU, /// expected '=' after formal parameter identifier 173 | KS_ERR_ASM_MACRO_ARGS, /// too many positional arguments 174 | KS_ERR_ASM_MACRO_LEVELS_EXCEED, /// macros cannot be nested more than 20 levels deep 175 | KS_ERR_ASM_MACRO_STR, /// invalid macro string 176 | KS_ERR_ASM_MACRO_INVALID, /// invalid macro (generic error) 177 | KS_ERR_ASM_ESC_BACKSLASH, /// unexpected backslash at end of escaped string 178 | KS_ERR_ASM_ESC_OCTAL, /// invalid octal escape sequence (out of range) 179 | KS_ERR_ASM_ESC_SEQUENCE, /// invalid escape sequence (unrecognized character) 180 | KS_ERR_ASM_ESC_STR, /// broken escape string 181 | KS_ERR_ASM_TOKEN_INVALID, /// invalid token 182 | KS_ERR_ASM_INSN_UNSUPPORTED, /// this instruction is unsupported in this mode 183 | KS_ERR_ASM_FIXUP_INVALID, /// invalid fixup 184 | KS_ERR_ASM_LABEL_INVALID, /// invalid label 185 | KS_ERR_ASM_FRAGMENT_INVALID, /// invalid fragment 186 | 187 | /// generic input assembly errors - architecture specific 188 | KS_ERR_ASM_INVALIDOPERAND = 512, 189 | KS_ERR_ASM_MISSINGFEATURE, 190 | KS_ERR_ASM_MNEMONICFAIL, 191 | } 192 | 193 | public enum ks_arch : int 194 | { 195 | KS_ARCH_ARM = 1, /// ARM architecture (including Thumb, Thumb-2) 196 | KS_ARCH_ARM64, /// ARM-64, also called AArch64 197 | KS_ARCH_MIPS, /// Mips architecture 198 | KS_ARCH_X86, /// X86 architecture (including x86 & x86-64) 199 | KS_ARCH_PPC, /// PowerPC architecture (currently unsupported) 200 | KS_ARCH_SPARC, /// Sparc architecture 201 | KS_ARCH_SYSTEMZ, /// SystemZ architecture (S390X) 202 | KS_ARCH_HEXAGON, /// Hexagon architecture 203 | KS_ARCH_MAX, 204 | } 205 | 206 | public enum ks_mode : int 207 | { 208 | KS_MODE_LITTLE_ENDIAN = 0, /// little-endian mode (default mode) 209 | KS_MODE_BIG_ENDIAN = 1 << 30, /// big-endian mode 210 | /// arm / arm64 211 | KS_MODE_ARM = 1 << 0, /// ARM mode 212 | KS_MODE_THUMB = 1 << 4, /// THUMB mode (including Thumb-2) 213 | KS_MODE_V8 = 1 << 6, /// ARMv8 A32 encodings for ARM 214 | /// mips 215 | KS_MODE_MICRO = 1 << 4, /// MicroMips mode 216 | KS_MODE_MIPS3 = 1 << 5, /// Mips III ISA 217 | KS_MODE_MIPS32R6 = 1 << 6, /// Mips32r6 ISA 218 | KS_MODE_MIPS32 = 1 << 2, /// Mips32 ISA 219 | KS_MODE_MIPS64 = 1 << 3, /// Mips64 ISA 220 | /// x86 / x64 221 | KS_MODE_16 = 1 << 1, /// 16-bit mode 222 | KS_MODE_32 = 1 << 2, /// 32-bit mode 223 | KS_MODE_64 = 1 << 3, /// 64-bit mode 224 | /// ppc 225 | KS_MODE_PPC32 = 1 << 2, /// 32-bit mode 226 | KS_MODE_PPC64 = 1 << 3, /// 64-bit mode 227 | KS_MODE_QPX = 1 << 4, /// Quad Processing eXtensions mode 228 | /// sparc 229 | KS_MODE_SPARC32 = 1 << 2, /// 32-bit mode 230 | KS_MODE_SPARC64 = 1 << 3, /// 64-bit mode 231 | KS_MODE_V9 = 1 << 4, /// SparcV9 mode 232 | } 233 | 234 | public enum ks_opt_value : uint 235 | { 236 | KS_OPT_SYNTAX_INTEL = 1 << 0, /// X86 Intel syntax - default on X86 (KS_OPT_SYNTAX). 237 | KS_OPT_SYNTAX_ATT = 1 << 1, /// X86 ATT asm syntax (KS_OPT_SYNTAX). 238 | KS_OPT_SYNTAX_NASM = 1 << 2, /// X86 Nasm syntax (KS_OPT_SYNTAX). 239 | KS_OPT_SYNTAX_MASM = 1 << 3, /// X86 Masm syntax (KS_OPT_SYNTAX) - unsupported yet. 240 | KS_OPT_SYNTAX_GAS = 1 << 4, /// X86 GNU GAS syntax (KS_OPT_SYNTAX). 241 | } 242 | 243 | public static class Keystone 244 | { 245 | [DllImport("$DllPath")] 246 | public static extern ks_err ks_open( 247 | ks_arch arch, 248 | ks_mode mode, 249 | ref IntPtr handle); 250 | 251 | [DllImport("$DllPath")] 252 | public static extern ks_err ks_option( 253 | IntPtr handle, 254 | int mode, 255 | ks_opt_value value); 256 | 257 | [DllImport("$DllPath")] 258 | public static extern int ks_asm( 259 | IntPtr handle, 260 | String assembly, 261 | ulong address, 262 | ref IntPtr encoding, 263 | ref uint encoding_size, 264 | ref uint stat_count); 265 | 266 | [DllImport("$DllPath")] 267 | public static extern ks_err ks_errno( 268 | IntPtr handle); 269 | 270 | [DllImport("$DllPath")] 271 | public static extern ks_err ks_close( 272 | IntPtr handle); 273 | 274 | [DllImport("$DllPath")] 275 | public static extern void ks_free( 276 | IntPtr handle); 277 | 278 | [DllImport("$DllPath")] 279 | public static extern int ks_version( 280 | uint major, 281 | uint minor); 282 | } 283 | "@ 284 | 285 | if ($Version){ 286 | $VerCount = [System.BitConverter]::GetBytes($([Keystone]::ks_version($null,$null))) 287 | $Banner = @" 288 | 289 | ;# 290 | ######### 291 | ######"" ;; 292 | ###";#### ;############## 293 | ##### ### ##"" "## ""###### 294 | #### ### ""### "### 295 | #### ## "### "# 296 | "### \# ; #### 297 | "### " ##"#### 298 | ## \### ## #### 299 | #### "###; ### #### 300 | ######## "#" ;### ###"##### 301 | "#############" ####"/##" 302 | " ;####### 303 | "#######" 304 | # 305 | 306 | -=[Keystone Engine v$($VerCount[1]).$($VerCount[0])]=- 307 | 308 | "@ 309 | # Mmm ASCII version banner! 310 | $Banner 311 | Return 312 | } 313 | 314 | # Asm Handle 315 | $AsmHandle = [IntPtr]::Zero 316 | 317 | # Initialize Keystone with ks_open() 318 | $CallResult = [Keystone]::ks_open($Architecture,$Mode,[ref]$AsmHandle) 319 | if ($CallResult -ne "KS_ERR_OK") { 320 | if ($CallResult -eq "KS_ERR_MODE"){ 321 | echo "`n[!] Invalid Architecture/Mode combination" 322 | echo "[>] Quitting..`n" 323 | } else { 324 | echo "`n[!] cs_open error: $CallResult" 325 | echo "[>] Quitting..`n" 326 | } 327 | Return 328 | } 329 | 330 | # Only one ks_opt_type -> KS_OPT_SYNTAX = 1 331 | $CallResult = [Keystone]::ks_option($AsmHandle, 1, $Syntax) 332 | if ($CallResult -ne "KS_ERR_OK") { 333 | echo "`n[!] ks_option error: $CallResult" 334 | echo "[>] Quitting..`n" 335 | $CallResult = [Keystone]::ks_close($AsmHandle) 336 | Return 337 | } 338 | 339 | # Result variables 340 | $Encoded = [IntPtr]::Zero 341 | [int]$Encoded_size = 0 342 | [int]$Stat_count = 0 343 | 344 | # Assemble instructions 345 | $CallResult = [Keystone]::ks_asm($AsmHandle, $Code, 0, [ref]$Encoded, [ref]$Encoded_size, [ref]$stat_count) 346 | 347 | if ($CallResult -ne 0) { 348 | echo "`n[!] ks_asm error: $([Keystone]::ks_errno($AsmHandle))" 349 | echo "[>] Quitting..`n" 350 | $CallResult = [Keystone]::ks_close($AsmHandle) 351 | Return 352 | } else { 353 | $BufferOffset = $Encoded.ToInt64() 354 | 355 | if ($Encoded_size -gt 0) { 356 | # PS/C# hex array 357 | $PSArray = @() 358 | # C-style hex array 359 | $CArray = @() 360 | # Raw hex array 361 | $RawArray = @() 362 | for ($i=0; $i -lt $Encoded_size; $i++) { 363 | $PSArray += echo "0x$("{0:X2}" -f $([Runtime.InteropServices.Marshal]::ReadByte($BufferOffset)))" 364 | $CArray += echo "\x$("{0:X2}" -f $([Runtime.InteropServices.Marshal]::ReadByte($BufferOffset)))" 365 | $RawArray += echo "$("{0:X2}" -f $([Runtime.InteropServices.Marshal]::ReadByte($BufferOffset)))" 366 | $BufferOffset = $BufferOffset+1 367 | } 368 | # Result Object 369 | $HashTable = @{ 370 | Bytes = $Encoded_size 371 | Instructions = $stat_count 372 | PSArray = $PSArray 373 | CArray = $CArray 374 | RawArray = $RawArray 375 | } 376 | New-Object PSObject -Property $HashTable |Select-Object Bytes,Instructions,PSArray,CArray,RawArray 377 | 378 | # Clean up! 379 | [Keystone]::ks_free($Encoded) 380 | $CallResult = [Keystone]::ks_close($AsmHandle) 381 | } else { 382 | echo "`n[!] No bytes assembled" 383 | echo "[>] Quitting..`n" 384 | $CallResult = [Keystone]::ks_close($AsmHandle) 385 | Return 386 | } 387 | } 388 | } -------------------------------------------------------------------------------- /Capstone/Capstone.psm1: -------------------------------------------------------------------------------- 1 | function Get-CapstoneDisassembly { 2 | <# 3 | .SYNOPSIS 4 | Powershell wrapper for Capstone (using inline C#). 5 | 6 | .DESCRIPTION 7 | Author: Ruben Boonen (@FuzzySec) 8 | License: BSD 3-Clause 9 | Required Dependencies: None 10 | Optional Dependencies: None 11 | 12 | .PARAMETER Architecture 13 | Architecture type. 14 | 15 | .PARAMETER Mode 16 | Mode type. 17 | 18 | .PARAMETER Bytes 19 | Byte array to be disassembled. 20 | 21 | .PARAMETER Syntax 22 | Syntax for output assembly. 23 | 24 | .PARAMETER Address 25 | Assign address for the first instruction to be disassembled. 26 | 27 | .PARAMETER Detailed 28 | Return detailed output. 29 | 30 | .PARAMETER Version 31 | Print ASCII version banner. 32 | 33 | .EXAMPLE 34 | 35 | C:\PS> $Bytes = [Byte[]] @( 0x10, 0xf1, 0x10, 0xe7, 0x11, 0xf2, 0x31, 0xe7, 0xdc, 0xa1, 0x2e, 0xf3, 0xe8, 0x4e, 0x62, 0xf3 ) 36 | C:\PS> Get-CapstoneDisassembly -Architecture CS_ARCH_ARM -Mode CS_MODE_ARM -Bytes $Bytes 37 | 38 | sdiv r0, r0, r1 39 | udiv r1, r1, r2 40 | vbit q5, q15, q6 41 | vcgt.f32 q10, q9, q12 42 | 43 | .EXAMPLE 44 | 45 | # Detailed mode & ATT syntax 46 | C:\PS> $Bytes = [Byte[]] @( 0xB8, 0x0A, 0x00, 0x00, 0x00, 0xF7, 0xF3 ) 47 | C:\PS> Get-CapstoneDisassembly -Architecture CS_ARCH_X86 -Mode CS_MODE_32 -Bytes $Bytes -Syntax ATT -Detailed 48 | 49 | Size : 5 50 | Address : 0x100000 51 | Mnemonic : movl 52 | Operands : $0xa, %eax 53 | Bytes : {184, 10, 0, 0...} 54 | RegRead : 55 | RegWrite : 56 | 57 | Size : 2 58 | Address : 0x100005 59 | Mnemonic : divl 60 | Operands : %ebx 61 | Bytes : {247, 243, 0, 0...} 62 | RegRead : {eax, edx} 63 | RegWrite : {eax, edx, eflags} 64 | 65 | .EXAMPLE 66 | 67 | # Get-CapstoneDisassembly emits objects 68 | C:\PS> $Bytes = [Byte[]] @( 0xB8, 0x0A, 0x00, 0x00, 0x00, 0xF7, 0xF3 ) 69 | C:\PS> $Object = Get-CapstoneDisassembly -Architecture CS_ARCH_X86 -Mode CS_MODE_32 -Bytes $Bytes -Detailed 70 | C:\PS> $Object |Select-Object Size,Mnemonic,Operands 71 | 72 | Size Mnemonic Operands 73 | ---- -------- -------- 74 | 5 mov eax, 0xa 75 | 2 div ebx 76 | 77 | #> 78 | 79 | param( 80 | [Parameter(ParameterSetName='Capstone', Mandatory = $True)] 81 | [ValidateSet( 82 | 'CS_ARCH_ARM', 83 | 'CS_ARCH_ARM64', 84 | 'CS_ARCH_MIPS', 85 | 'CS_ARCH_X86', 86 | 'CS_ARCH_PPC', 87 | 'CS_ARCH_SPARC', 88 | 'CS_ARCH_SYSZ', 89 | 'CS_ARCH_XCORE', 90 | 'CS_ARCH_MAX', 91 | 'CS_ARCH_ALL') 92 | ] 93 | [String]$Architecture, 94 | 95 | [Parameter(ParameterSetName='Capstone', Mandatory = $True)] 96 | [ValidateSet( 97 | 'CS_MODE_LITTLE_ENDIAN', 98 | 'CS_MODE_ARM', 99 | 'CS_MODE_16', 100 | 'CS_MODE_32', 101 | 'CS_MODE_64', 102 | 'CS_MODE_THUMB', 103 | 'CS_MODE_MCLASS', 104 | 'CS_MODE_V8', 105 | 'CS_MODE_MICRO', 106 | 'CS_MODE_MIPS3', 107 | 'CS_MODE_MIPS32R6', 108 | 'CS_MODE_MIPSGP64', 109 | 'CS_MODE_V9', 110 | 'CS_MODE_BIG_ENDIAN', 111 | 'CS_MODE_MIPS32', 112 | 'CS_MODE_MIPS64') 113 | ] 114 | [String]$Mode, 115 | 116 | [Parameter(ParameterSetName='Capstone', Mandatory = $True)] 117 | [ValidateNotNullOrEmpty()] 118 | [Byte[]]$Bytes, 119 | 120 | [Parameter(ParameterSetName='Capstone', Mandatory = $False)] 121 | [ValidateSet( 122 | 'Intel', 123 | 'ATT') 124 | ] 125 | [String]$Syntax = "Intel", 126 | 127 | [Parameter(ParameterSetName='Capstone', Mandatory = $False)] 128 | [UInt64]$Address = 0x100000, 129 | 130 | [Parameter(ParameterSetName='Capstone', Mandatory = $False)] 131 | [switch]$Detailed = $null, 132 | 133 | [Parameter(ParameterSetName='Version', Mandatory = $False)] 134 | [switch]$Version = $null 135 | ) 136 | 137 | # Compatibility for PS v2 / PS v3+ 138 | if(!$PSScriptRoot) { 139 | $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent 140 | } 141 | 142 | # Set the capstone DLL path 143 | if ([IntPtr]::Size -eq 4){ 144 | $DllPath = $($PSScriptRoot + '\Lib\Capstone-3.0.4\x86\capstone.dll').Replace('\','\\') 145 | } else { 146 | $DllPath = $($PSScriptRoot + '\Lib\Capstone-3.0.4\x64\capstone.dll').Replace('\','\\') 147 | } 148 | 149 | # Inline C# to parse the unmanaged capstone DLL 150 | Add-Type -TypeDefinition @" 151 | using System; 152 | using System.Diagnostics; 153 | using System.Runtime.InteropServices; 154 | using System.Security.Principal; 155 | 156 | [StructLayout(LayoutKind.Sequential)] 157 | public struct cs_insn 158 | { 159 | public uint id; 160 | public ulong address; 161 | public ushort size; 162 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] 163 | public byte[] bytes; 164 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 165 | public string mnemonic; 166 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 160)] 167 | public string operands; 168 | public IntPtr detail; 169 | } 170 | 171 | /// Partial, only architecture-independent internal data 172 | [StructLayout(LayoutKind.Sequential)] 173 | public struct cs_detail 174 | { 175 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] 176 | public byte[] regs_read; 177 | public byte regs_read_count; 178 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] 179 | public byte[] regs_write; 180 | public byte regs_write_count; 181 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] 182 | public byte[] groups; 183 | public byte groups_count; 184 | } 185 | 186 | public enum cs_err : int 187 | { 188 | CS_ERR_OK = 0, /// No error: everything was fine 189 | CS_ERR_MEM, /// Out-Of-Memory error: cs_open(), cs_disasm(), cs_disasm_iter() 190 | CS_ERR_ARCH, /// Unsupported architecture: cs_open() 191 | CS_ERR_HANDLE, /// Invalid handle: cs_op_count(), cs_op_index() 192 | CS_ERR_CSH, /// Invalid csh argument: cs_close(), cs_errno(), cs_option() 193 | CS_ERR_MODE, /// Invalid/unsupported mode: cs_open() 194 | CS_ERR_OPTION, /// Invalid/unsupported option: cs_option() 195 | CS_ERR_DETAIL, /// Information is unavailable because detail option is OFF 196 | CS_ERR_MEMSETUP, /// Dynamic memory management uninitialized (see CS_OPT_MEM) 197 | CS_ERR_VERSION, /// Unsupported version (bindings) 198 | CS_ERR_DIET, /// Access irrelevant data in "diet" engine 199 | CS_ERR_SKIPDATA, /// Access irrelevant data for "data" instruction in SKIPDATA mode 200 | CS_ERR_X86_ATT, /// X86 AT&T syntax is unsupported (opt-out at compile time) 201 | CS_ERR_X86_INTEL, /// X86 Intel syntax is unsupported (opt-out at compile time) 202 | } 203 | 204 | public enum cs_arch : int 205 | { 206 | CS_ARCH_ARM = 0, /// ARM architecture (including Thumb, Thumb-2) 207 | CS_ARCH_ARM64, /// ARM-64, also called AArch64 208 | CS_ARCH_MIPS, /// Mips architecture 209 | CS_ARCH_X86, /// X86 architecture (including x86 & x86-64) 210 | CS_ARCH_PPC, /// PowerPC architecture 211 | CS_ARCH_SPARC, /// Sparc architecture 212 | CS_ARCH_SYSZ, /// SystemZ architecture 213 | CS_ARCH_XCORE, /// XCore architecture 214 | CS_ARCH_MAX, 215 | CS_ARCH_ALL = 0xFFFF, /// All architectures - for cs_support() 216 | } 217 | 218 | public enum cs_mode : int 219 | { 220 | CS_MODE_LITTLE_ENDIAN = 0, /// little-endian mode (default mode) 221 | CS_MODE_ARM = 0, /// 32-bit ARM 222 | CS_MODE_16 = 1 << 1, /// 16-bit mode (X86) 223 | CS_MODE_32 = 1 << 2, /// 32-bit mode (X86) 224 | CS_MODE_64 = 1 << 3, /// 64-bit mode (X86, PPC) 225 | CS_MODE_THUMB = 1 << 4, /// ARM's Thumb mode, including Thumb-2 226 | CS_MODE_MCLASS = 1 << 5, /// ARM's Cortex-M series 227 | CS_MODE_V8 = 1 << 6, /// ARMv8 A32 encodings for ARM 228 | CS_MODE_MICRO = 1 << 4, /// MicroMips mode (MIPS) 229 | CS_MODE_MIPS3 = 1 << 5, /// Mips III ISA 230 | CS_MODE_MIPS32R6 = 1 << 6, /// Mips32r6 ISA 231 | CS_MODE_MIPSGP64 = 1 << 7, /// General Purpose Registers are 64-bit wide (MIPS) 232 | CS_MODE_V9 = 1 << 4, /// SparcV9 mode (Sparc) 233 | CS_MODE_BIG_ENDIAN = 1 << 31, /// big-endian mode 234 | CS_MODE_MIPS32 = CS_MODE_32, /// Mips32 ISA (Mips) 235 | CS_MODE_MIPS64 = CS_MODE_64, /// Mips64 ISA (Mips) 236 | } 237 | 238 | public static class Capstone 239 | { 240 | [DllImport("$DllPath")] 241 | public static extern cs_err cs_open( 242 | cs_arch arch, 243 | cs_mode mode, 244 | ref IntPtr handle); 245 | 246 | [DllImport("$DllPath")] 247 | public static extern UInt32 cs_disasm( 248 | IntPtr handle, 249 | byte[] code, 250 | int code_size, 251 | ulong address, 252 | int count, 253 | ref IntPtr insn); 254 | 255 | [DllImport("$DllPath")] 256 | public static extern bool cs_free( 257 | IntPtr insn, 258 | int count); 259 | 260 | [DllImport("$DllPath")] 261 | public static extern cs_err cs_close( 262 | ref IntPtr handle); 263 | 264 | [DllImport("$DllPath")] 265 | public static extern cs_err cs_option( 266 | IntPtr handle, 267 | int type, 268 | int value); 269 | 270 | [DllImport("$DllPath", CallingConvention = CallingConvention.Cdecl)] 271 | public static extern IntPtr cs_reg_name( 272 | IntPtr handle, 273 | uint reg_id); 274 | 275 | [DllImport("$DllPath")] 276 | public static extern int cs_version( 277 | uint major, 278 | uint minor); 279 | } 280 | "@ 281 | 282 | if ($Version){ 283 | $VerCount = [System.BitConverter]::GetBytes($([Capstone]::cs_version($null,$null))) 284 | $Banner = @" 285 | 286 | (((; 287 | (; "((((\ 288 | ;((((((; "((((; 289 | ((((""\(((( "(((( 290 | ((((" ((\ "(((( "(((\ 291 | ;(((/ ((((((( "(((( \((( 292 | ((((" (((* "(((( \(((;"(((\ 293 | ((((";((("/(( \(((;"(((\"(((\ 294 | (((( (((( ((((" "(((\ ((() (((\ 295 | ;((("(((( (((* **"" ((()"(((; 296 | (((" ((( (((( ((((((((((((((:*((( 297 | (((( (((*)((( ********"""" ;;(((((; 298 | (((* ((( (((((((((((((((((((((*"" ( 299 | ((("(((( """***********"""" ;;((((( 300 | "" (((((((((((((((((((((((((((*"" 301 | """****(((((****""" 302 | 303 | -=[Capstone Engine v$($VerCount[1]).$($VerCount[0])]=- 304 | 305 | "@ 306 | # Mmm ASCII version banner! 307 | $Banner 308 | Return 309 | } 310 | 311 | # Disasm Handle 312 | $DisAsmHandle = [IntPtr]::Zero 313 | 314 | # Initialize Capstone with cs_open() 315 | $CallResult = [Capstone]::cs_open($Architecture,$Mode,[ref]$DisAsmHandle) 316 | if ($CallResult -ne "CS_ERR_OK") { 317 | if ($CallResult -eq "CS_ERR_MODE"){ 318 | echo "`n[!] Invalid Architecture/Mode combination" 319 | echo "[>] Quitting..`n" 320 | } else { 321 | echo "`n[!] cs_open error: $CallResult" 322 | echo "[>] Quitting..`n" 323 | } 324 | Return 325 | } 326 | 327 | # Set disassembly syntax 328 | #--- 329 | # cs_opt_type -> CS_OPT_SYNTAX = 1 330 | #--- 331 | # cs_opt_value -> CS_OPT_SYNTAX_INTEL = 1 332 | # -> CS_OPT_SYNTAX_ATT = 2 333 | if ($Syntax -eq "Intel") { 334 | $CS_OPT_SYNTAX = 1 335 | } else { 336 | $CS_OPT_SYNTAX = 2 337 | } 338 | $CallResult = [Capstone]::cs_option($DisAsmHandle, 1, $CS_OPT_SYNTAX) 339 | if ($CallResult -ne "CS_ERR_OK") { 340 | echo "`n[!] cs_option error: $CallResult" 341 | echo "[>] Quitting..`n" 342 | $CallResult = [Capstone]::cs_close([ref]$DisAsmHandle) 343 | Return 344 | } 345 | 346 | # Set disassembly detail 347 | #--- 348 | # cs_opt_type -> CS_OPT_DETAIL = 2 349 | #--- 350 | # cs_opt_value -> CS_OPT_ON = 3 351 | # -> CS_OPT_OFF = 0 352 | if ($Detailed) { 353 | $CS_OPT = 3 354 | } else { 355 | $CS_OPT = 0 356 | } 357 | $CallResult = [Capstone]::cs_option($DisAsmHandle, 2, $CS_OPT) 358 | if ($CallResult -ne "CS_ERR_OK") { 359 | echo "`n[!] cs_option error: $CallResult" 360 | echo "[>] Quitting..`n" 361 | $CallResult = [Capstone]::cs_close([ref]$DisAsmHandle) 362 | Return 363 | } 364 | 365 | # Out Buffer Handle 366 | $InsnHandle = [IntPtr]::Zero 367 | 368 | # Disassemble bytes 369 | $Count = [Capstone]::cs_disasm($DisAsmHandle, $Bytes, $Bytes.Count, $Address, 0, [ref]$InsnHandle) 370 | 371 | if ($Count -gt 0) { 372 | # Result Array 373 | $Disasm = @() 374 | 375 | # Result struct 376 | $cs_insn = New-Object cs_insn 377 | $cs_insn_size = [System.Runtime.InteropServices.Marshal]::SizeOf($cs_insn) 378 | $cs_insn = $cs_insn.GetType() 379 | 380 | # Result detail struct 381 | $cs_detail = New-Object cs_detail 382 | $cs_detail = $cs_detail.GetType() 383 | 384 | # Result buffer offset 385 | $BuffOffset = $InsnHandle.ToInt64() 386 | 387 | for ($i=0; $i -lt $Count; $i++) { 388 | # Cast Offset to cs_insn 389 | $InsnPointer = New-Object System.Intptr -ArgumentList $BuffOffset 390 | $Cast = [system.runtime.interopservices.marshal]::PtrToStructure($InsnPointer,[type]$cs_insn) 391 | 392 | if ($CS_OPT -eq 0) { 393 | $HashTable = @{ 394 | Address = echo "0x$("{0:X}" -f $Cast.address)" 395 | Instruction = echo "$($Cast.mnemonic) $($Cast.operands)" 396 | } 397 | $Object = New-Object PSObject -Property $HashTable 398 | $Disasm += $Object |Select-Object Address,Instruction 399 | } else { 400 | $DetailCast = [system.runtime.interopservices.marshal]::PtrToStructure($Cast.detail,[type]$cs_detail) 401 | if($DetailCast.regs_read_count -gt 0) { 402 | $RegRead = @() 403 | for ($r=0; $r -lt $DetailCast.regs_read_count; $r++) { 404 | $NamePointer = [Capstone]::cs_reg_name($DisAsmHandle, $DetailCast.regs_read[$r]) 405 | $RegRead += [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($NamePointer) 406 | } 407 | } 408 | if ($DetailCast.regs_write_count -gt 0) { 409 | $RegWrite = @() 410 | for ($r=0; $r -lt $DetailCast.regs_write_count; $r++) { 411 | $NamePointer = [Capstone]::cs_reg_name($DisAsmHandle, $DetailCast.regs_write[$r]) 412 | $RegWrite += [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($NamePointer) 413 | } 414 | } 415 | $HashTable = @{ 416 | Address = echo "0x$("{0:X}" -f $Cast.address)" 417 | Mnemonic = $Cast.mnemonic 418 | Operands = $Cast.operands 419 | Bytes = $Cast.bytes 420 | Size = $Cast.size 421 | RegRead = $RegRead 422 | RegWrite = $RegWrite 423 | } 424 | $Object = New-Object PSObject -Property $HashTable 425 | $Disasm += $Object |Select-Object Size,Address,Mnemonic,Operands,Bytes,RegRead,RegWrite 426 | } 427 | $BuffOffset = $BuffOffset + $cs_insn_size 428 | } 429 | } else { 430 | echo "`n[!] Disassembly Failed" 431 | echo "[>] Quitting..`n" 432 | $CallResult = [Capstone]::cs_close([ref]$DisAsmHandle) 433 | Return 434 | } 435 | 436 | # Print result 437 | $Disasm 438 | 439 | # Free Buffer Handle 440 | $CallResult = [Capstone]::cs_free($InsnHandle, $Count) 441 | } --------------------------------------------------------------------------------