Home | History | Annotate | Download | only in Capstone
      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 }