mirror of
https://github.com/capstone-engine/capstone.git
synced 2024-11-27 23:40:25 +00:00
Update PowerShell bindings (#1239)
* Remove trailing whitespace * ~2x speedup by removing array appending More info: https://powershell.org/2013/09/16/powershell-performance-the-operator-and-when-to-avoid-it/ * Import inline C# conditionally Avoids errors when importing module using "-Force" * Throw exception on missing DLL + use idiomatic PowerShell * Throw exception on errors + use idiomatic PowerShell * Throw exception on errors + use idiomatic PowerShell * Use idiomatic PowerShell * Fix DLL path escaping * Add native PowerShell formatting Instruction address will display as "0xdeadbeef" in console output, but the actual value will be stored as appropriate integer type. This allows to use "Address" property directly in code that relies on Get-Capstone disasselbly w/o type conversion. The original module author was using hex-strings, because when you add things in PowerShell like this: $Integer + '0xFF' , PowerShell will cast everything to the type of the first operand. And it's smart enough to cast hex-string to integer. Example: https://github.com/FuzzySecurity/PowerShell-Suite/blob/master/Trace-Execution.ps1#L195 But this is unreliable and moreover, PowerShell has peculiar quirks when casting hex-strings: https://github.com/PowerShell/PowerShell/issues/3313 * Move Capstone init to separate function * Add Get-CaptoneVersion function Which resturns "version" object. Also add back erroneously deleted "return" to Get-CapstoneDisassembly -Version and convert it to advanced function. * Fix help text * Replace double quotes with single quotes where appropriate * No need to assign $null to switch params * Make return usage more obvious * No need for double quotes in version banner * Add space after comma * ~3x speedup by removing New-Object usage. Requires PS 3.0 * Cosmetic fixes * Remove PS 2.0 compatibility code * Fix PSScriptAnalyzer warnings * Don't load module if inline C# doesn't compile * Return actual instruction bytes * Fix version function * Use lowercase for accelerators * Remove "Mandatory = $False" since it's default * Add spaces around "=" and ";" * Use lowercase for built-in variables * Tabs -> Spaces * Update help * Use standard manifest * UTF-8, no BOM * Remove remaining New-Object invocations * Bump module version (semver anyone?) * Restore PSv2 compatibility Use [pscustomobject]/New-Object based on reported PS version. * Tabs -> Spaces * Update authors
This commit is contained in:
parent
5212dc571a
commit
d14da45e8f
157
bindings/powershell/Capstone/Capstone.Format.ps1xml
Normal file
157
bindings/powershell/Capstone/Capstone.Format.ps1xml
Normal file
@ -0,0 +1,157 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Configuration>
|
||||
<DefaultSettings>
|
||||
<EnumerableExpansions>
|
||||
<EnumerableExpansion>
|
||||
<Expand>Both</Expand>
|
||||
</EnumerableExpansion>
|
||||
</EnumerableExpansions>
|
||||
</DefaultSettings>
|
||||
<ViewDefinitions>
|
||||
<View>
|
||||
<Name>CapstoneDisassemblyViewSimple</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>CapstoneDisassembly.Simple</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<ListControl>
|
||||
<ListEntries>
|
||||
<ListEntry>
|
||||
<ListItems>
|
||||
<ListItem>
|
||||
<PropertyName>Address</PropertyName>
|
||||
<FormatString>0x{0:X}</FormatString>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>Instruction</PropertyName>
|
||||
</ListItem>
|
||||
</ListItems>
|
||||
</ListEntry>
|
||||
</ListEntries>
|
||||
</ListControl>
|
||||
</View>
|
||||
<View>
|
||||
<Name>CapstoneDisassemblyViewSimple</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>CapstoneDisassembly.Simple</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<TableControl>
|
||||
<TableHeaders>
|
||||
<TableColumnHeader>
|
||||
<Label>Address</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>Instruction</Label>
|
||||
</TableColumnHeader>
|
||||
</TableHeaders>
|
||||
<TableRowEntries>
|
||||
<TableRowEntry>
|
||||
<TableColumnItems>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Address</PropertyName>
|
||||
<FormatString>0x{0:x}</FormatString>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Instruction</PropertyName>
|
||||
</TableColumnItem>
|
||||
</TableColumnItems>
|
||||
</TableRowEntry>
|
||||
</TableRowEntries>
|
||||
</TableControl>
|
||||
</View>
|
||||
<View>
|
||||
<Name>CapstoneDisassemblyViewDetailed</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>CapstoneDisassembly.Detailed</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<ListControl>
|
||||
<ListEntries>
|
||||
<ListEntry>
|
||||
<ListItems>
|
||||
<ListItem>
|
||||
<PropertyName>Address</PropertyName>
|
||||
<FormatString>0x{0:X}</FormatString>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>Mnemonic</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>Operands</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>Bytes</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>Size</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>RegRead</PropertyName>
|
||||
</ListItem>
|
||||
<ListItem>
|
||||
<PropertyName>RegWrite</PropertyName>
|
||||
</ListItem>
|
||||
</ListItems>
|
||||
</ListEntry>
|
||||
</ListEntries>
|
||||
</ListControl>
|
||||
</View>
|
||||
<View>
|
||||
<Name>CapstoneDisassemblyViewDetailed</Name>
|
||||
<ViewSelectedBy>
|
||||
<TypeName>CapstoneDisassembly.Detailed</TypeName>
|
||||
</ViewSelectedBy>
|
||||
<TableControl>
|
||||
<TableHeaders>
|
||||
<TableColumnHeader>
|
||||
<Label>Address</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>Mnemonic</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>Operands</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>Bytes</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>Size</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>RegRead</Label>
|
||||
</TableColumnHeader>
|
||||
<TableColumnHeader>
|
||||
<Label>RegWrite</Label>
|
||||
</TableColumnHeader>
|
||||
</TableHeaders>
|
||||
<TableRowEntries>
|
||||
<TableRowEntry>
|
||||
<TableColumnItems>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Address</PropertyName>
|
||||
<FormatString>0x{0:x}</FormatString>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Mnemonic</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Operands</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Bytes</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>Size</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>RegRead</PropertyName>
|
||||
</TableColumnItem>
|
||||
<TableColumnItem>
|
||||
<PropertyName>RegWrite</PropertyName>
|
||||
</TableColumnItem>
|
||||
</TableColumnItems>
|
||||
</TableRowEntry>
|
||||
</TableRowEntries>
|
||||
</TableControl>
|
||||
</View>
|
||||
</ViewDefinitions>
|
||||
</Configuration>
|
@ -1,25 +1,118 @@
|
||||
@{
|
||||
# Script module or binary module file associated with this manifest.
|
||||
ModuleToProcess = 'Capstone.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '0.0.0.1'
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = 'd34db33f-9958-436d-a2d8-a77844a2bda5'
|
||||
|
||||
# Author of this module
|
||||
Author = 'Ruben Boonen'
|
||||
|
||||
# Copyright statement for this module
|
||||
Copyright = 'BSD 3-Clause'
|
||||
|
||||
# Description of the functionality provided by this module
|
||||
Description = 'Capstone Engine Binding Module'
|
||||
|
||||
# Minimum version of the Windows PowerShell engine required by this module
|
||||
PowerShellVersion = '2.0'
|
||||
|
||||
# Functions to export from this module
|
||||
FunctionsToExport = '*'
|
||||
}
|
||||
#
|
||||
# Module manifest for module 'Capstone'
|
||||
#
|
||||
|
||||
@{
|
||||
|
||||
# Script module or binary module file associated with this manifest.
|
||||
ModuleToProcess = 'Capstone.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '0.0.0.2'
|
||||
|
||||
# Supported PSEditions
|
||||
# CompatiblePSEditions = @()
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = 'd34db33f-9958-436d-a2d8-a77844a2bda5'
|
||||
|
||||
# Author of this module
|
||||
Author = 'Ruben Boonen, beatcracker'
|
||||
|
||||
# Company or vendor of this module
|
||||
# CompanyName = 'Unknown'
|
||||
|
||||
# Copyright statement for this module
|
||||
Copyright = 'BSD 3-Clause'
|
||||
|
||||
# Description of the functionality provided by this module
|
||||
Description = 'Capstone Engine Binding Module'
|
||||
|
||||
# Minimum version of the Windows PowerShell engine required by this module
|
||||
PowerShellVersion = '2.0'
|
||||
|
||||
# Name of the Windows PowerShell host required by this module
|
||||
# PowerShellHostName = ''
|
||||
|
||||
# Minimum version of the Windows PowerShell host required by this module
|
||||
# PowerShellHostVersion = ''
|
||||
|
||||
# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
|
||||
# DotNetFrameworkVersion = ''
|
||||
|
||||
# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
|
||||
# CLRVersion = ''
|
||||
|
||||
# Processor architecture (None, X86, Amd64) required by this module
|
||||
# ProcessorArchitecture = ''
|
||||
|
||||
# Modules that must be imported into the global environment prior to importing this module
|
||||
# RequiredModules = @()
|
||||
|
||||
# Assemblies that must be loaded prior to importing this module
|
||||
# RequiredAssemblies = @()
|
||||
|
||||
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
|
||||
# ScriptsToProcess = @()
|
||||
|
||||
# Type files (.ps1xml) to be loaded when importing this module
|
||||
# TypesToProcess = @()
|
||||
|
||||
# Format files (.ps1xml) to be loaded when importing this module
|
||||
FormatsToProcess = 'Capstone.Format.ps1xml'
|
||||
|
||||
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
|
||||
# NestedModules = @()
|
||||
|
||||
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
|
||||
FunctionsToExport = 'Get-CapstoneVersion', 'Get-CapstoneDisassembly'
|
||||
|
||||
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
|
||||
CmdletsToExport = @()
|
||||
|
||||
# Variables to export from this module
|
||||
VariablesToExport = @()
|
||||
|
||||
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
|
||||
AliasesToExport = @()
|
||||
|
||||
# DSC resources to export from this module
|
||||
# DscResourcesToExport = @()
|
||||
|
||||
# List of all modules packaged with this module
|
||||
# ModuleList = @()
|
||||
|
||||
# List of all files packaged with this module
|
||||
# FileList = @()
|
||||
|
||||
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
|
||||
PrivateData = @{
|
||||
|
||||
PSData = @{
|
||||
|
||||
# Tags applied to this module. These help with module discovery in online galleries.
|
||||
# Tags = @()
|
||||
|
||||
# A URL to the license for this module.
|
||||
# LicenseUri = ''
|
||||
|
||||
# A URL to the main website for this project.
|
||||
# ProjectUri = ''
|
||||
|
||||
# A URL to an icon representing this module.
|
||||
# IconUri = ''
|
||||
|
||||
# ReleaseNotes of this module
|
||||
# ReleaseNotes = ''
|
||||
|
||||
} # End of PSData hashtable
|
||||
|
||||
} # End of PrivateData hashtable
|
||||
|
||||
# HelpInfo URI of this module
|
||||
# HelpInfoURI = ''
|
||||
|
||||
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
|
||||
# DefaultCommandPrefix = ''
|
||||
|
||||
}
|
@ -1,442 +1,500 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Get Capstone version as Version object
|
||||
#>
|
||||
function Get-CapstoneVersion {
|
||||
$Version = [System.BitConverter]::GetBytes(
|
||||
[Capstone]::cs_version($null, $null)
|
||||
)
|
||||
|
||||
New-Object -TypeName version -ArgumentList @(
|
||||
$Version[1]
|
||||
$Version[0]
|
||||
0
|
||||
0
|
||||
)
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Create C# bindings for capstone.dll
|
||||
|
||||
.PARAMETER DllPath
|
||||
Path to capstone.dll
|
||||
#>
|
||||
function Initialize-Capstone {
|
||||
[CmdletBinding()]
|
||||
Param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateScript( {
|
||||
try {
|
||||
Test-Path -Path $_ -PathType Leaf -ErrorAction Stop
|
||||
} catch {
|
||||
throw "Capstone DLL is missing: $DllPath"
|
||||
}
|
||||
})]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]$DllPath
|
||||
)
|
||||
|
||||
# Escape path for use in inline C#
|
||||
$DllPath = $DllPath.Replace('\', '\\')
|
||||
|
||||
# Inline C# to parse the unmanaged capstone DLL
|
||||
# http://stackoverflow.com/questions/16552801/how-do-i-conditionally-add-a-class-with-add-type-typedefinition-if-it-isnt-add
|
||||
if (-not ([System.Management.Automation.PSTypeName]'Capstone').Type) {
|
||||
Add-Type -TypeDefinition @"
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct cs_insn
|
||||
{
|
||||
public uint id;
|
||||
public ulong address;
|
||||
public ushort size;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
|
||||
public byte[] bytes;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
|
||||
public string mnemonic;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 160)]
|
||||
public string operands;
|
||||
public IntPtr detail;
|
||||
}
|
||||
|
||||
/// Partial, only architecture-independent internal data
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct cs_detail
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
|
||||
public byte[] regs_read;
|
||||
public byte regs_read_count;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
|
||||
public byte[] regs_write;
|
||||
public byte regs_write_count;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
||||
public byte[] groups;
|
||||
public byte groups_count;
|
||||
}
|
||||
|
||||
public enum cs_err : int
|
||||
{
|
||||
CS_ERR_OK = 0, /// No error: everything was fine
|
||||
CS_ERR_MEM, /// Out-Of-Memory error: cs_open(), cs_disasm(), cs_disasm_iter()
|
||||
CS_ERR_ARCH, /// Unsupported architecture: cs_open()
|
||||
CS_ERR_HANDLE, /// Invalid handle: cs_op_count(), cs_op_index()
|
||||
CS_ERR_CSH, /// Invalid csh argument: cs_close(), cs_errno(), cs_option()
|
||||
CS_ERR_MODE, /// Invalid/unsupported mode: cs_open()
|
||||
CS_ERR_OPTION, /// Invalid/unsupported option: cs_option()
|
||||
CS_ERR_DETAIL, /// Information is unavailable because detail option is OFF
|
||||
CS_ERR_MEMSETUP, /// Dynamic memory management uninitialized (see CS_OPT_MEM)
|
||||
CS_ERR_VERSION, /// Unsupported version (bindings)
|
||||
CS_ERR_DIET, /// Access irrelevant data in "diet" engine
|
||||
CS_ERR_SKIPDATA, /// Access irrelevant data for "data" instruction in SKIPDATA mode
|
||||
CS_ERR_X86_ATT, /// X86 AT&T syntax is unsupported (opt-out at compile time)
|
||||
CS_ERR_X86_INTEL, /// X86 Intel syntax is unsupported (opt-out at compile time)
|
||||
}
|
||||
public enum cs_arch : int
|
||||
{
|
||||
CS_ARCH_ARM = 0, /// ARM architecture (including Thumb, Thumb-2)
|
||||
CS_ARCH_ARM64, /// ARM-64, also called AArch64
|
||||
CS_ARCH_MIPS, /// Mips architecture
|
||||
CS_ARCH_X86, /// X86 architecture (including x86 & x86-64)
|
||||
CS_ARCH_PPC, /// PowerPC architecture
|
||||
CS_ARCH_SPARC, /// Sparc architecture
|
||||
CS_ARCH_SYSZ, /// SystemZ architecture
|
||||
CS_ARCH_XCORE, /// XCore architecture
|
||||
CS_ARCH_MAX,
|
||||
CS_ARCH_ALL = 0xFFFF, /// All architectures - for cs_support()
|
||||
}
|
||||
public enum cs_mode : int
|
||||
{
|
||||
CS_MODE_LITTLE_ENDIAN = 0, /// little-endian mode (default mode)
|
||||
CS_MODE_ARM = 0, /// 32-bit ARM
|
||||
CS_MODE_16 = 1 << 1, /// 16-bit mode (X86)
|
||||
CS_MODE_32 = 1 << 2, /// 32-bit mode (X86)
|
||||
CS_MODE_64 = 1 << 3, /// 64-bit mode (X86, PPC)
|
||||
CS_MODE_THUMB = 1 << 4, /// ARM's Thumb mode, including Thumb-2
|
||||
CS_MODE_MCLASS = 1 << 5, /// ARM's Cortex-M series
|
||||
CS_MODE_V8 = 1 << 6, /// ARMv8 A32 encodings for ARM
|
||||
CS_MODE_MICRO = 1 << 4, /// MicroMips mode (MIPS)
|
||||
CS_MODE_MIPS3 = 1 << 5, /// Mips III ISA
|
||||
CS_MODE_MIPS32R6 = 1 << 6, /// Mips32r6 ISA
|
||||
CS_MODE_MIPSGP64 = 1 << 7, /// General Purpose Registers are 64-bit wide (MIPS)
|
||||
CS_MODE_V9 = 1 << 4, /// SparcV9 mode (Sparc)
|
||||
CS_MODE_BIG_ENDIAN = 1 << 31, /// big-endian mode
|
||||
CS_MODE_MIPS32 = CS_MODE_32, /// Mips32 ISA (Mips)
|
||||
CS_MODE_MIPS64 = CS_MODE_64, /// Mips64 ISA (Mips)
|
||||
}
|
||||
|
||||
public static class Capstone
|
||||
{
|
||||
[DllImport("$DllPath")]
|
||||
public static extern cs_err cs_open(
|
||||
cs_arch arch,
|
||||
cs_mode mode,
|
||||
ref IntPtr handle);
|
||||
|
||||
[DllImport("$DllPath")]
|
||||
public static extern UInt32 cs_disasm(
|
||||
IntPtr handle,
|
||||
byte[] code,
|
||||
int code_size,
|
||||
ulong address,
|
||||
int count,
|
||||
ref IntPtr insn);
|
||||
|
||||
[DllImport("$DllPath")]
|
||||
public static extern bool cs_free(
|
||||
IntPtr insn,
|
||||
int count);
|
||||
|
||||
[DllImport("$DllPath")]
|
||||
public static extern cs_err cs_close(
|
||||
ref IntPtr handle);
|
||||
|
||||
[DllImport("$DllPath")]
|
||||
public static extern cs_err cs_option(
|
||||
IntPtr handle,
|
||||
int type,
|
||||
int value);
|
||||
|
||||
[DllImport("$DllPath", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr cs_reg_name(
|
||||
IntPtr handle,
|
||||
uint reg_id);
|
||||
|
||||
[DllImport("$DllPath")]
|
||||
public static extern int cs_version(
|
||||
uint major,
|
||||
uint minor);
|
||||
}
|
||||
"@
|
||||
} else {
|
||||
Write-Verbose 'C# bindings are already compiled'
|
||||
}
|
||||
}
|
||||
|
||||
function Get-CapstoneDisassembly {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Powershell wrapper for Capstone (using inline C#).
|
||||
Powershell wrapper for Capstone (using inline C#).
|
||||
|
||||
.DESCRIPTION
|
||||
Author: Ruben Boonen (@FuzzySec)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
Author: Ruben Boonen (@FuzzySec), @beatcracker
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.PARAMETER Architecture
|
||||
Architecture type.
|
||||
Architecture type.
|
||||
|
||||
.PARAMETER Mode
|
||||
Mode type.
|
||||
Mode type.
|
||||
|
||||
.PARAMETER Bytes
|
||||
Byte array to be disassembled.
|
||||
Byte array to be disassembled.
|
||||
|
||||
.PARAMETER Syntax
|
||||
Syntax for output assembly.
|
||||
Syntax for output assembly.
|
||||
|
||||
.PARAMETER Address
|
||||
Assign address for the first instruction to be disassembled.
|
||||
Assign address for the first instruction to be disassembled.
|
||||
|
||||
.PARAMETER Detailed
|
||||
Return detailed output.
|
||||
Return detailed output.
|
||||
|
||||
.PARAMETER Version
|
||||
Print ASCII version banner.
|
||||
Print ASCII version banner.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> $Bytes = [Byte[]] @( 0x10, 0xf1, 0x10, 0xe7, 0x11, 0xf2, 0x31, 0xe7, 0xdc, 0xa1, 0x2e, 0xf3, 0xe8, 0x4e, 0x62, 0xf3 )
|
||||
C:\PS> Get-CapstoneDisassembly -Architecture CS_ARCH_ARM -Mode CS_MODE_ARM -Bytes $Bytes
|
||||
|
||||
sdiv r0, r0, r1
|
||||
udiv r1, r1, r2
|
||||
vbit q5, q15, q6
|
||||
vcgt.f32 q10, q9, q12
|
||||
C:\PS> $Bytes = [byte[]] @( 0x10, 0xf1, 0x10, 0xe7, 0x11, 0xf2, 0x31, 0xe7, 0xdc, 0xa1, 0x2e, 0xf3, 0xe8, 0x4e, 0x62, 0xf3 )
|
||||
C:\PS> Get-CapstoneDisassembly -Architecture CS_ARCH_ARM -Mode CS_MODE_ARM -Bytes $Bytes
|
||||
|
||||
Address : 0x100000
|
||||
Instruction : sdiv r0, r0, r1
|
||||
|
||||
Address : 0x100004
|
||||
Instruction : udiv r1, r1, r2
|
||||
|
||||
Address : 0x100008
|
||||
Instruction : vbit q5, q15, q6
|
||||
|
||||
Address : 0x10000C
|
||||
Instruction : vcgt.f32 q10, q9, q12
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
# Detailed mode & ATT syntax
|
||||
C:\PS> $Bytes = [Byte[]] @( 0xB8, 0x0A, 0x00, 0x00, 0x00, 0xF7, 0xF3 )
|
||||
C:\PS> Get-CapstoneDisassembly -Architecture CS_ARCH_X86 -Mode CS_MODE_32 -Bytes $Bytes -Syntax ATT -Detailed
|
||||
|
||||
Size : 5
|
||||
Address : 0x100000
|
||||
Mnemonic : movl
|
||||
Operands : $0xa, %eax
|
||||
Bytes : {184, 10, 0, 0...}
|
||||
RegRead :
|
||||
RegWrite :
|
||||
|
||||
Size : 2
|
||||
Address : 0x100005
|
||||
Mnemonic : divl
|
||||
Operands : %ebx
|
||||
Bytes : {247, 243, 0, 0...}
|
||||
RegRead : {eax, edx}
|
||||
RegWrite : {eax, edx, eflags}
|
||||
# Detailed mode & ATT syntax
|
||||
C:\PS> $Bytes = [byte[]] @( 0xB8, 0x0A, 0x00, 0x00, 0x00, 0xF7, 0xF3 )
|
||||
C:\PS> Get-CapstoneDisassembly -Architecture CS_ARCH_X86 -Mode CS_MODE_32 -Bytes $Bytes -Syntax ATT -Detailed
|
||||
|
||||
Address : 0x100000
|
||||
Mnemonic : movl
|
||||
Operands : $0xa, %eax
|
||||
Bytes : {184, 10, 0, 0...}
|
||||
Size : 5
|
||||
RegRead :
|
||||
RegWrite :
|
||||
|
||||
Address : 0x100005
|
||||
Mnemonic : divl
|
||||
Operands : %ebx
|
||||
Bytes : {247, 243}
|
||||
Size : 2
|
||||
RegRead : {eax, edx}
|
||||
RegWrite : {eax, edx, eflags}
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
# Get-CapstoneDisassembly emits objects
|
||||
C:\PS> $Bytes = [Byte[]] @( 0xB8, 0x0A, 0x00, 0x00, 0x00, 0xF7, 0xF3 )
|
||||
C:\PS> $Object = Get-CapstoneDisassembly -Architecture CS_ARCH_X86 -Mode CS_MODE_32 -Bytes $Bytes -Detailed
|
||||
C:\PS> $Object |Select-Object Size,Mnemonic,Operands
|
||||
|
||||
Size Mnemonic Operands
|
||||
---- -------- --------
|
||||
5 mov eax, 0xa
|
||||
2 div ebx
|
||||
# Get-CapstoneDisassembly emits objects
|
||||
C:\PS> $Bytes = [byte[]] @( 0xB8, 0x0A, 0x00, 0x00, 0x00, 0xF7, 0xF3 )
|
||||
C:\PS> $Object = Get-CapstoneDisassembly -Architecture CS_ARCH_X86 -Mode CS_MODE_32 -Bytes $Bytes -Detailed
|
||||
C:\PS> $Object | Select-Object -Property Size, Mnemonic, Operands
|
||||
|
||||
Size Mnemonic Operands
|
||||
---- -------- --------
|
||||
5 mov eax, 0xa
|
||||
2 div ebx
|
||||
#>
|
||||
[CmdletBinding(DefaultParameterSetName = 'Capstone')]
|
||||
Param (
|
||||
[Parameter(ParameterSetName = 'Capstone', Mandatory = $true)]
|
||||
[ValidateSet(
|
||||
'CS_ARCH_ARM',
|
||||
'CS_ARCH_ARM64',
|
||||
'CS_ARCH_MIPS',
|
||||
'CS_ARCH_X86',
|
||||
'CS_ARCH_PPC',
|
||||
'CS_ARCH_SPARC',
|
||||
'CS_ARCH_SYSZ',
|
||||
'CS_ARCH_XCORE',
|
||||
'CS_ARCH_MAX',
|
||||
'CS_ARCH_ALL'
|
||||
)]
|
||||
[string]$Architecture,
|
||||
|
||||
param(
|
||||
[Parameter(ParameterSetName='Capstone', Mandatory = $True)]
|
||||
[ValidateSet(
|
||||
'CS_ARCH_ARM',
|
||||
'CS_ARCH_ARM64',
|
||||
'CS_ARCH_MIPS',
|
||||
'CS_ARCH_X86',
|
||||
'CS_ARCH_PPC',
|
||||
'CS_ARCH_SPARC',
|
||||
'CS_ARCH_SYSZ',
|
||||
'CS_ARCH_XCORE',
|
||||
'CS_ARCH_MAX',
|
||||
'CS_ARCH_ALL')
|
||||
]
|
||||
[String]$Architecture,
|
||||
|
||||
[Parameter(ParameterSetName='Capstone', Mandatory = $True)]
|
||||
[ValidateSet(
|
||||
'CS_MODE_LITTLE_ENDIAN',
|
||||
'CS_MODE_ARM',
|
||||
'CS_MODE_16',
|
||||
'CS_MODE_32',
|
||||
'CS_MODE_64',
|
||||
'CS_MODE_THUMB',
|
||||
'CS_MODE_MCLASS',
|
||||
'CS_MODE_V8',
|
||||
'CS_MODE_MICRO',
|
||||
'CS_MODE_MIPS3',
|
||||
'CS_MODE_MIPS32R6',
|
||||
'CS_MODE_MIPSGP64',
|
||||
'CS_MODE_V9',
|
||||
'CS_MODE_BIG_ENDIAN',
|
||||
'CS_MODE_MIPS32',
|
||||
'CS_MODE_MIPS64')
|
||||
]
|
||||
[String]$Mode,
|
||||
|
||||
[Parameter(ParameterSetName='Capstone', Mandatory = $True)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[Byte[]]$Bytes,
|
||||
|
||||
[Parameter(ParameterSetName='Capstone', Mandatory = $False)]
|
||||
[ValidateSet(
|
||||
'Intel',
|
||||
'ATT')
|
||||
]
|
||||
[String]$Syntax = "Intel",
|
||||
[Parameter(ParameterSetName = 'Capstone', Mandatory = $true)]
|
||||
[ValidateSet(
|
||||
'CS_MODE_LITTLE_ENDIAN',
|
||||
'CS_MODE_ARM',
|
||||
'CS_MODE_16',
|
||||
'CS_MODE_32',
|
||||
'CS_MODE_64',
|
||||
'CS_MODE_THUMB',
|
||||
'CS_MODE_MCLASS',
|
||||
'CS_MODE_V8',
|
||||
'CS_MODE_MICRO',
|
||||
'CS_MODE_MIPS3',
|
||||
'CS_MODE_MIPS32R6',
|
||||
'CS_MODE_MIPSGP64',
|
||||
'CS_MODE_V9',
|
||||
'CS_MODE_BIG_ENDIAN',
|
||||
'CS_MODE_MIPS32',
|
||||
'CS_MODE_MIPS64'
|
||||
)]
|
||||
[string]$Mode,
|
||||
|
||||
[Parameter(ParameterSetName='Capstone', Mandatory = $False)]
|
||||
[UInt64]$Address = 0x100000,
|
||||
[Parameter(ParameterSetName = 'Capstone', Mandatory = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[byte[]]$Bytes,
|
||||
|
||||
[Parameter(ParameterSetName='Capstone', Mandatory = $False)]
|
||||
[switch]$Detailed = $null,
|
||||
|
||||
[Parameter(ParameterSetName='Version', Mandatory = $False)]
|
||||
[switch]$Version = $null
|
||||
[Parameter(ParameterSetName = 'Capstone')]
|
||||
[ValidateSet(
|
||||
'Intel',
|
||||
'ATT'
|
||||
)]
|
||||
[string]$Syntax = 'Intel',
|
||||
|
||||
[Parameter(ParameterSetName = 'Capstone')]
|
||||
[uint64]$Address = 0x100000,
|
||||
|
||||
[Parameter(ParameterSetName = 'Capstone')]
|
||||
[switch]$Detailed,
|
||||
|
||||
[Parameter(ParameterSetName = 'Version')]
|
||||
[switch]$Version
|
||||
)
|
||||
|
||||
# Compatibility for PS v2 / PS v3+
|
||||
if(!$PSScriptRoot) {
|
||||
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
|
||||
}
|
||||
|
||||
# Set the capstone DLL path
|
||||
$DllPath = $($PSScriptRoot + '\Lib\Capstone\capstone.dll').Replace('\','\\')
|
||||
if ($Version) {
|
||||
$Banner = @'
|
||||
|
||||
# Make sure the user didn't forget the DLL
|
||||
if (![IO.File]::Exists($DllPath)) {
|
||||
echo "`n[!] Missing Capstone DLL"
|
||||
echo "[>] Quitting!`n"
|
||||
Return
|
||||
}
|
||||
(((;
|
||||
(; "((((\
|
||||
;((((((; "((((;
|
||||
((((""\(((( "((((
|
||||
((((" ((\ "(((( "(((\
|
||||
;(((/ ((((((( "(((( \(((
|
||||
((((" (((* "(((( \(((;"(((\
|
||||
((((";((("/(( \(((;"(((\"(((\
|
||||
(((( (((( ((((" "(((\ ((() (((\
|
||||
;((("(((( (((* **"" ((()"(((;
|
||||
(((" ((( (((( ((((((((((((((:*(((
|
||||
(((( (((*)((( ********"""" ;;(((((;
|
||||
(((* ((( (((((((((((((((((((((*"" (
|
||||
((("(((( """***********"""" ;;(((((
|
||||
"" (((((((((((((((((((((((((((*""
|
||||
"""****(((((****"""
|
||||
|
||||
# Inline C# to parse the unmanaged capstone DLL
|
||||
Add-Type -TypeDefinition @"
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct cs_insn
|
||||
{
|
||||
public uint id;
|
||||
public ulong address;
|
||||
public ushort size;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
|
||||
public byte[] bytes;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
|
||||
public string mnemonic;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 160)]
|
||||
public string operands;
|
||||
public IntPtr detail;
|
||||
}
|
||||
-=[Capstone Engine v{0}]=-
|
||||
|
||||
/// Partial, only architecture-independent internal data
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct cs_detail
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
|
||||
public byte[] regs_read;
|
||||
public byte regs_read_count;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
|
||||
public byte[] regs_write;
|
||||
public byte regs_write_count;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
||||
public byte[] groups;
|
||||
public byte groups_count;
|
||||
}
|
||||
'@ -f (Get-CapstoneVersion).ToString(2)
|
||||
# Mmm ASCII version banner!
|
||||
return $Banner
|
||||
}
|
||||
|
||||
public enum cs_err : int
|
||||
{
|
||||
CS_ERR_OK = 0, /// No error: everything was fine
|
||||
CS_ERR_MEM, /// Out-Of-Memory error: cs_open(), cs_disasm(), cs_disasm_iter()
|
||||
CS_ERR_ARCH, /// Unsupported architecture: cs_open()
|
||||
CS_ERR_HANDLE, /// Invalid handle: cs_op_count(), cs_op_index()
|
||||
CS_ERR_CSH, /// Invalid csh argument: cs_close(), cs_errno(), cs_option()
|
||||
CS_ERR_MODE, /// Invalid/unsupported mode: cs_open()
|
||||
CS_ERR_OPTION, /// Invalid/unsupported option: cs_option()
|
||||
CS_ERR_DETAIL, /// Information is unavailable because detail option is OFF
|
||||
CS_ERR_MEMSETUP, /// Dynamic memory management uninitialized (see CS_OPT_MEM)
|
||||
CS_ERR_VERSION, /// Unsupported version (bindings)
|
||||
CS_ERR_DIET, /// Access irrelevant data in "diet" engine
|
||||
CS_ERR_SKIPDATA, /// Access irrelevant data for "data" instruction in SKIPDATA mode
|
||||
CS_ERR_X86_ATT, /// X86 AT&T syntax is unsupported (opt-out at compile time)
|
||||
CS_ERR_X86_INTEL, /// X86 Intel syntax is unsupported (opt-out at compile time)
|
||||
}
|
||||
public enum cs_arch : int
|
||||
{
|
||||
CS_ARCH_ARM = 0, /// ARM architecture (including Thumb, Thumb-2)
|
||||
CS_ARCH_ARM64, /// ARM-64, also called AArch64
|
||||
CS_ARCH_MIPS, /// Mips architecture
|
||||
CS_ARCH_X86, /// X86 architecture (including x86 & x86-64)
|
||||
CS_ARCH_PPC, /// PowerPC architecture
|
||||
CS_ARCH_SPARC, /// Sparc architecture
|
||||
CS_ARCH_SYSZ, /// SystemZ architecture
|
||||
CS_ARCH_XCORE, /// XCore architecture
|
||||
CS_ARCH_MAX,
|
||||
CS_ARCH_ALL = 0xFFFF, /// All architectures - for cs_support()
|
||||
}
|
||||
public enum cs_mode : int
|
||||
{
|
||||
CS_MODE_LITTLE_ENDIAN = 0, /// little-endian mode (default mode)
|
||||
CS_MODE_ARM = 0, /// 32-bit ARM
|
||||
CS_MODE_16 = 1 << 1, /// 16-bit mode (X86)
|
||||
CS_MODE_32 = 1 << 2, /// 32-bit mode (X86)
|
||||
CS_MODE_64 = 1 << 3, /// 64-bit mode (X86, PPC)
|
||||
CS_MODE_THUMB = 1 << 4, /// ARM's Thumb mode, including Thumb-2
|
||||
CS_MODE_MCLASS = 1 << 5, /// ARM's Cortex-M series
|
||||
CS_MODE_V8 = 1 << 6, /// ARMv8 A32 encodings for ARM
|
||||
CS_MODE_MICRO = 1 << 4, /// MicroMips mode (MIPS)
|
||||
CS_MODE_MIPS3 = 1 << 5, /// Mips III ISA
|
||||
CS_MODE_MIPS32R6 = 1 << 6, /// Mips32r6 ISA
|
||||
CS_MODE_MIPSGP64 = 1 << 7, /// General Purpose Registers are 64-bit wide (MIPS)
|
||||
CS_MODE_V9 = 1 << 4, /// SparcV9 mode (Sparc)
|
||||
CS_MODE_BIG_ENDIAN = 1 << 31, /// big-endian mode
|
||||
CS_MODE_MIPS32 = CS_MODE_32, /// Mips32 ISA (Mips)
|
||||
CS_MODE_MIPS64 = CS_MODE_64, /// Mips64 ISA (Mips)
|
||||
}
|
||||
|
||||
public static class Capstone
|
||||
{
|
||||
[DllImport("$DllPath")]
|
||||
public static extern cs_err cs_open(
|
||||
cs_arch arch,
|
||||
cs_mode mode,
|
||||
ref IntPtr handle);
|
||||
# Disasm Handle
|
||||
$DisAsmHandle = [System.IntPtr]::Zero
|
||||
|
||||
[DllImport("$DllPath")]
|
||||
public static extern UInt32 cs_disasm(
|
||||
IntPtr handle,
|
||||
byte[] code,
|
||||
int code_size,
|
||||
ulong address,
|
||||
int count,
|
||||
ref IntPtr insn);
|
||||
# Initialize Capstone with cs_open()
|
||||
$CallResult = [Capstone]::cs_open($Architecture, $Mode, [ref]$DisAsmHandle)
|
||||
if ($CallResult -ne 'CS_ERR_OK') {
|
||||
if ($CallResult -eq 'CS_ERR_MODE') {
|
||||
throw "Invalid Architecture/Mode combination: $Architecture/$Mode"
|
||||
} else {
|
||||
throw "cs_open error: $CallResult"
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("$DllPath")]
|
||||
public static extern bool cs_free(
|
||||
IntPtr insn,
|
||||
int count);
|
||||
# Set disassembly syntax
|
||||
#---
|
||||
# cs_opt_type -> CS_OPT_SYNTAX = 1
|
||||
#---
|
||||
# cs_opt_value -> CS_OPT_SYNTAX_INTEL = 1
|
||||
# -> CS_OPT_SYNTAX_ATT = 2
|
||||
if ($Syntax -eq 'Intel') {
|
||||
$CS_OPT_SYNTAX = 1
|
||||
} else {
|
||||
$CS_OPT_SYNTAX = 2
|
||||
}
|
||||
|
||||
[DllImport("$DllPath")]
|
||||
public static extern cs_err cs_close(
|
||||
ref IntPtr handle);
|
||||
$CallResult = [Capstone]::cs_option($DisAsmHandle, 1, $CS_OPT_SYNTAX)
|
||||
if ($CallResult -ne 'CS_ERR_OK') {
|
||||
$CallResult = [Capstone]::cs_close([ref]$DisAsmHandle)
|
||||
throw "cs_option error: $CallResult"
|
||||
}
|
||||
|
||||
[DllImport("$DllPath")]
|
||||
public static extern cs_err cs_option(
|
||||
IntPtr handle,
|
||||
int type,
|
||||
int value);
|
||||
# Set disassembly detail
|
||||
#---
|
||||
# cs_opt_type -> CS_OPT_DETAIL = 2
|
||||
#---
|
||||
# cs_opt_value -> CS_OPT_ON = 3
|
||||
# -> CS_OPT_OFF = 0
|
||||
if ($Detailed) {
|
||||
$CS_OPT = 3
|
||||
} else {
|
||||
$CS_OPT = 0
|
||||
}
|
||||
|
||||
[DllImport("$DllPath", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr cs_reg_name(
|
||||
IntPtr handle,
|
||||
uint reg_id);
|
||||
$CallResult = [Capstone]::cs_option($DisAsmHandle, 2, $CS_OPT)
|
||||
if ($CallResult -ne 'CS_ERR_OK') {
|
||||
$CallResult = [Capstone]::cs_close([ref]$DisAsmHandle)
|
||||
throw "cs_option error: $CallResult"
|
||||
}
|
||||
|
||||
[DllImport("$DllPath")]
|
||||
public static extern int cs_version(
|
||||
uint major,
|
||||
uint minor);
|
||||
}
|
||||
"@
|
||||
# Out Buffer Handle
|
||||
$InsnHandle = [System.IntPtr]::Zero
|
||||
|
||||
if ($Version){
|
||||
$VerCount = [System.BitConverter]::GetBytes($([Capstone]::cs_version($null,$null)))
|
||||
$Banner = @"
|
||||
# Disassemble bytes
|
||||
$Count = [Capstone]::cs_disasm($DisAsmHandle, $Bytes, $Bytes.Count, $Address, 0, [ref]$InsnHandle)
|
||||
|
||||
(((;
|
||||
(; "((((\
|
||||
;((((((; "((((;
|
||||
((((""\(((( "((((
|
||||
((((" ((\ "(((( "(((\
|
||||
;(((/ ((((((( "(((( \(((
|
||||
((((" (((* "(((( \(((;"(((\
|
||||
((((";((("/(( \(((;"(((\"(((\
|
||||
(((( (((( ((((" "(((\ ((() (((\
|
||||
;((("(((( (((* **"" ((()"(((;
|
||||
(((" ((( (((( ((((((((((((((:*(((
|
||||
(((( (((*)((( ********"""" ;;(((((;
|
||||
(((* ((( (((((((((((((((((((((*"" (
|
||||
((("(((( """***********"""" ;;(((((
|
||||
"" (((((((((((((((((((((((((((*""
|
||||
"""****(((((****"""
|
||||
if ($Count -gt 0) {
|
||||
# Result struct
|
||||
$cs_insn = if ($PSVersionTable.PSVersion.Major -gt 2) {
|
||||
[cs_insn]@{}
|
||||
} else {
|
||||
New-Object -TypeName cs_insn
|
||||
}
|
||||
|
||||
-=[Capstone Engine v$($VerCount[1]).$($VerCount[0])]=-
|
||||
$cs_insn_size = [System.Runtime.InteropServices.Marshal]::SizeOf($cs_insn)
|
||||
$cs_insn = $cs_insn.GetType()
|
||||
|
||||
"@
|
||||
# Mmm ASCII version banner!
|
||||
$Banner
|
||||
Return
|
||||
}
|
||||
|
||||
# Disasm Handle
|
||||
$DisAsmHandle = [IntPtr]::Zero
|
||||
|
||||
# Initialize Capstone with cs_open()
|
||||
$CallResult = [Capstone]::cs_open($Architecture,$Mode,[ref]$DisAsmHandle)
|
||||
if ($CallResult -ne "CS_ERR_OK") {
|
||||
if ($CallResult -eq "CS_ERR_MODE"){
|
||||
echo "`n[!] Invalid Architecture/Mode combination"
|
||||
echo "[>] Quitting..`n"
|
||||
} else {
|
||||
echo "`n[!] cs_open error: $CallResult"
|
||||
echo "[>] Quitting..`n"
|
||||
}
|
||||
Return
|
||||
}
|
||||
# Result detail struct
|
||||
$cs_detail = if ($PSVersionTable.PSVersion.Major -gt 2) {
|
||||
[cs_detail]@{}
|
||||
} else {
|
||||
New-Object -TypeName cs_detail
|
||||
}
|
||||
$cs_detail = $cs_detail.GetType()
|
||||
|
||||
# Set disassembly syntax
|
||||
#---
|
||||
# cs_opt_type -> CS_OPT_SYNTAX = 1
|
||||
#---
|
||||
# cs_opt_value -> CS_OPT_SYNTAX_INTEL = 1
|
||||
# -> CS_OPT_SYNTAX_ATT = 2
|
||||
if ($Syntax -eq "Intel") {
|
||||
$CS_OPT_SYNTAX = 1
|
||||
} else {
|
||||
$CS_OPT_SYNTAX = 2
|
||||
}
|
||||
$CallResult = [Capstone]::cs_option($DisAsmHandle, 1, $CS_OPT_SYNTAX)
|
||||
if ($CallResult -ne "CS_ERR_OK") {
|
||||
echo "`n[!] cs_option error: $CallResult"
|
||||
echo "[>] Quitting..`n"
|
||||
$CallResult = [Capstone]::cs_close([ref]$DisAsmHandle)
|
||||
Return
|
||||
}
|
||||
# Result buffer offset
|
||||
$BuffOffset = $InsnHandle.ToInt64()
|
||||
|
||||
# Set disassembly detail
|
||||
#---
|
||||
# cs_opt_type -> CS_OPT_DETAIL = 2
|
||||
#---
|
||||
# cs_opt_value -> CS_OPT_ON = 3
|
||||
# -> CS_OPT_OFF = 0
|
||||
if ($Detailed) {
|
||||
$CS_OPT = 3
|
||||
} else {
|
||||
$CS_OPT = 0
|
||||
}
|
||||
$CallResult = [Capstone]::cs_option($DisAsmHandle, 2, $CS_OPT)
|
||||
if ($CallResult -ne "CS_ERR_OK") {
|
||||
echo "`n[!] cs_option error: $CallResult"
|
||||
echo "[>] Quitting..`n"
|
||||
$CallResult = [Capstone]::cs_close([ref]$DisAsmHandle)
|
||||
Return
|
||||
}
|
||||
for ($i = 0 ; $i -lt $Count ; $i++) {
|
||||
# Cast Offset to cs_insn
|
||||
$Cast = [System.Runtime.InteropServices.Marshal]::PtrToStructure([System.Intptr]$BuffOffset, [type]$cs_insn)
|
||||
|
||||
# Out Buffer Handle
|
||||
$InsnHandle = [IntPtr]::Zero
|
||||
if ($CS_OPT -eq 0) {
|
||||
$Disassembly = @{
|
||||
Address = $Cast.address
|
||||
Instruction = '{0} {1}' -f $Cast.mnemonic, $Cast.operands
|
||||
}
|
||||
|
||||
# Disassemble bytes
|
||||
$Count = [Capstone]::cs_disasm($DisAsmHandle, $Bytes, $Bytes.Count, $Address, 0, [ref]$InsnHandle)
|
||||
|
||||
if ($Count -gt 0) {
|
||||
# Result Array
|
||||
$Disasm = @()
|
||||
if ($PSVersionTable.PSVersion.Major -gt 2) {
|
||||
# Add TypeName for PS formatting and output result
|
||||
$Disassembly.PSTypeName ='CapstoneDisassembly.Simple'
|
||||
[pscustomobject]$Disassembly
|
||||
} else {
|
||||
$Disassembly = New-Object -TypeName PSObject -Property $Disassembly
|
||||
# Add TypeName for PS formatting and output result
|
||||
$Disassembly.PSObject.TypeNames.Insert(0, 'CapstoneDisassembly.Simple')
|
||||
$Disassembly
|
||||
}
|
||||
} else {
|
||||
$DetailCast = [System.Runtime.InteropServices.Marshal]::PtrToStructure($Cast.detail, [type]$cs_detail)
|
||||
if ($DetailCast.regs_read_count -gt 0) {
|
||||
$RegRead = for ($r = 0 ; $r -lt $DetailCast.regs_read_count ; $r++) {
|
||||
$NamePointer = [Capstone]::cs_reg_name($DisAsmHandle, $DetailCast.regs_read[$r])
|
||||
[System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($NamePointer)
|
||||
}
|
||||
}
|
||||
|
||||
# Result struct
|
||||
$cs_insn = New-Object cs_insn
|
||||
$cs_insn_size = [System.Runtime.InteropServices.Marshal]::SizeOf($cs_insn)
|
||||
$cs_insn = $cs_insn.GetType()
|
||||
if ($DetailCast.regs_write_count -gt 0) {
|
||||
$RegWrite = for ($r = 0 ; $r -lt $DetailCast.regs_write_count ; $r++) {
|
||||
$NamePointer = [Capstone]::cs_reg_name($DisAsmHandle, $DetailCast.regs_write[$r])
|
||||
[System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($NamePointer)
|
||||
}
|
||||
}
|
||||
|
||||
# Result detail struct
|
||||
$cs_detail = New-Object cs_detail
|
||||
$cs_detail = $cs_detail.GetType()
|
||||
|
||||
# Result buffer offset
|
||||
$BuffOffset = $InsnHandle.ToInt64()
|
||||
|
||||
for ($i=0; $i -lt $Count; $i++) {
|
||||
# Cast Offset to cs_insn
|
||||
$InsnPointer = New-Object System.Intptr -ArgumentList $BuffOffset
|
||||
$Cast = [system.runtime.interopservices.marshal]::PtrToStructure($InsnPointer,[type]$cs_insn)
|
||||
|
||||
if ($CS_OPT -eq 0) {
|
||||
$HashTable = @{
|
||||
Address = echo "0x$("{0:X}" -f $Cast.address)"
|
||||
Instruction = echo "$($Cast.mnemonic) $($Cast.operands)"
|
||||
}
|
||||
$Object = New-Object PSObject -Property $HashTable
|
||||
$Disasm += $Object |Select-Object Address,Instruction
|
||||
} else {
|
||||
$DetailCast = [system.runtime.interopservices.marshal]::PtrToStructure($Cast.detail,[type]$cs_detail)
|
||||
if($DetailCast.regs_read_count -gt 0) {
|
||||
$RegRead = @()
|
||||
for ($r=0; $r -lt $DetailCast.regs_read_count; $r++) {
|
||||
$NamePointer = [Capstone]::cs_reg_name($DisAsmHandle, $DetailCast.regs_read[$r])
|
||||
$RegRead += [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($NamePointer)
|
||||
}
|
||||
}
|
||||
if ($DetailCast.regs_write_count -gt 0) {
|
||||
$RegWrite = @()
|
||||
for ($r=0; $r -lt $DetailCast.regs_write_count; $r++) {
|
||||
$NamePointer = [Capstone]::cs_reg_name($DisAsmHandle, $DetailCast.regs_write[$r])
|
||||
$RegWrite += [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi($NamePointer)
|
||||
}
|
||||
}
|
||||
$HashTable = @{
|
||||
Address = echo "0x$("{0:X}" -f $Cast.address)"
|
||||
Mnemonic = $Cast.mnemonic
|
||||
Operands = $Cast.operands
|
||||
Bytes = $Cast.bytes
|
||||
Size = $Cast.size
|
||||
RegRead = $RegRead
|
||||
RegWrite = $RegWrite
|
||||
}
|
||||
$Object = New-Object PSObject -Property $HashTable
|
||||
$Disasm += $Object |Select-Object Size,Address,Mnemonic,Operands,Bytes,RegRead,RegWrite
|
||||
}
|
||||
$BuffOffset = $BuffOffset + $cs_insn_size
|
||||
}
|
||||
} else {
|
||||
echo "`n[!] Disassembly Failed"
|
||||
echo "[>] Quitting..`n"
|
||||
$CallResult = [Capstone]::cs_close([ref]$DisAsmHandle)
|
||||
Return
|
||||
}
|
||||
|
||||
# Print result
|
||||
$Disasm
|
||||
|
||||
# Free Buffer Handle
|
||||
$CallResult = [Capstone]::cs_free($InsnHandle, $Count)
|
||||
}
|
||||
$Disassembly = @{
|
||||
Address = $Cast.address
|
||||
Mnemonic = $Cast.mnemonic
|
||||
Operands = $Cast.operands
|
||||
Bytes = $Cast.bytes[0..($Cast.size - 1)]
|
||||
Size = $Cast.size
|
||||
RegRead = $RegRead
|
||||
RegWrite = $RegWrite
|
||||
}
|
||||
|
||||
if ($PSVersionTable.PSVersion.Major -gt 2) {
|
||||
# Add TypeName for PS formatting and output result
|
||||
$Disassembly.PSTypeName = 'CapstoneDisassembly.Detailed'
|
||||
[pscustomobject]$Disassembly
|
||||
} else {
|
||||
$Disassembly = New-Object -TypeName PSObject -Property $Disassembly
|
||||
# Add TypeName for PS formatting and output result
|
||||
$Disassembly.PSObject.TypeNames.Insert(0, 'CapstoneDisassembly.Detailed')
|
||||
$Disassembly
|
||||
}
|
||||
}
|
||||
$BuffOffset = $BuffOffset + $cs_insn_size
|
||||
}
|
||||
} else {
|
||||
$CallResult = [Capstone]::cs_close([ref]$DisAsmHandle)
|
||||
throw 'Disassembly Failed'
|
||||
}
|
||||
|
||||
# Free Buffer Handle
|
||||
$CallResult = [Capstone]::cs_free($InsnHandle, $Count)
|
||||
}
|
||||
|
||||
#region Init
|
||||
|
||||
Initialize-Capstone -DllPath (
|
||||
Join-Path -Path $PSScriptRoot -ChildPath 'Lib\Capstone\capstone.dll'
|
||||
) -ErrorAction Stop
|
||||
|
||||
#endregion
|
Loading…
Reference in New Issue
Block a user