aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbitform <matt@exploit-monday.com>2012-06-26 20:09:55 -0400
committerbitform <matt@exploit-monday.com>2012-06-26 20:09:55 -0400
commit72c00d7422ea2df4fe397db099d67c6945d48724 (patch)
treeb1f15501a5df588a5f10badadaf4ae5553012bd8
parent65fde4aac016d766ee274383349bffe54bfa1aa1 (diff)
downloadPowerSploit-72c00d7422ea2df4fe397db099d67c6945d48724.tar.gz
PowerSploit-72c00d7422ea2df4fe397db099d67c6945d48724.zip
Added Get-ILDisassembly - an MSIL disassembler
Added Get-ILDisassembly. Added RE_Tools folder for all current and future reverse engineering tools.
-rw-r--r--README6
-rw-r--r--RE_Tools/Get-ILDisassembly.ps1196
2 files changed, 202 insertions, 0 deletions
diff --git a/README b/README
index 86a44ac..4942259 100644
--- a/README
+++ b/README
@@ -32,6 +32,12 @@ Invoke-ReverseDnsLookup:
An assortment of scripts used to parse/manipulate Windows portable executables
+----------
+.\RE_Tools
+----------
+
+Tools to aid in reverse engineering
+
-------
License
-------
diff --git a/RE_Tools/Get-ILDisassembly.ps1 b/RE_Tools/Get-ILDisassembly.ps1
new file mode 100644
index 0000000..6cb9db8
--- /dev/null
+++ b/RE_Tools/Get-ILDisassembly.ps1
@@ -0,0 +1,196 @@
+function Get-ILDisassembly
+{
+<#
+.Synopsis
+
+ PowerSploit Module - Get-ILDisassembly
+ Author: Matthew Graeber (@mattifestation)
+ License: BSD 3-Clause
+
+.Description
+
+ Get-ILDisassembly disassembles a raw MSIL byte array passed in from a MethodInfo object in a manner
+ similar to that of Ildasm.
+
+ The majority of this code was simply translated from C# (with permission) from a code example taken from:
+ "C# 4.0 in a Nutshell", Copyright 2010, Joseph Albahari and Ben Albahari, pg. 728-733
+
+.Parameter MethodInfo
+
+ A MethodInfo object that describes the implementation of the method and contains the IL for the method.
+
+.Example
+
+ PS> [Int].GetMethod('Parse', [String]) | Get-ILDisassembly | Format-Table Position, Instruction, Operand -AutoSize
+
+ Position Instruction Operand
+ -------- ----------- -------
+ IL_0000 ldarg.0
+ IL_0001 ldc.i4.7
+ IL_0002 call System.Globalization.NumberFormatInfo.get_CurrentInfo
+ IL_0007 call System.Number.ParseInt32
+ IL_000C ret
+
+ Description
+ -----------
+ Disassembles the System.Int32.Parse(String) method
+
+.Example
+
+ PS> $MethodInfo = [Array].GetMethod('BinarySearch', [Type[]]([Array], [Object]))
+ PS> Get-ILDisassembly $MethodInfo | Format-Table Position, Instruction, Operand -AutoSize
+
+ Position Instruction Operand
+ -------- ----------- -------
+ IL_0000 ldarg.0
+ IL_0001 brtrue.s IL_000E
+ IL_0003 ldstr 'array'
+ IL_0008 newobj System.ArgumentNullException..ctor
+ IL_000D throw
+ IL_000E ldarg.0
+ IL_000F ldc.i4.0
+ IL_0010 callvirt System.Array.GetLowerBound
+ IL_0015 stloc.0
+ IL_0016 ldarg.0
+ IL_0017 ldloc.0
+ IL_0018 ldarg.0
+ IL_0019 callvirt System.Array.get_Length
+ IL_001E ldarg.1
+ IL_001F ldnull
+ IL_0020 call System.Array.BinarySearch
+ IL_0025 ret
+
+ Description
+ -----------
+ Disassembles the System.Array.BinarySearch(Array, Object) method
+
+.Inputs
+ System.Reflection.MethodInfo. The method description containing the raw IL bytecodes.
+
+.Outputs
+ System.Object. Returns a custom object consisting of a position, instruction, and opcode parameter.
+
+.Link
+ My blog: http://www.exploit-monday.com
+ Original C# code: http://www.albahari.com/nutshell/cs4ch18.aspx
+ OpCodes Class: http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.aspx
+ ECMA-335 IL Standard: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-335.pdf
+#>
+
+Param ( [Parameter(Mandatory = $True, ValueFromPipeline = $True)] [System.Reflection.MethodInfo] $MethodInfo )
+
+ if (!($MethodInfo.GetMethodBody())) {
+ return
+ }
+
+ $IL = $MethodInfo.GetMethodBody().GetILAsByteArray()
+ $MethodModule = $MethodInfo.DeclaringType.Module
+
+ $OpCodeTable = @{}
+
+ # Fill OpCodeTable with every OpCode so that it can be referenced by numeric byte value
+ [System.Reflection.Emit.OpCodes].GetMembers() |
+ ForEach-Object {
+ try {
+ $OpCode = $_.GetValue($null)
+ $OpCodeTable[[Int16] $OpCode.Value] = $OpCode
+ } catch {}
+ }
+
+ $Position = 0
+
+ # Disassemble every instruction until the end of the IL bytecode array is reached
+ while ($Position -lt $IL.Length) {
+
+ # Get current instruction position
+ $InstructionPostion = "IL_{0}" -f ($Position.ToString('X4'))
+
+ if ($IL[$Position] -eq 0xFE) {
+ # You are dealing with a two-byte opcode in this case
+ $Op = $OpCodeTable[[Int16] ([BitConverter]::ToInt16($IL[($Position+1)..$Position], 0))]
+ $Position++
+ } else {
+ # Otherwise, it's a one-byte opcode
+ $Op = $OpCodeTable[[Int16] $IL[$Position]]
+ }
+
+ $Position++
+
+ $Type = $Op.OperandType
+ $Operand = $null
+
+ if ($Type -eq 'InlineNone') {
+ $OperandLength = 0
+ } elseif (($Type -eq 'ShortInlineBrTarget') -or ($Type -eq 'ShortInlineI') -or ($Type -eq 'ShortInlineVar')) {
+ $OperandLength = 1
+
+ if ($Type -eq 'ShortInlineBrTarget') { # Short relative jump instruction
+ # [SByte]::Parse was used because PowerShell doesn't handle signed bytes well
+ $Target = $Position + ([SByte]::Parse($IL[$Position].ToString('X2'), 'AllowHexSpecifier')) + 1
+ $Operand = "IL_{0}" -f ($Target.ToString('X4'))
+ }
+ } elseif ($Type -eq 'InlineVar') {
+ $OperandLength = 2
+ } elseif (($Type -eq 'InlineI8') -or (($Type -eq 'InlineR'))) {
+ $OperandLength = 8
+ } elseif ($Type -eq 'InlineSwitch') {
+ # This is the only operand type with a variable number of operands
+ $TargetCount = [BitConverter]::ToInt32($IL, $Position)
+ $OperandLength = 4 * ($TargetCount + 1)
+ $Targets = New-Object String[]($TargetCount)
+
+ foreach ($i in 0..($TargetCount - 1)) {
+ # Get all switch jump targets
+ $Target = [BitConverter]::ToInt32($IL, ($Position + ($i + 1) * 4))
+ $Targets[$i] = "IL_{0}" -f (($Position + $Target + $OperandLength).ToString('X4'))
+ }
+
+ $Operand = "({0})" -f ($Targets -join ',')
+ } else {
+ $OperandLength = 4
+ $Operand = $null
+
+ $OpInt = [BitConverter]::ToInt32($IL, $Position)
+
+ if (($Type -eq 'InlineTok') -or ($Type -eq 'InlineMethod') -or ($Type -eq 'InlineField') -or ($Type -eq 'InlineType')) {
+ # Resolve all operands with metadata tokens
+ Write-Verbose "OpCode Metadata for member: $OpInt"
+ try { $MemberInfo = $MethodModule.ResolveMember($OpInt) } catch { $Operand = $null }
+ if (!$MemberInfo) { $Operand = $null }
+
+ # Retrieve the actual name of the class and method
+ if ($MemberInfo.ReflectedType) {
+ $Operand = "{0}.{1}" -f ($MemberInfo.ReflectedType.Fullname), ($MemberInfo.Name)
+ } elseif ($MemberInfo -is [Type]) {
+ $Operand = $MemberInfo.GetType().FullName
+ } else {
+ $Operand = $MemberInfo.Name
+ }
+ } elseif ($Type -eq 'InlineString') {
+ # Retrieve the referenced string
+ $Operand = "`'{0}`'" -f ($MethodModule.ResolveString($OpInt))
+ } elseif ($Type -eq 'InlineBrTarget') {
+ $Operand = "IL_{0}" -f (($Position + $OpInt + 4).ToString('X4'))
+ } else {
+ $Operand = $null
+ }
+ }
+
+ if (($OperandLength -gt 0) -and ($OperandLength -ne 4) -and ($Type -ne 'InlineSwitch') -and ($Type -ne 'ShortInlineBrTarget')) {
+ # Simply print the hex for all operands with immediate values
+ $Operand = "0x{0}" -f (($IL[$Position..($Position+$OperandLength-1)] | ForEach-Object { $_.ToString('X2') }) -join '')
+ }
+
+ $Instruction = @{
+ Position = $InstructionPostion
+ Instruction = $Op.Name
+ Operand = $Operand
+ }
+
+ # Return a custom object containing a position, instruction, and fully-qualified operand
+ New-Object PSObject -Property $Instruction
+
+ # Adjust the position in the opcode array accordingly
+ $Position += $OperandLength
+ }
+} \ No newline at end of file