• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download

Get-CapstoneDisassembly()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 }