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 }