1*9a0e4156SSadaf Ebrahimi <#
2*9a0e4156SSadaf Ebrahimi .SYNOPSIS
3*9a0e4156SSadaf Ebrahimi Get Capstone version as Version object
4*9a0e4156SSadaf Ebrahimi #>
Get-CapstoneVersionnull5*9a0e4156SSadaf Ebrahimi function Get-CapstoneVersion {
6*9a0e4156SSadaf Ebrahimi $Version = [System.BitConverter]::GetBytes(
7*9a0e4156SSadaf Ebrahimi [Capstone]::cs_version($null, $null)
8*9a0e4156SSadaf Ebrahimi )
9*9a0e4156SSadaf Ebrahimi
10*9a0e4156SSadaf Ebrahimi New-Object -TypeName version -ArgumentList @(
11*9a0e4156SSadaf Ebrahimi $Version[1]
12*9a0e4156SSadaf Ebrahimi $Version[0]
13*9a0e4156SSadaf Ebrahimi 0
14*9a0e4156SSadaf Ebrahimi 0
15*9a0e4156SSadaf Ebrahimi )
16*9a0e4156SSadaf Ebrahimi }
17*9a0e4156SSadaf Ebrahimi
18*9a0e4156SSadaf Ebrahimi <#
19*9a0e4156SSadaf Ebrahimi .SYNOPSIS
20*9a0e4156SSadaf Ebrahimi Create C# bindings for capstone.dll
21*9a0e4156SSadaf Ebrahimi
22*9a0e4156SSadaf Ebrahimi .PARAMETER DllPath
23*9a0e4156SSadaf Ebrahimi Path to capstone.dll
24*9a0e4156SSadaf Ebrahimi #>
Initialize-Capstone()25*9a0e4156SSadaf Ebrahimi function Initialize-Capstone {
26*9a0e4156SSadaf Ebrahimi [CmdletBinding()]
27*9a0e4156SSadaf Ebrahimi Param (
28*9a0e4156SSadaf Ebrahimi [Parameter(Mandatory = $true)]
29*9a0e4156SSadaf Ebrahimi [ValidateScript( {
30*9a0e4156SSadaf Ebrahimi try {
31*9a0e4156SSadaf Ebrahimi Test-Path -Path $_ -PathType Leaf -ErrorAction Stop
32*9a0e4156SSadaf Ebrahimi } catch {
33*9a0e4156SSadaf Ebrahimi throw "Capstone DLL is missing: $DllPath"
34*9a0e4156SSadaf Ebrahimi }
35*9a0e4156SSadaf Ebrahimi })]
36*9a0e4156SSadaf Ebrahimi [ValidateNotNullOrEmpty()]
37*9a0e4156SSadaf Ebrahimi [string]$DllPath
38*9a0e4156SSadaf Ebrahimi )
39*9a0e4156SSadaf Ebrahimi
40*9a0e4156SSadaf Ebrahimi # Escape path for use in inline C#
41*9a0e4156SSadaf Ebrahimi $DllPath = $DllPath.Replace('\', '\\')
42*9a0e4156SSadaf Ebrahimi
43*9a0e4156SSadaf Ebrahimi # Inline C# to parse the unmanaged capstone DLL
44*9a0e4156SSadaf Ebrahimi # http://stackoverflow.com/questions/16552801/how-do-i-conditionally-add-a-class-with-add-type-typedefinition-if-it-isnt-add
45*9a0e4156SSadaf Ebrahimi if (-not ([System.Management.Automation.PSTypeName]'Capstone').Type) {
46*9a0e4156SSadaf Ebrahimi Add-Type -TypeDefinition @"
47*9a0e4156SSadaf Ebrahimi using System;
48*9a0e4156SSadaf Ebrahimi using System.Diagnostics;
49*9a0e4156SSadaf Ebrahimi using System.Runtime.InteropServices;
50*9a0e4156SSadaf Ebrahimi using System.Security.Principal;
51*9a0e4156SSadaf Ebrahimi
52*9a0e4156SSadaf Ebrahimi [StructLayout(LayoutKind.Sequential)]
53*9a0e4156SSadaf Ebrahimi public struct cs_insn
54*9a0e4156SSadaf Ebrahimi {
55*9a0e4156SSadaf Ebrahimi public uint id;
56*9a0e4156SSadaf Ebrahimi public ulong address;
57*9a0e4156SSadaf Ebrahimi public ushort size;
58*9a0e4156SSadaf Ebrahimi [MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)]
59*9a0e4156SSadaf Ebrahimi public byte[] bytes;
60*9a0e4156SSadaf Ebrahimi [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
61*9a0e4156SSadaf Ebrahimi public string mnemonic;
62*9a0e4156SSadaf Ebrahimi [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 160)]
63*9a0e4156SSadaf Ebrahimi public string operands;
64*9a0e4156SSadaf Ebrahimi public IntPtr detail;
65*9a0e4156SSadaf Ebrahimi }
66*9a0e4156SSadaf Ebrahimi
67*9a0e4156SSadaf Ebrahimi /// Partial, only architecture-independent internal data
68*9a0e4156SSadaf Ebrahimi [StructLayout(LayoutKind.Sequential)]
69*9a0e4156SSadaf Ebrahimi public struct cs_detail
70*9a0e4156SSadaf Ebrahimi {
71*9a0e4156SSadaf Ebrahimi [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
72*9a0e4156SSadaf Ebrahimi public byte[] regs_read;
73*9a0e4156SSadaf Ebrahimi public byte regs_read_count;
74*9a0e4156SSadaf Ebrahimi [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
75*9a0e4156SSadaf Ebrahimi public byte[] regs_write;
76*9a0e4156SSadaf Ebrahimi public byte regs_write_count;
77*9a0e4156SSadaf Ebrahimi [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
78*9a0e4156SSadaf Ebrahimi public byte[] groups;
79*9a0e4156SSadaf Ebrahimi public byte groups_count;
80*9a0e4156SSadaf Ebrahimi }
81*9a0e4156SSadaf Ebrahimi
82*9a0e4156SSadaf Ebrahimi public enum cs_err : int
83*9a0e4156SSadaf Ebrahimi {
84*9a0e4156SSadaf Ebrahimi CS_ERR_OK = 0, /// No error: everything was fine
85*9a0e4156SSadaf Ebrahimi CS_ERR_MEM, /// Out-Of-Memory error: cs_open(), cs_disasm(), cs_disasm_iter()
86*9a0e4156SSadaf Ebrahimi CS_ERR_ARCH, /// Unsupported architecture: cs_open()
87*9a0e4156SSadaf Ebrahimi CS_ERR_HANDLE, /// Invalid handle: cs_op_count(), cs_op_index()
88*9a0e4156SSadaf Ebrahimi CS_ERR_CSH, /// Invalid csh argument: cs_close(), cs_errno(), cs_option()
89*9a0e4156SSadaf Ebrahimi CS_ERR_MODE, /// Invalid/unsupported mode: cs_open()
90*9a0e4156SSadaf Ebrahimi CS_ERR_OPTION, /// Invalid/unsupported option: cs_option()
91*9a0e4156SSadaf Ebrahimi CS_ERR_DETAIL, /// Information is unavailable because detail option is OFF
92*9a0e4156SSadaf Ebrahimi CS_ERR_MEMSETUP, /// Dynamic memory management uninitialized (see CS_OPT_MEM)
93*9a0e4156SSadaf Ebrahimi CS_ERR_VERSION, /// Unsupported version (bindings)
94*9a0e4156SSadaf Ebrahimi CS_ERR_DIET, /// Access irrelevant data in "diet" engine
95*9a0e4156SSadaf Ebrahimi CS_ERR_SKIPDATA, /// Access irrelevant data for "data" instruction in SKIPDATA mode
96*9a0e4156SSadaf Ebrahimi CS_ERR_X86_ATT, /// X86 AT&T syntax is unsupported (opt-out at compile time)
97*9a0e4156SSadaf Ebrahimi CS_ERR_X86_INTEL, /// X86 Intel syntax is unsupported (opt-out at compile time)
98*9a0e4156SSadaf Ebrahimi }
99*9a0e4156SSadaf Ebrahimi public enum cs_arch : int
100*9a0e4156SSadaf Ebrahimi {
101*9a0e4156SSadaf Ebrahimi CS_ARCH_ARM = 0, /// ARM architecture (including Thumb, Thumb-2)
102*9a0e4156SSadaf Ebrahimi CS_ARCH_ARM64, /// ARM-64, also called AArch64
103*9a0e4156SSadaf Ebrahimi CS_ARCH_MIPS, /// Mips architecture
104*9a0e4156SSadaf Ebrahimi CS_ARCH_X86, /// X86 architecture (including x86 & x86-64)
105*9a0e4156SSadaf Ebrahimi CS_ARCH_PPC, /// PowerPC architecture
106*9a0e4156SSadaf Ebrahimi CS_ARCH_SPARC, /// Sparc architecture
107*9a0e4156SSadaf Ebrahimi CS_ARCH_SYSZ, /// SystemZ architecture
108*9a0e4156SSadaf Ebrahimi CS_ARCH_XCORE, /// XCore architecture
109*9a0e4156SSadaf Ebrahimi CS_ARCH_MAX,
110*9a0e4156SSadaf Ebrahimi CS_ARCH_ALL = 0xFFFF, /// All architectures - for cs_support()
111*9a0e4156SSadaf Ebrahimi }
112*9a0e4156SSadaf Ebrahimi public enum cs_mode : int
113*9a0e4156SSadaf Ebrahimi {
114*9a0e4156SSadaf Ebrahimi CS_MODE_LITTLE_ENDIAN = 0, /// little-endian mode (default mode)
115*9a0e4156SSadaf Ebrahimi CS_MODE_ARM = 0, /// 32-bit ARM
116*9a0e4156SSadaf Ebrahimi CS_MODE_16 = 1 << 1, /// 16-bit mode (X86)
117*9a0e4156SSadaf Ebrahimi CS_MODE_32 = 1 << 2, /// 32-bit mode (X86)
118*9a0e4156SSadaf Ebrahimi CS_MODE_64 = 1 << 3, /// 64-bit mode (X86, PPC)
119*9a0e4156SSadaf Ebrahimi CS_MODE_THUMB = 1 << 4, /// ARM's Thumb mode, including Thumb-2
120*9a0e4156SSadaf Ebrahimi CS_MODE_MCLASS = 1 << 5, /// ARM's Cortex-M series
121*9a0e4156SSadaf Ebrahimi CS_MODE_V8 = 1 << 6, /// ARMv8 A32 encodings for ARM
122*9a0e4156SSadaf Ebrahimi CS_MODE_MICRO = 1 << 4, /// MicroMips mode (MIPS)
123*9a0e4156SSadaf Ebrahimi CS_MODE_MIPS3 = 1 << 5, /// Mips III ISA
124*9a0e4156SSadaf Ebrahimi CS_MODE_MIPS32R6 = 1 << 6, /// Mips32r6 ISA
125*9a0e4156SSadaf Ebrahimi CS_MODE_MIPSGP64 = 1 << 7, /// General Purpose Registers are 64-bit wide (MIPS)
126*9a0e4156SSadaf Ebrahimi CS_MODE_V9 = 1 << 4, /// SparcV9 mode (Sparc)
127*9a0e4156SSadaf Ebrahimi CS_MODE_BIG_ENDIAN = 1 << 31, /// big-endian mode
128*9a0e4156SSadaf Ebrahimi CS_MODE_MIPS32 = CS_MODE_32, /// Mips32 ISA (Mips)
129*9a0e4156SSadaf Ebrahimi CS_MODE_MIPS64 = CS_MODE_64, /// Mips64 ISA (Mips)
130*9a0e4156SSadaf Ebrahimi }
131*9a0e4156SSadaf Ebrahimi
132*9a0e4156SSadaf Ebrahimi public static class Capstone
133*9a0e4156SSadaf Ebrahimi {
134*9a0e4156SSadaf Ebrahimi [DllImport("$DllPath")]
135*9a0e4156SSadaf Ebrahimi public static extern cs_err cs_open(
136*9a0e4156SSadaf Ebrahimi cs_arch arch,
137*9a0e4156SSadaf Ebrahimi cs_mode mode,
138*9a0e4156SSadaf Ebrahimi ref IntPtr handle);
139*9a0e4156SSadaf Ebrahimi
140*9a0e4156SSadaf Ebrahimi [DllImport("$DllPath")]
141*9a0e4156SSadaf Ebrahimi public static extern UInt32 cs_disasm(
142*9a0e4156SSadaf Ebrahimi IntPtr handle,
143*9a0e4156SSadaf Ebrahimi byte[] code,
144*9a0e4156SSadaf Ebrahimi int code_size,
145*9a0e4156SSadaf Ebrahimi ulong address,
146*9a0e4156SSadaf Ebrahimi int count,
147*9a0e4156SSadaf Ebrahimi ref IntPtr insn);
148*9a0e4156SSadaf Ebrahimi
149*9a0e4156SSadaf Ebrahimi [DllImport("$DllPath")]
150*9a0e4156SSadaf Ebrahimi public static extern bool cs_free(
151*9a0e4156SSadaf Ebrahimi IntPtr insn,
152*9a0e4156SSadaf Ebrahimi int count);
153*9a0e4156SSadaf Ebrahimi
154*9a0e4156SSadaf Ebrahimi [DllImport("$DllPath")]
155*9a0e4156SSadaf Ebrahimi public static extern cs_err cs_close(
156*9a0e4156SSadaf Ebrahimi ref IntPtr handle);
157*9a0e4156SSadaf Ebrahimi
158*9a0e4156SSadaf Ebrahimi [DllImport("$DllPath")]
159*9a0e4156SSadaf Ebrahimi public static extern cs_err cs_option(
160*9a0e4156SSadaf Ebrahimi IntPtr handle,
161*9a0e4156SSadaf Ebrahimi int type,
162*9a0e4156SSadaf Ebrahimi int value);
163*9a0e4156SSadaf Ebrahimi
164*9a0e4156SSadaf Ebrahimi [DllImport("$DllPath", CallingConvention = CallingConvention.Cdecl)]
165*9a0e4156SSadaf Ebrahimi public static extern IntPtr cs_reg_name(
166*9a0e4156SSadaf Ebrahimi IntPtr handle,
167*9a0e4156SSadaf Ebrahimi uint reg_id);
168*9a0e4156SSadaf Ebrahimi
169*9a0e4156SSadaf Ebrahimi [DllImport("$DllPath")]
170*9a0e4156SSadaf Ebrahimi public static extern int cs_version(
171*9a0e4156SSadaf Ebrahimi uint major,
172*9a0e4156SSadaf Ebrahimi uint minor);
173*9a0e4156SSadaf Ebrahimi }
174*9a0e4156SSadaf Ebrahimi "@
175*9a0e4156SSadaf Ebrahimi } else {
176*9a0e4156SSadaf Ebrahimi Write-Verbose 'C# bindings are already compiled'
177*9a0e4156SSadaf Ebrahimi }
178*9a0e4156SSadaf Ebrahimi }
179*9a0e4156SSadaf Ebrahimi
Get-CapstoneDisassembly()180*9a0e4156SSadaf Ebrahimi function Get-CapstoneDisassembly {
181*9a0e4156SSadaf Ebrahimi <#
182*9a0e4156SSadaf Ebrahimi .SYNOPSIS
183*9a0e4156SSadaf Ebrahimi Powershell wrapper for Capstone (using inline C#).
184*9a0e4156SSadaf Ebrahimi
185*9a0e4156SSadaf Ebrahimi .DESCRIPTION
186*9a0e4156SSadaf Ebrahimi Author: Ruben Boonen (@FuzzySec), @beatcracker
187*9a0e4156SSadaf Ebrahimi License: BSD 3-Clause
188*9a0e4156SSadaf Ebrahimi Required Dependencies: None
189*9a0e4156SSadaf Ebrahimi Optional Dependencies: None
190*9a0e4156SSadaf Ebrahimi
191*9a0e4156SSadaf Ebrahimi .PARAMETER Architecture
192*9a0e4156SSadaf Ebrahimi Architecture type.
193*9a0e4156SSadaf Ebrahimi
194*9a0e4156SSadaf Ebrahimi .PARAMETER Mode
195*9a0e4156SSadaf Ebrahimi Mode type.
196*9a0e4156SSadaf Ebrahimi
197*9a0e4156SSadaf Ebrahimi .PARAMETER Bytes
198*9a0e4156SSadaf Ebrahimi Byte array to be disassembled.
199*9a0e4156SSadaf Ebrahimi
200*9a0e4156SSadaf Ebrahimi .PARAMETER Syntax
201*9a0e4156SSadaf Ebrahimi Syntax for output assembly.
202*9a0e4156SSadaf Ebrahimi
203*9a0e4156SSadaf Ebrahimi .PARAMETER Address
204*9a0e4156SSadaf Ebrahimi Assign address for the first instruction to be disassembled.
205*9a0e4156SSadaf Ebrahimi
206*9a0e4156SSadaf Ebrahimi .PARAMETER Detailed
207*9a0e4156SSadaf Ebrahimi Return detailed output.
208*9a0e4156SSadaf Ebrahimi
209*9a0e4156SSadaf Ebrahimi .PARAMETER Version
210*9a0e4156SSadaf Ebrahimi Print ASCII version banner.
211*9a0e4156SSadaf Ebrahimi
212*9a0e4156SSadaf Ebrahimi .EXAMPLE
213*9a0e4156SSadaf Ebrahimi
214*9a0e4156SSadaf Ebrahimi C:\PS> $Bytes = [byte[]] @( 0x10, 0xf1, 0x10, 0xe7, 0x11, 0xf2, 0x31, 0xe7, 0xdc, 0xa1, 0x2e, 0xf3, 0xe8, 0x4e, 0x62, 0xf3 )
215*9a0e4156SSadaf Ebrahimi C:\PS> Get-CapstoneDisassembly -Architecture CS_ARCH_ARM -Mode CS_MODE_ARM -Bytes $Bytes
216*9a0e4156SSadaf Ebrahimi
217*9a0e4156SSadaf Ebrahimi Address : 0x100000
218*9a0e4156SSadaf Ebrahimi Instruction : sdiv r0, r0, r1
219*9a0e4156SSadaf Ebrahimi
220*9a0e4156SSadaf Ebrahimi Address : 0x100004
221*9a0e4156SSadaf Ebrahimi Instruction : udiv r1, r1, r2
222*9a0e4156SSadaf Ebrahimi
223*9a0e4156SSadaf Ebrahimi Address : 0x100008
224*9a0e4156SSadaf Ebrahimi Instruction : vbit q5, q15, q6
225*9a0e4156SSadaf Ebrahimi
226*9a0e4156SSadaf Ebrahimi Address : 0x10000C
227*9a0e4156SSadaf Ebrahimi Instruction : vcgt.f32 q10, q9, q12
228*9a0e4156SSadaf Ebrahimi
229*9a0e4156SSadaf Ebrahimi .EXAMPLE
230*9a0e4156SSadaf Ebrahimi
231*9a0e4156SSadaf Ebrahimi # Detailed mode & ATT syntax
232*9a0e4156SSadaf Ebrahimi C:\PS> $Bytes = [byte[]] @( 0xB8, 0x0A, 0x00, 0x00, 0x00, 0xF7, 0xF3 )
233*9a0e4156SSadaf Ebrahimi C:\PS> Get-CapstoneDisassembly -Architecture CS_ARCH_X86 -Mode CS_MODE_32 -Bytes $Bytes -Syntax ATT -Detailed
234*9a0e4156SSadaf Ebrahimi
235*9a0e4156SSadaf Ebrahimi Address : 0x100000
236*9a0e4156SSadaf Ebrahimi Mnemonic : movl
237*9a0e4156SSadaf Ebrahimi Operands : $0xa, %eax
238*9a0e4156SSadaf Ebrahimi Bytes : {184, 10, 0, 0...}
239*9a0e4156SSadaf Ebrahimi Size : 5
240*9a0e4156SSadaf Ebrahimi RegRead :
241*9a0e4156SSadaf Ebrahimi RegWrite :
242*9a0e4156SSadaf Ebrahimi
243*9a0e4156SSadaf Ebrahimi Address : 0x100005
244*9a0e4156SSadaf Ebrahimi Mnemonic : divl
245*9a0e4156SSadaf Ebrahimi Operands : %ebx
246*9a0e4156SSadaf Ebrahimi Bytes : {247, 243}
247*9a0e4156SSadaf Ebrahimi Size : 2
248*9a0e4156SSadaf Ebrahimi RegRead : {eax, edx}
249*9a0e4156SSadaf Ebrahimi RegWrite : {eax, edx, eflags}
250*9a0e4156SSadaf Ebrahimi
251*9a0e4156SSadaf Ebrahimi .EXAMPLE
252*9a0e4156SSadaf Ebrahimi
253*9a0e4156SSadaf Ebrahimi # Get-CapstoneDisassembly emits objects
254*9a0e4156SSadaf Ebrahimi C:\PS> $Bytes = [byte[]] @( 0xB8, 0x0A, 0x00, 0x00, 0x00, 0xF7, 0xF3 )
255*9a0e4156SSadaf Ebrahimi C:\PS> $Object = Get-CapstoneDisassembly -Architecture CS_ARCH_X86 -Mode CS_MODE_32 -Bytes $Bytes -Detailed
256*9a0e4156SSadaf Ebrahimi C:\PS> $Object | Select-Object -Property Size, Mnemonic, Operands
257*9a0e4156SSadaf Ebrahimi
258*9a0e4156SSadaf Ebrahimi Size Mnemonic Operands
259*9a0e4156SSadaf Ebrahimi ---- -------- --------
260*9a0e4156SSadaf Ebrahimi 5 mov eax, 0xa
261*9a0e4156SSadaf Ebrahimi 2 div ebx
262*9a0e4156SSadaf Ebrahimi #>
263*9a0e4156SSadaf Ebrahimi [CmdletBinding(DefaultParameterSetName = 'Capstone')]
264*9a0e4156SSadaf Ebrahimi Param (
265*9a0e4156SSadaf Ebrahimi [Parameter(ParameterSetName = 'Capstone', Mandatory = $true)]
266*9a0e4156SSadaf Ebrahimi [ValidateSet(
267*9a0e4156SSadaf Ebrahimi 'CS_ARCH_ARM',
268*9a0e4156SSadaf Ebrahimi 'CS_ARCH_ARM64',
269*9a0e4156SSadaf Ebrahimi 'CS_ARCH_MIPS',
270*9a0e4156SSadaf Ebrahimi 'CS_ARCH_X86',
271*9a0e4156SSadaf Ebrahimi 'CS_ARCH_PPC',
272*9a0e4156SSadaf Ebrahimi 'CS_ARCH_SPARC',
273*9a0e4156SSadaf Ebrahimi 'CS_ARCH_SYSZ',
274*9a0e4156SSadaf Ebrahimi 'CS_ARCH_XCORE',
275*9a0e4156SSadaf Ebrahimi 'CS_ARCH_MAX',
276*9a0e4156SSadaf Ebrahimi 'CS_ARCH_ALL'
277*9a0e4156SSadaf Ebrahimi )]
278*9a0e4156SSadaf Ebrahimi [string]$Architecture,
279*9a0e4156SSadaf Ebrahimi
280*9a0e4156SSadaf Ebrahimi [Parameter(ParameterSetName = 'Capstone', Mandatory = $true)]
281*9a0e4156SSadaf Ebrahimi [ValidateSet(
282*9a0e4156SSadaf Ebrahimi 'CS_MODE_LITTLE_ENDIAN',
283*9a0e4156SSadaf Ebrahimi 'CS_MODE_ARM',
284*9a0e4156SSadaf Ebrahimi 'CS_MODE_16',
285*9a0e4156SSadaf Ebrahimi 'CS_MODE_32',
286*9a0e4156SSadaf Ebrahimi 'CS_MODE_64',
287*9a0e4156SSadaf Ebrahimi 'CS_MODE_THUMB',
288*9a0e4156SSadaf Ebrahimi 'CS_MODE_MCLASS',
289*9a0e4156SSadaf Ebrahimi 'CS_MODE_V8',
290*9a0e4156SSadaf Ebrahimi 'CS_MODE_MICRO',
291*9a0e4156SSadaf Ebrahimi 'CS_MODE_MIPS3',
292*9a0e4156SSadaf Ebrahimi 'CS_MODE_MIPS32R6',
293*9a0e4156SSadaf Ebrahimi 'CS_MODE_MIPSGP64',
294*9a0e4156SSadaf Ebrahimi 'CS_MODE_V9',
295*9a0e4156SSadaf Ebrahimi 'CS_MODE_BIG_ENDIAN',
296*9a0e4156SSadaf Ebrahimi 'CS_MODE_MIPS32',
297*9a0e4156SSadaf Ebrahimi 'CS_MODE_MIPS64'
298*9a0e4156SSadaf Ebrahimi )]
299*9a0e4156SSadaf Ebrahimi [string]$Mode,
300*9a0e4156SSadaf Ebrahimi
301*9a0e4156SSadaf Ebrahimi [Parameter(ParameterSetName = 'Capstone', Mandatory = $true)]
302*9a0e4156SSadaf Ebrahimi [ValidateNotNullOrEmpty()]
303*9a0e4156SSadaf Ebrahimi [byte[]]$Bytes,
304*9a0e4156SSadaf Ebrahimi
305*9a0e4156SSadaf Ebrahimi [Parameter(ParameterSetName = 'Capstone')]
306*9a0e4156SSadaf Ebrahimi [ValidateSet(
307*9a0e4156SSadaf Ebrahimi 'Intel',
308*9a0e4156SSadaf Ebrahimi 'ATT'
309*9a0e4156SSadaf Ebrahimi )]
310*9a0e4156SSadaf Ebrahimi [string]$Syntax = 'Intel',
311*9a0e4156SSadaf Ebrahimi
312*9a0e4156SSadaf Ebrahimi [Parameter(ParameterSetName = 'Capstone')]
313*9a0e4156SSadaf Ebrahimi [uint64]$Address = 0x100000,
314*9a0e4156SSadaf Ebrahimi
315*9a0e4156SSadaf Ebrahimi [Parameter(ParameterSetName = 'Capstone')]
316*9a0e4156SSadaf Ebrahimi [switch]$Detailed,
317*9a0e4156SSadaf Ebrahimi
318*9a0e4156SSadaf Ebrahimi [Parameter(ParameterSetName = 'Version')]
319*9a0e4156SSadaf Ebrahimi [switch]$Version
320*9a0e4156SSadaf Ebrahimi )
321*9a0e4156SSadaf Ebrahimi
322*9a0e4156SSadaf Ebrahimi if ($Version) {
323*9a0e4156SSadaf Ebrahimi $Banner = @'
324*9a0e4156SSadaf Ebrahimi
325*9a0e4156SSadaf Ebrahimi (((;
326*9a0e4156SSadaf Ebrahimi (; "((((\
327*9a0e4156SSadaf Ebrahimi ;((((((; "((((;
328*9a0e4156SSadaf Ebrahimi ((((""\(((( "((((
329*9a0e4156SSadaf Ebrahimi ((((" ((\ "(((( "(((\
330*9a0e4156SSadaf Ebrahimi ;(((/ ((((((( "(((( \(((
331*9a0e4156SSadaf Ebrahimi ((((" (((* "(((( \(((;"(((\
332*9a0e4156SSadaf Ebrahimi ((((";((("/(( \(((;"(((\"(((\
333*9a0e4156SSadaf Ebrahimi (((( (((( ((((" "(((\ ((() (((\
334*9a0e4156SSadaf Ebrahimi ;((("(((( (((* **"" ((()"(((;
335*9a0e4156SSadaf Ebrahimi (((" ((( (((( ((((((((((((((:*(((
336*9a0e4156SSadaf Ebrahimi (((( (((*)((( ********"""" ;;(((((;
337*9a0e4156SSadaf Ebrahimi (((* ((( (((((((((((((((((((((*"" (
338*9a0e4156SSadaf Ebrahimi ((("(((( """***********"""" ;;(((((
339*9a0e4156SSadaf Ebrahimi "" (((((((((((((((((((((((((((*""
340*9a0e4156SSadaf Ebrahimi """****(((((****"""
341*9a0e4156SSadaf Ebrahimi
342*9a0e4156SSadaf Ebrahimi -=[Capstone Engine v{0}]=-
343*9a0e4156SSadaf Ebrahimi
344*9a0e4156SSadaf Ebrahimi '@ -f (Get-CapstoneVersion).ToString(2)
345*9a0e4156SSadaf Ebrahimi # Mmm ASCII version banner!
346*9a0e4156SSadaf Ebrahimi return $Banner
347*9a0e4156SSadaf Ebrahimi }
348*9a0e4156SSadaf Ebrahimi
349*9a0e4156SSadaf Ebrahimi # Disasm Handle
350*9a0e4156SSadaf Ebrahimi $DisAsmHandle = [System.IntPtr]::Zero
351*9a0e4156SSadaf Ebrahimi
352*9a0e4156SSadaf Ebrahimi # Initialize Capstone with cs_open()
353*9a0e4156SSadaf Ebrahimi $CallResult = [Capstone]::cs_open($Architecture, $Mode, [ref]$DisAsmHandle)
354*9a0e4156SSadaf Ebrahimi if ($CallResult -ne 'CS_ERR_OK') {
355*9a0e4156SSadaf Ebrahimi if ($CallResult -eq 'CS_ERR_MODE') {
356*9a0e4156SSadaf Ebrahimi throw "Invalid Architecture/Mode combination: $Architecture/$Mode"
357*9a0e4156SSadaf Ebrahimi } else {
358*9a0e4156SSadaf Ebrahimi throw "cs_open error: $CallResult"
359*9a0e4156SSadaf Ebrahimi }
360*9a0e4156SSadaf Ebrahimi }
361*9a0e4156SSadaf Ebrahimi
362*9a0e4156SSadaf Ebrahimi # Set disassembly syntax
363*9a0e4156SSadaf Ebrahimi #---
364*9a0e4156SSadaf Ebrahimi # cs_opt_type -> CS_OPT_SYNTAX = 1
365*9a0e4156SSadaf Ebrahimi #---
366*9a0e4156SSadaf Ebrahimi # cs_opt_value -> CS_OPT_SYNTAX_INTEL = 1
367*9a0e4156SSadaf Ebrahimi # -> CS_OPT_SYNTAX_ATT = 2
368*9a0e4156SSadaf Ebrahimi if ($Syntax -eq 'Intel') {
369*9a0e4156SSadaf Ebrahimi $CS_OPT_SYNTAX = 1
370*9a0e4156SSadaf Ebrahimi } else {
371*9a0e4156SSadaf Ebrahimi $CS_OPT_SYNTAX = 2
372*9a0e4156SSadaf Ebrahimi }
373*9a0e4156SSadaf Ebrahimi
374*9a0e4156SSadaf Ebrahimi $CallResult = [Capstone]::cs_option($DisAsmHandle, 1, $CS_OPT_SYNTAX)
375*9a0e4156SSadaf Ebrahimi if ($CallResult -ne 'CS_ERR_OK') {
376*9a0e4156SSadaf Ebrahimi $CallResult = [Capstone]::cs_close([ref]$DisAsmHandle)
377*9a0e4156SSadaf Ebrahimi throw "cs_option error: $CallResult"
378*9a0e4156SSadaf Ebrahimi }
379*9a0e4156SSadaf Ebrahimi
380*9a0e4156SSadaf Ebrahimi # Set disassembly detail
381*9a0e4156SSadaf Ebrahimi #---
382*9a0e4156SSadaf Ebrahimi # cs_opt_type -> CS_OPT_DETAIL = 2
383*9a0e4156SSadaf Ebrahimi #---
384*9a0e4156SSadaf Ebrahimi # cs_opt_value -> CS_OPT_ON = 3
385*9a0e4156SSadaf Ebrahimi # -> CS_OPT_OFF = 0
386*9a0e4156SSadaf Ebrahimi if ($Detailed) {
387*9a0e4156SSadaf Ebrahimi $CS_OPT = 3
388*9a0e4156SSadaf Ebrahimi } else {
389*9a0e4156SSadaf Ebrahimi $CS_OPT = 0
390*9a0e4156SSadaf Ebrahimi }
391*9a0e4156SSadaf Ebrahimi
392*9a0e4156SSadaf Ebrahimi $CallResult = [Capstone]::cs_option($DisAsmHandle, 2, $CS_OPT)
393*9a0e4156SSadaf Ebrahimi if ($CallResult -ne 'CS_ERR_OK') {
394*9a0e4156SSadaf Ebrahimi $CallResult = [Capstone]::cs_close([ref]$DisAsmHandle)
395*9a0e4156SSadaf Ebrahimi throw "cs_option error: $CallResult"
396*9a0e4156SSadaf Ebrahimi }
397*9a0e4156SSadaf Ebrahimi
398*9a0e4156SSadaf Ebrahimi # Out Buffer Handle
399*9a0e4156SSadaf Ebrahimi $InsnHandle = [System.IntPtr]::Zero
400*9a0e4156SSadaf Ebrahimi
401*9a0e4156SSadaf Ebrahimi # Disassemble bytes
402*9a0e4156SSadaf Ebrahimi $Count = [Capstone]::cs_disasm($DisAsmHandle, $Bytes, $Bytes.Count, $Address, 0, [ref]$InsnHandle)
403*9a0e4156SSadaf Ebrahimi
404*9a0e4156SSadaf Ebrahimi if ($Count -gt 0) {
405*9a0e4156SSadaf Ebrahimi # Result struct
406*9a0e4156SSadaf Ebrahimi $cs_insn = if ($PSVersionTable.PSVersion.Major -gt 2) {
407*9a0e4156SSadaf Ebrahimi [cs_insn]@{}
408*9a0e4156SSadaf Ebrahimi } else {
409*9a0e4156SSadaf Ebrahimi New-Object -TypeName cs_insn
410*9a0e4156SSadaf Ebrahimi }
411*9a0e4156SSadaf Ebrahimi
412*9a0e4156SSadaf Ebrahimi $cs_insn_size = [System.Runtime.InteropServices.Marshal]::SizeOf($cs_insn)
413*9a0e4156SSadaf Ebrahimi $cs_insn = $cs_insn.GetType()
414*9a0e4156SSadaf Ebrahimi
415*9a0e4156SSadaf Ebrahimi # Result detail struct
416*9a0e4156SSadaf Ebrahimi $cs_detail = if ($PSVersionTable.PSVersion.Major -gt 2) {
417*9a0e4156SSadaf Ebrahimi [cs_detail]@{}
418*9a0e4156SSadaf Ebrahimi } else {
419*9a0e4156SSadaf Ebrahimi New-Object -TypeName cs_detail
420*9a0e4156SSadaf Ebrahimi }
421*9a0e4156SSadaf Ebrahimi $cs_detail = $cs_detail.GetType()
422*9a0e4156SSadaf Ebrahimi
423*9a0e4156SSadaf Ebrahimi # Result buffer offset
424*9a0e4156SSadaf Ebrahimi $BuffOffset = $InsnHandle.ToInt64()
425*9a0e4156SSadaf Ebrahimi
426*9a0e4156SSadaf Ebrahimi for ($i = 0 ; $i -lt $Count ; $i++) {
427*9a0e4156SSadaf Ebrahimi # Cast Offset to cs_insn
428*9a0e4156SSadaf Ebrahimi $Cast = [System.Runtime.InteropServices.Marshal]::PtrToStructure([System.Intptr]$BuffOffset, [type]$cs_insn)
429*9a0e4156SSadaf Ebrahimi
430*9a0e4156SSadaf Ebrahimi if ($CS_OPT -eq 0) {
431*9a0e4156SSadaf Ebrahimi $Disassembly = @{
432*9a0e4156SSadaf Ebrahimi Address = $Cast.address
433*9a0e4156SSadaf Ebrahimi Instruction = '{0} {1}' -f $Cast.mnemonic, $Cast.operands
434*9a0e4156SSadaf Ebrahimi }
435*9a0e4156SSadaf Ebrahimi
436*9a0e4156SSadaf Ebrahimi if ($PSVersionTable.PSVersion.Major -gt 2) {
437*9a0e4156SSadaf Ebrahimi # Add TypeName for PS formatting and output result
438*9a0e4156SSadaf Ebrahimi $Disassembly.PSTypeName ='CapstoneDisassembly.Simple'
439*9a0e4156SSadaf Ebrahimi [pscustomobject]$Disassembly
440*9a0e4156SSadaf Ebrahimi } else {
441*9a0e4156SSadaf Ebrahimi $Disassembly = New-Object -TypeName PSObject -Property $Disassembly
442*9a0e4156SSadaf Ebrahimi # Add TypeName for PS formatting and output result
443*9a0e4156SSadaf Ebrahimi $Disassembly.PSObject.TypeNames.Insert(0, 'CapstoneDisassembly.Simple')
444*9a0e4156SSadaf Ebrahimi $Disassembly
445*9a0e4156SSadaf Ebrahimi }
446*9a0e4156SSadaf Ebrahimi } else {
447*9a0e4156SSadaf Ebrahimi $DetailCast = [System.Runtime.InteropServices.Marshal]::PtrToStructure($Cast.detail, [type]$cs_detail)
448*9a0e4156SSadaf Ebrahimi if ($DetailCast.regs_read_count -gt 0) {
449*9a0e4156SSadaf Ebrahimi $RegRead = for ($r = 0 ; $r -lt $DetailCast.regs_read_count ; $r++) {
450*9a0e4156SSadaf Ebrahimi $NamePointer = [Capstone]::cs_reg_name($DisAsmHandle, $DetailCast.regs_read[$r])
451*9a0e4156SSadaf Ebrahimi [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($NamePointer)
452*9a0e4156SSadaf Ebrahimi }
453*9a0e4156SSadaf Ebrahimi }
454*9a0e4156SSadaf Ebrahimi
455*9a0e4156SSadaf Ebrahimi if ($DetailCast.regs_write_count -gt 0) {
456*9a0e4156SSadaf Ebrahimi $RegWrite = for ($r = 0 ; $r -lt $DetailCast.regs_write_count ; $r++) {
457*9a0e4156SSadaf Ebrahimi $NamePointer = [Capstone]::cs_reg_name($DisAsmHandle, $DetailCast.regs_write[$r])
458*9a0e4156SSadaf Ebrahimi [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($NamePointer)
459*9a0e4156SSadaf Ebrahimi }
460*9a0e4156SSadaf Ebrahimi }
461*9a0e4156SSadaf Ebrahimi
462*9a0e4156SSadaf Ebrahimi $Disassembly = @{
463*9a0e4156SSadaf Ebrahimi Address = $Cast.address
464*9a0e4156SSadaf Ebrahimi Mnemonic = $Cast.mnemonic
465*9a0e4156SSadaf Ebrahimi Operands = $Cast.operands
466*9a0e4156SSadaf Ebrahimi Bytes = $Cast.bytes[0..($Cast.size - 1)]
467*9a0e4156SSadaf Ebrahimi Size = $Cast.size
468*9a0e4156SSadaf Ebrahimi RegRead = $RegRead
469*9a0e4156SSadaf Ebrahimi RegWrite = $RegWrite
470*9a0e4156SSadaf Ebrahimi }
471*9a0e4156SSadaf Ebrahimi
472*9a0e4156SSadaf Ebrahimi if ($PSVersionTable.PSVersion.Major -gt 2) {
473*9a0e4156SSadaf Ebrahimi # Add TypeName for PS formatting and output result
474*9a0e4156SSadaf Ebrahimi $Disassembly.PSTypeName = 'CapstoneDisassembly.Detailed'
475*9a0e4156SSadaf Ebrahimi [pscustomobject]$Disassembly
476*9a0e4156SSadaf Ebrahimi } else {
477*9a0e4156SSadaf Ebrahimi $Disassembly = New-Object -TypeName PSObject -Property $Disassembly
478*9a0e4156SSadaf Ebrahimi # Add TypeName for PS formatting and output result
479*9a0e4156SSadaf Ebrahimi $Disassembly.PSObject.TypeNames.Insert(0, 'CapstoneDisassembly.Detailed')
480*9a0e4156SSadaf Ebrahimi $Disassembly
481*9a0e4156SSadaf Ebrahimi }
482*9a0e4156SSadaf Ebrahimi }
483*9a0e4156SSadaf Ebrahimi $BuffOffset = $BuffOffset + $cs_insn_size
484*9a0e4156SSadaf Ebrahimi }
485*9a0e4156SSadaf Ebrahimi } else {
486*9a0e4156SSadaf Ebrahimi $CallResult = [Capstone]::cs_close([ref]$DisAsmHandle)
487*9a0e4156SSadaf Ebrahimi throw 'Disassembly Failed'
488*9a0e4156SSadaf Ebrahimi }
489*9a0e4156SSadaf Ebrahimi
490*9a0e4156SSadaf Ebrahimi # Free Buffer Handle
491*9a0e4156SSadaf Ebrahimi $CallResult = [Capstone]::cs_free($InsnHandle, $Count)
492*9a0e4156SSadaf Ebrahimi }
493*9a0e4156SSadaf Ebrahimi
494*9a0e4156SSadaf Ebrahimi #region Init
495*9a0e4156SSadaf Ebrahimi
496*9a0e4156SSadaf Ebrahimi Initialize-Capstone -DllPath (
497*9a0e4156SSadaf Ebrahimi Join-Path -Path $PSScriptRoot -ChildPath 'Lib\Capstone\capstone.dll'
498*9a0e4156SSadaf Ebrahimi ) -ErrorAction Stop
499*9a0e4156SSadaf Ebrahimi
500*9a0e4156SSadaf Ebrahimi #endregion