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 $DllPath = $($PSScriptRoot + '\Lib\Capstone\capstone.dll').Replace('\','\\') 144 145 # Make sure the user didn't forget the DLL 146 if (![IO.File]::Exists($DllPath)) { 147 echo "`n[!] Missing Capstone DLL" 148 echo "[>] Quitting!`n" 149 Return 150 } 151 152 # Inline C# to parse the unmanaged capstone DLL 153 Add-Type -TypeDefinition @" 154 using System; 155 using System.Diagnostics; 156 using System.Runtime.InteropServices; 157 using System.Security.Principal; 158 159 [StructLayout(LayoutKind.Sequential)] 160 public struct cs_insn 161 { 162 public uint id; 163 public ulong address; 164 public ushort size; 165 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] 166 public byte[] bytes; 167 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 168 public string mnemonic; 169 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 160)] 170 public string operands; 171 public IntPtr detail; 172 } 173 174 /// Partial, only architecture-independent internal data 175 [StructLayout(LayoutKind.Sequential)] 176 public struct cs_detail 177 { 178 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] 179 public byte[] regs_read; 180 public byte regs_read_count; 181 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] 182 public byte[] regs_write; 183 public byte regs_write_count; 184 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] 185 public byte[] groups; 186 public byte groups_count; 187 } 188 189 public enum cs_err : int 190 { 191 CS_ERR_OK = 0, /// No error: everything was fine 192 CS_ERR_MEM, /// Out-Of-Memory error: cs_open(), cs_disasm(), cs_disasm_iter() 193 CS_ERR_ARCH, /// Unsupported architecture: cs_open() 194 CS_ERR_HANDLE, /// Invalid handle: cs_op_count(), cs_op_index() 195 CS_ERR_CSH, /// Invalid csh argument: cs_close(), cs_errno(), cs_option() 196 CS_ERR_MODE, /// Invalid/unsupported mode: cs_open() 197 CS_ERR_OPTION, /// Invalid/unsupported option: cs_option() 198 CS_ERR_DETAIL, /// Information is unavailable because detail option is OFF 199 CS_ERR_MEMSETUP, /// Dynamic memory management uninitialized (see CS_OPT_MEM) 200 CS_ERR_VERSION, /// Unsupported version (bindings) 201 CS_ERR_DIET, /// Access irrelevant data in "diet" engine 202 CS_ERR_SKIPDATA, /// Access irrelevant data for "data" instruction in SKIPDATA mode 203 CS_ERR_X86_ATT, /// X86 AT&T syntax is unsupported (opt-out at compile time) 204 CS_ERR_X86_INTEL, /// X86 Intel syntax is unsupported (opt-out at compile time) 205 } 206 public enum cs_arch : int 207 { 208 CS_ARCH_ARM = 0, /// ARM architecture (including Thumb, Thumb-2) 209 CS_ARCH_ARM64, /// ARM-64, also called AArch64 210 CS_ARCH_MIPS, /// Mips architecture 211 CS_ARCH_X86, /// X86 architecture (including x86 & x86-64) 212 CS_ARCH_PPC, /// PowerPC architecture 213 CS_ARCH_SPARC, /// Sparc architecture 214 CS_ARCH_SYSZ, /// SystemZ architecture 215 CS_ARCH_XCORE, /// XCore architecture 216 CS_ARCH_MAX, 217 CS_ARCH_ALL = 0xFFFF, /// All architectures - for cs_support() 218 } 219 public enum cs_mode : int 220 { 221 CS_MODE_LITTLE_ENDIAN = 0, /// little-endian mode (default mode) 222 CS_MODE_ARM = 0, /// 32-bit ARM 223 CS_MODE_16 = 1 << 1, /// 16-bit mode (X86) 224 CS_MODE_32 = 1 << 2, /// 32-bit mode (X86) 225 CS_MODE_64 = 1 << 3, /// 64-bit mode (X86, PPC) 226 CS_MODE_THUMB = 1 << 4, /// ARM's Thumb mode, including Thumb-2 227 CS_MODE_MCLASS = 1 << 5, /// ARM's Cortex-M series 228 CS_MODE_V8 = 1 << 6, /// ARMv8 A32 encodings for ARM 229 CS_MODE_MICRO = 1 << 4, /// MicroMips mode (MIPS) 230 CS_MODE_MIPS3 = 1 << 5, /// Mips III ISA 231 CS_MODE_MIPS32R6 = 1 << 6, /// Mips32r6 ISA 232 CS_MODE_MIPSGP64 = 1 << 7, /// General Purpose Registers are 64-bit wide (MIPS) 233 CS_MODE_V9 = 1 << 4, /// SparcV9 mode (Sparc) 234 CS_MODE_BIG_ENDIAN = 1 << 31, /// big-endian mode 235 CS_MODE_MIPS32 = CS_MODE_32, /// Mips32 ISA (Mips) 236 CS_MODE_MIPS64 = CS_MODE_64, /// Mips64 ISA (Mips) 237 } 238 239 public static class Capstone 240 { 241 [DllImport("$DllPath")] 242 public static extern cs_err cs_open( 243 cs_arch arch, 244 cs_mode mode, 245 ref IntPtr handle); 246 247 [DllImport("$DllPath")] 248 public static extern UInt32 cs_disasm( 249 IntPtr handle, 250 byte[] code, 251 int code_size, 252 ulong address, 253 int count, 254 ref IntPtr insn); 255 256 [DllImport("$DllPath")] 257 public static extern bool cs_free( 258 IntPtr insn, 259 int count); 260 261 [DllImport("$DllPath")] 262 public static extern cs_err cs_close( 263 ref IntPtr handle); 264 265 [DllImport("$DllPath")] 266 public static extern cs_err cs_option( 267 IntPtr handle, 268 int type, 269 int value); 270 271 [DllImport("$DllPath", CallingConvention = CallingConvention.Cdecl)] 272 public static extern IntPtr cs_reg_name( 273 IntPtr handle, 274 uint reg_id); 275 276 [DllImport("$DllPath")] 277 public static extern int cs_version( 278 uint major, 279 uint minor); 280 } 281 "@ 282 283 if ($Version){ 284 $VerCount = [System.BitConverter]::GetBytes($([Capstone]::cs_version($null,$null))) 285 $Banner = @" 286 287 (((; 288 (; "((((\ 289 ;((((((; "((((; 290 ((((""\(((( "(((( 291 ((((" ((\ "(((( "(((\ 292 ;(((/ ((((((( "(((( \((( 293 ((((" (((* "(((( \(((;"(((\ 294 ((((";((("/(( \(((;"(((\"(((\ 295 (((( (((( ((((" "(((\ ((() (((\ 296 ;((("(((( (((* **"" ((()"(((; 297 (((" ((( (((( ((((((((((((((:*((( 298 (((( (((*)((( ********"""" ;;(((((; 299 (((* ((( (((((((((((((((((((((*"" ( 300 ((("(((( """***********"""" ;;((((( 301 "" (((((((((((((((((((((((((((*"" 302 """****(((((****""" 303 304 -=[Capstone Engine v$($VerCount[1]).$($VerCount[0])]=- 305 306 "@ 307 # Mmm ASCII version banner! 308 $Banner 309 Return 310 } 311 312 # Disasm Handle 313 $DisAsmHandle = [IntPtr]::Zero 314 315 # Initialize Capstone with cs_open() 316 $CallResult = [Capstone]::cs_open($Architecture,$Mode,[ref]$DisAsmHandle) 317 if ($CallResult -ne "CS_ERR_OK") { 318 if ($CallResult -eq "CS_ERR_MODE"){ 319 echo "`n[!] Invalid Architecture/Mode combination" 320 echo "[>] Quitting..`n" 321 } else { 322 echo "`n[!] cs_open error: $CallResult" 323 echo "[>] Quitting..`n" 324 } 325 Return 326 } 327 328 # Set disassembly syntax 329 #--- 330 # cs_opt_type -> CS_OPT_SYNTAX = 1 331 #--- 332 # cs_opt_value -> CS_OPT_SYNTAX_INTEL = 1 333 # -> CS_OPT_SYNTAX_ATT = 2 334 if ($Syntax -eq "Intel") { 335 $CS_OPT_SYNTAX = 1 336 } else { 337 $CS_OPT_SYNTAX = 2 338 } 339 $CallResult = [Capstone]::cs_option($DisAsmHandle, 1, $CS_OPT_SYNTAX) 340 if ($CallResult -ne "CS_ERR_OK") { 341 echo "`n[!] cs_option error: $CallResult" 342 echo "[>] Quitting..`n" 343 $CallResult = [Capstone]::cs_close([ref]$DisAsmHandle) 344 Return 345 } 346 347 # Set disassembly detail 348 #--- 349 # cs_opt_type -> CS_OPT_DETAIL = 2 350 #--- 351 # cs_opt_value -> CS_OPT_ON = 3 352 # -> CS_OPT_OFF = 0 353 if ($Detailed) { 354 $CS_OPT = 3 355 } else { 356 $CS_OPT = 0 357 } 358 $CallResult = [Capstone]::cs_option($DisAsmHandle, 2, $CS_OPT) 359 if ($CallResult -ne "CS_ERR_OK") { 360 echo "`n[!] cs_option error: $CallResult" 361 echo "[>] Quitting..`n" 362 $CallResult = [Capstone]::cs_close([ref]$DisAsmHandle) 363 Return 364 } 365 366 # Out Buffer Handle 367 $InsnHandle = [IntPtr]::Zero 368 369 # Disassemble bytes 370 $Count = [Capstone]::cs_disasm($DisAsmHandle, $Bytes, $Bytes.Count, $Address, 0, [ref]$InsnHandle) 371 372 if ($Count -gt 0) { 373 # Result Array 374 $Disasm = @() 375 376 # Result struct 377 $cs_insn = New-Object cs_insn 378 $cs_insn_size = [System.Runtime.InteropServices.Marshal]::SizeOf($cs_insn) 379 $cs_insn = $cs_insn.GetType() 380 381 # Result detail struct 382 $cs_detail = New-Object cs_detail 383 $cs_detail = $cs_detail.GetType() 384 385 # Result buffer offset 386 $BuffOffset = $InsnHandle.ToInt64() 387 388 for ($i=0; $i -lt $Count; $i++) { 389 # Cast Offset to cs_insn 390 $InsnPointer = New-Object System.Intptr -ArgumentList $BuffOffset 391 $Cast = [system.runtime.interopservices.marshal]::PtrToStructure($InsnPointer,[type]$cs_insn) 392 393 if ($CS_OPT -eq 0) { 394 $HashTable = @{ 395 Address = echo "0x$("{0:X}" -f $Cast.address)" 396 Instruction = echo "$($Cast.mnemonic) $($Cast.operands)" 397 } 398 $Object = New-Object PSObject -Property $HashTable 399 $Disasm += $Object |Select-Object Address,Instruction 400 } else { 401 $DetailCast = [system.runtime.interopservices.marshal]::PtrToStructure($Cast.detail,[type]$cs_detail) 402 if($DetailCast.regs_read_count -gt 0) { 403 $RegRead = @() 404 for ($r=0; $r -lt $DetailCast.regs_read_count; $r++) { 405 $NamePointer = [Capstone]::cs_reg_name($DisAsmHandle, $DetailCast.regs_read[$r]) 406 $RegRead += [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($NamePointer) 407 } 408 } 409 if ($DetailCast.regs_write_count -gt 0) { 410 $RegWrite = @() 411 for ($r=0; $r -lt $DetailCast.regs_write_count; $r++) { 412 $NamePointer = [Capstone]::cs_reg_name($DisAsmHandle, $DetailCast.regs_write[$r]) 413 $RegWrite += [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($NamePointer) 414 } 415 } 416 $HashTable = @{ 417 Address = echo "0x$("{0:X}" -f $Cast.address)" 418 Mnemonic = $Cast.mnemonic 419 Operands = $Cast.operands 420 Bytes = $Cast.bytes 421 Size = $Cast.size 422 RegRead = $RegRead 423 RegWrite = $RegWrite 424 } 425 $Object = New-Object PSObject -Property $HashTable 426 $Disasm += $Object |Select-Object Size,Address,Mnemonic,Operands,Bytes,RegRead,RegWrite 427 } 428 $BuffOffset = $BuffOffset + $cs_insn_size 429 } 430 } else { 431 echo "`n[!] Disassembly Failed" 432 echo "[>] Quitting..`n" 433 $CallResult = [Capstone]::cs_close([ref]$DisAsmHandle) 434 Return 435 } 436 437 # Print result 438 $Disasm 439 440 # Free Buffer Handle 441 $CallResult = [Capstone]::cs_free($InsnHandle, $Count) 442 }