metasm 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/Gemfile +1 -0
- data/doc/code_organisation.txt +1 -1
- data/metasm.gemspec +1 -1
- data/metasm.rb +2 -1
- data/metasm/cpu/arc/decode.rb +3 -3
- data/metasm/cpu/arm/decode.rb +2 -2
- data/metasm/cpu/ia32/compile_c.rb +18 -2
- data/metasm/cpu/ia32/decode.rb +9 -4
- data/metasm/cpu/ia32/decompile.rb +22 -8
- data/metasm/cpu/ia32/opcodes.rb +5 -5
- data/metasm/cpu/mcs51.rb +8 -0
- data/metasm/cpu/mcs51/decode.rb +99 -0
- data/metasm/cpu/mcs51/main.rb +76 -0
- data/metasm/cpu/mcs51/opcodes.rb +120 -0
- data/metasm/cpu/mips/decode.rb +5 -4
- data/metasm/cpu/st20.rb +9 -0
- data/metasm/cpu/st20/decode.rb +180 -0
- data/metasm/cpu/st20/decompile.rb +283 -0
- data/metasm/cpu/st20/main.rb +37 -0
- data/metasm/cpu/st20/opcodes.rb +140 -0
- data/metasm/cpu/x86_64/encode.rb +4 -2
- data/metasm/cpu/x86_64/opcodes.rb +4 -2
- data/metasm/decode.rb +16 -15
- data/metasm/decompile.rb +1 -1
- data/metasm/disassemble.rb +3 -1
- data/metasm/disassemble_api.rb +3 -1
- data/metasm/dynldr.rb +9 -3
- data/metasm/encode.rb +2 -2
- data/metasm/exe_format/coff.rb +3 -1
- data/metasm/exe_format/coff_decode.rb +5 -3
- data/metasm/exe_format/elf.rb +4 -0
- data/metasm/exe_format/elf_decode.rb +1 -2
- data/metasm/exe_format/elf_encode.rb +4 -1
- data/metasm/exe_format/macho.rb +20 -6
- data/metasm/exe_format/pe.rb +1 -1
- data/metasm/exe_format/serialstruct.rb +1 -1
- data/metasm/gui.rb +1 -1
- data/metasm/gui/dasm_hex.rb +2 -2
- data/metasm/gui/dasm_main.rb +8 -8
- data/metasm/gui/debug.rb +4 -4
- data/metasm/gui/gtk.rb +1 -1
- data/metasm/gui/qt.rb +2 -2
- data/metasm/gui/win32.rb +1 -1
- data/metasm/main.rb +11 -6
- data/metasm/os/windows.rb +26 -23
- data/misc/hexdump.rb +2 -2
- data/misc/objdiff.rb +4 -1
- data/misc/objscan.rb +1 -1
- data/samples/dasm-plugins/bindiff.rb +1 -1
- data/samples/dasm-plugins/scanxrefs.rb +2 -1
- data/samples/dynamic_ruby.rb +24 -25
- data/samples/elfencode.rb +15 -0
- data/samples/exeencode.rb +2 -2
- data/samples/metasm-shell.rb +67 -55
- data/tests/mcs51.rb +27 -0
- metadata +13 -2
@@ -0,0 +1,37 @@
|
|
1
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
2
|
+
# Copyright (C) 2006-2009 Yoann GUILLOT
|
3
|
+
#
|
4
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
5
|
+
|
6
|
+
|
7
|
+
require 'metasm/main'
|
8
|
+
|
9
|
+
module Metasm
|
10
|
+
class ST20 < CPU
|
11
|
+
def initialize(size=32)
|
12
|
+
super()
|
13
|
+
@endianness = :little
|
14
|
+
@size = size
|
15
|
+
init_opcodes
|
16
|
+
end
|
17
|
+
|
18
|
+
def register_symbols
|
19
|
+
[:a, :b, :c]
|
20
|
+
end
|
21
|
+
|
22
|
+
def render_instruction(i)
|
23
|
+
r = []
|
24
|
+
r << i.opname
|
25
|
+
if not i.args.empty?
|
26
|
+
r << ' '
|
27
|
+
i.args.each { |a_| r << a_ << ', ' }
|
28
|
+
r.pop
|
29
|
+
end
|
30
|
+
r
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class TransPuter < ST20
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
2
|
+
# Copyright (C) 2006-2009 Yoann GUILLOT
|
3
|
+
#
|
4
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
5
|
+
|
6
|
+
require 'metasm/cpu/st20/main'
|
7
|
+
|
8
|
+
module Metasm
|
9
|
+
|
10
|
+
class ST20
|
11
|
+
def init_opcodes
|
12
|
+
@op_function = op_get_function
|
13
|
+
@op_operate = op_get_operate
|
14
|
+
@opcode_list = @op_function.sort.map { |b, n|
|
15
|
+
op = Opcode.new(n, b)
|
16
|
+
op.props[:setip] = true if n == 'cj'
|
17
|
+
op.props[:setip] = op.props[:stopexec] = true if n == 'j'
|
18
|
+
op.props[:setip] = op.props[:stopexec] = op.props[:saveip] = true if n == 'fcall'
|
19
|
+
op
|
20
|
+
}
|
21
|
+
@opc_operate = {}
|
22
|
+
op = Opcode.new('ret', 0)
|
23
|
+
op.props[:setip] = op.props[:stopexec] = true
|
24
|
+
@opc_operate['ret'] = op
|
25
|
+
end
|
26
|
+
|
27
|
+
def op_get_function
|
28
|
+
{
|
29
|
+
0x00 => 'j', 0x10 => 'ldlp', 0x20 => 'pfix', 0x30 => 'ldnl',
|
30
|
+
0x40 => 'ldc', 0x50 => 'ldnlp', 0x60 => 'nfix', 0x70 => 'ldl',
|
31
|
+
0x80 => 'adc', 0x90 => 'fcall', 0xa0 => 'cj', 0xb0 => 'ajw',
|
32
|
+
0xc0 => 'eqc', 0xd0 => 'stl', 0xe0 => 'stnl', 0xf0 => 'opr'
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def op_get_operate
|
37
|
+
{
|
38
|
+
0x00 => 'rev', 0x01 => 'dup', 0x02 => 'rot', 0x03 => 'arot',
|
39
|
+
0x04 => 'add', 0x05 => 'sub', 0x06 => 'mul', 0x07 => 'wsub',
|
40
|
+
0x08 => 'not', 0x09 => 'and', 0x0A => 'or', 0x0B => 'shl',
|
41
|
+
0x0C => 'shr', 0x0D => 'jab', 0x0E => 'timeslice', 0x0F => 'breakpoint',
|
42
|
+
0x10 => 'addc', 0x11 => 'subc', 0x12 => 'mac', 0x13 => 'umac',
|
43
|
+
0x14 => 'smul', 0x15 => 'smacinit', 0x16 => 'smacloop', 0x17 => 'biquad',
|
44
|
+
0x18 => 'divstep', 0x19 => 'unsign', 0x1A => 'saturate', 0x1B => 'gt',
|
45
|
+
0x1C => 'gtu', 0x1D => 'order', 0x1E => 'orderu', 0x1F => 'ashr',
|
46
|
+
0x20 => 'xor', 0x21 => 'xbword', 0x22 => 'xsword', 0x23 => 'bitld',
|
47
|
+
0x24 => 'bitst', 0x25 => 'bitmask', 0x26 => 'statusset', 0x27 => 'statusclr',
|
48
|
+
0x28 => 'statustst', 0x29 => 'rmw', 0x2A => 'lbinc', 0x2B => 'sbinc',
|
49
|
+
0x2C => 'lsinc', 0x2D => 'lsxinc', 0x2E => 'ssinc', 0x2F => 'lwinc',
|
50
|
+
0x30 => 'swinc', 0x31 => 'ecall', 0x32 => 'eret', 0x33 => 'run',
|
51
|
+
0x34 => 'stop', 0x35 => 'signal', 0x36 => 'wait', 0x37 => 'enqueue',
|
52
|
+
0x38 => 'dequeue', 0x39 => 'ldtdesc', 0x3A => 'ldpi', 0x3B => 'gajw',
|
53
|
+
0x3C => 'ldprodid', 0x3D => 'io', 0x3E => 'swap32', 0x3F => 'nop',
|
54
|
+
}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class TransPuter
|
59
|
+
def op_get_operate
|
60
|
+
{
|
61
|
+
0x00 => 'rev', 0x01 => 'lb', 0x02 => 'bsub', 0x03 => 'endp',
|
62
|
+
0x04 => 'diff', 0x05 => 'add', 0x06 => 'gcall', 0x07 => 'in',
|
63
|
+
0x08 => 'prod', 0x09 => 'gt', 0x0a => 'wsub', 0x0b => 'out',
|
64
|
+
0x0c => 'sub', 0x0d => 'startp', 0x0e => 'outbyte', 0x0f => 'outword',
|
65
|
+
0x10 => 'seterr', 0x11 => 'mreleasep', 0x12 => 'resetch', 0x13 => 'csub0',
|
66
|
+
0x14 => 'extvrfy', 0x15 => 'stopp', 0x16 => 'ladd', 0x17 => 'stlb',
|
67
|
+
0x18 => 'sthf', 0x19 => 'norm', 0x1a => 'ldiv', 0x1b => 'ldpi',
|
68
|
+
0x1c => 'stlf', 0x1d => 'xdble', 0x1e => 'ldpri', 0x1f => 'rem',
|
69
|
+
0x20 => 'ret', 0x21 => 'lend', 0x22 => 'ldtimer', 0x23 => 'testlds',
|
70
|
+
0x24 => 'testlde', 0x25 => 'testldd', 0x26 => 'teststs', 0x27 => 'testste',
|
71
|
+
0x28 => 'teststd', 0x29 => 'testerr', 0x2a => 'testpranal', 0x2b => 'tin',
|
72
|
+
0x2c => 'div', 0x2d => 'testhardchan', 0x2e => 'dist', 0x2f => 'disc',
|
73
|
+
0x30 => 'diss', 0x31 => 'lmul', 0x32 => 'not', 0x33 => 'xor',
|
74
|
+
0x34 => 'bcnt', 0x35 => 'lshr', 0x36 => 'lshl', 0x37 => 'lsum',
|
75
|
+
0x38 => 'lsub', 0x39 => 'runp', 0x3a => 'xword', 0x3b => 'sb',
|
76
|
+
0x3c => 'gajw', 0x3d => 'savel', 0x3e => 'saveh', 0x3f => 'wcnt',
|
77
|
+
0x40 => 'shr', 0x41 => 'shl', 0x42 => 'mint', 0x43 => 'alt',
|
78
|
+
0x44 => 'altwt', 0x45 => 'altend', 0x46 => 'and', 0x47 => 'enbt',
|
79
|
+
0x48 => 'enbc', 0x49 => 'enbs', 0x4a => 'move', 0x4b => 'or',
|
80
|
+
0x4c => 'csngl', 0x4d => 'ccnt1', 0x4e => 'talt', 0x4f => 'ldiff',
|
81
|
+
0x50 => 'sthb', 0x51 => 'taltwt', 0x52 => 'sum', 0x53 => 'mul',
|
82
|
+
0x54 => 'sttimer', 0x55 => 'stoperr', 0x56 => 'cword', 0x57 => 'clrhalterr',
|
83
|
+
0x58 => 'sethalterr', 0x59 => 'testhalterr', 0x5a => 'dup', 0x5b => 'move2dinit',
|
84
|
+
0x5c => 'move2dall', 0x5d => 'move2dnonzero', 0x5e => 'move2dzero', 0x5f => 'gtu',
|
85
|
+
0x60 => 'extin', 0x61 => 'extout', 0x62 => 'minn', 0x63 => 'unpacksn',
|
86
|
+
0x64 => 'moutn', 0x65 => 'xminn', 0x66 => 'extenbc', 0x67 => 'extndisc',
|
87
|
+
0x68 => 'extmin', 0x69 => 'extmout', 0x6a => 'extmin64', 0x6b => 'extmout64',
|
88
|
+
0x6c => 'postnormsn', 0x6d => 'roundsn', 0x6e => 'extminn', 0x6f => 'extmoutn',
|
89
|
+
0x70 => 'enbc3', 0x71 => 'ldinf', 0x72 => 'fmul', 0x73 => 'cflerr',
|
90
|
+
0x74 => 'crcword', 0x75 => 'crcbyte', 0x76 => 'bitcnt', 0x77 => 'bitrevword',
|
91
|
+
0x78 => 'bitrevnbits', 0x79 => 'pop', 0x7a => 'timerdisableh', 0x7b => 'timerdisablel',
|
92
|
+
0x7c => 'timerenableh', 0x7d => 'timerenablel', 0x7e => 'ldmemstartval',
|
93
|
+
0x80 => 'fpsttest', 0x81 => 'wsubdb', 0x82 => 'fpldnldbi', 0x83 => 'fpchkerr',
|
94
|
+
0x84 => 'fpstnldb', 0x85 => 'fpldtest', 0x86 => 'fpldnlsni', 0x87 => 'fpadd',
|
95
|
+
0x88 => 'fpstnlsn', 0x89 => 'fpsub', 0x8a => 'fpldnldb', 0x8b => 'fpmul',
|
96
|
+
0x8c => 'fpdiv', 0x8d => 'fprange', 0x8e => 'fpldnlsn', 0x8f => 'fpremfirst',
|
97
|
+
0x90 => 'fpremstep', 0x91 => 'fpnan', 0x92 => 'fpordered', 0x93 => 'fpnotfinite',
|
98
|
+
0x94 => 'fpgt', 0x95 => 'fpeq', 0x96 => 'fpi32tor32', 0x97 => 'fpge',
|
99
|
+
0x98 => 'fpi32tor64', 0x99 => 'enbt3', 0x9a => 'fpb32tor64', 0x9b => 'fplg',
|
100
|
+
0x9c => 'fptesterr', 0x9d => 'fprtoi32', 0x9e => 'fpstnli32', 0x9f => 'fpldzerosn',
|
101
|
+
0xa0 => 'fpldzerodb', 0xa1 => 'fpint', 0xa2 => 'getpri', 0xa3 => 'fpdup',
|
102
|
+
0xa4 => 'fprev', 0xa5 => 'setpri', 0xa6 => 'fpldnladddb', 0xa7 => 'fpentry3',
|
103
|
+
0xa8 => 'fpldnlmuldb', 0xa9 => 'fpentry2', 0xaa => 'fpldnladdsn', 0xab => 'fpentry',
|
104
|
+
0xac => 'fpldnlmulsn', 0xad => 'enbs3',
|
105
|
+
0xb0 => 'settimeslice', 0xb1 => 'break', 0xb2 => 'clrj0break', 0xb3 => 'setj0break',
|
106
|
+
0xb4 => 'testj0break', 0xb6 => 'ldflags', 0xb7 => 'stflags',
|
107
|
+
0xb8 => 'xbword', 0xb9 => 'lbx', 0xba => 'cb', 0xbb => 'cbu',
|
108
|
+
0xbc => 'insphdr', 0xbd => 'readbfr', 0xbe => 'ldconf', 0xbf => 'stconf',
|
109
|
+
0xc0 => 'ldcnt', 0xc1 => 'ssub', 0xc2 => 'ldth', 0xc3 => 'ldchstatus',
|
110
|
+
0xc4 => 'intdis', 0xc5 => 'intenb', 0xc6 => 'ldtrapped', 0xc7 => 'cir',
|
111
|
+
0xc8 => 'ss', 0xc9 => 'chantype', 0xca => 'ls', 0xcb => 'sttrapped',
|
112
|
+
0xcc => 'ciru', 0xcd => 'gintdis', 0xce => 'gintenb', 0xcf => 'fprem',
|
113
|
+
0xd0 => 'fprn', 0xd1 => 'fpdivby2', 0xd2 => 'fpmulby2', 0xd3 => 'fpsqrt',
|
114
|
+
0xd4 => 'fprp', 0xd5 => 'fprm', 0xd6 => 'fprz', 0xd7 => 'fpr32tor64',
|
115
|
+
0xd8 => 'fpr64tor32', 0xd9 => 'fpexpdec32', 0xda => 'fpexpinc32', 0xdb => 'fpabs',
|
116
|
+
0xdd => 'fpadddbsn', 0xde => 'fpchki32', 0xdf => 'fpchki64',
|
117
|
+
0xe0 => 'mnew', 0xe1 => 'mfree', 0xe2 => 'malloc', 0xe3 => 'mrelease',
|
118
|
+
0xe4 => 'min', 0xe5 => 'mout', 0xe6 => 'min64', 0xe7 => 'mout64',
|
119
|
+
0xe8 => 'xable', 0xe9 => 'xin', 0xea => 'xmin', 0xeb => 'xmin64',
|
120
|
+
0xec => 'xend', 0xed => 'ndisc', 0xee => 'ndist', 0xef => 'ndiss',
|
121
|
+
0xf0 => 'devlb', 0xf1 => 'devsb', 0xf2 => 'devls', 0xf3 => 'devss',
|
122
|
+
0xf4 => 'devlw', 0xf5 => 'devsw', 0xf8 => 'xsword', 0xf9 => 'lsx',
|
123
|
+
0xfa => 'cs', 0xfb => 'csu', 0xfc => 'trap', 0xfd => 'null',
|
124
|
+
0x1ff => 'start',
|
125
|
+
0x17c => 'lddevid',
|
126
|
+
0x200 => 'in8', 0x201 => 'in32', 0x202 => 'out8', 0x203 => 'out32',
|
127
|
+
0x204 => 'xstl',
|
128
|
+
0x22f => 'proc_alloc',
|
129
|
+
0x230 => 'proc_param', 0x231 => 'proc_mt_copy', 0x232 => 'proc_mt_move', 0x233 => 'proc_start',
|
130
|
+
0x234 => 'proc_end', 0x235 => 'getaff', 0x236 => 'setaff', 0x237 => 'getpas',
|
131
|
+
0x238 => 'mt_alloc', 0x239 => 'mt_release', 0x23a => 'mt_clone', 0x23b => 'mt_in',
|
132
|
+
0x23c => 'mt_out', 0x23d => 'mt_xchg', 0x23e => 'mt_lock', 0x23f => 'mt_unlock',
|
133
|
+
0x240 => 'mt_enroll', 0x241 => 'mt_resign', 0x242 => 'mt_sync', 0x243 => 'mt_xin',
|
134
|
+
0x244 => 'mt_xout', 0x245 => 'mt_xxchg', 0x246 => 'mt_dclone', 0x247 => 'mt_bind',
|
135
|
+
0x248 => 'mb', 0x249 => 'rmb', 0x24a => 'wmb', 0x24b => 'ext_mt_in',
|
136
|
+
0x24c => 'ext_mt_out', 0x24d => 'mt_resize',
|
137
|
+
}
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
data/metasm/cpu/x86_64/encode.rb
CHANGED
@@ -76,20 +76,22 @@ class X86_64
|
|
76
76
|
|
77
77
|
imm ||= 0 if @b.val_enc == 5
|
78
78
|
if imm
|
79
|
+
i32 = :i32
|
80
|
+
i32 = :a32 if (self.b and self.b.sz == 32) or (self.i and self.i.sz == 32)
|
79
81
|
case Expression.in_range?(imm, :i8)
|
80
82
|
when true
|
81
83
|
or_bits[1<<6]
|
82
84
|
[ret << Expression.encode_imm(imm, :i8, endianness)]
|
83
85
|
when false
|
84
86
|
or_bits[2<<6]
|
85
|
-
[ret << Expression.encode_imm(imm,
|
87
|
+
[ret << Expression.encode_imm(imm, i32, endianness)]
|
86
88
|
when nil
|
87
89
|
rets = ret.dup
|
88
90
|
or_bits[1<<6]
|
89
91
|
ret << @imm.encode(:i8, endianness)
|
90
92
|
rets, ret = ret, rets # or_bits[] modifies ret directly
|
91
93
|
or_bits[2<<6]
|
92
|
-
ret << @imm.encode(
|
94
|
+
ret << @imm.encode(i32, endianness)
|
93
95
|
[ret, rets]
|
94
96
|
end
|
95
97
|
else
|
@@ -46,8 +46,8 @@ class X86_64
|
|
46
46
|
o.args.include?(:seg2A) or
|
47
47
|
o.args.include?(:farptr) or
|
48
48
|
%w[aaa aad aam aas bound daa das into jcxz jecxz
|
49
|
-
lds les loadall arpl pusha pushad popa
|
50
|
-
|
49
|
+
lds les loadall arpl pusha pushad popa popad pushfd popfd
|
50
|
+
].include?(o.name.split('.')[0])
|
51
51
|
# split needed for lds.a32
|
52
52
|
}
|
53
53
|
|
@@ -57,6 +57,8 @@ class X86_64
|
|
57
57
|
|
58
58
|
addop('cmpxchg16b', [0x0F, 0xC7], 1) { |o| o.props[:opsz] = 64 ; o.props[:argsz] = 128 }
|
59
59
|
addop('iretq', [0xCF], nil, :stopexec, :setip) { |o| o.props[:opsz] = 64 } ; opcode_list.unshift opcode_list.pop
|
60
|
+
addop('pushfq', [0x9C]) { |o| o.props[:auto64] = true }
|
61
|
+
addop('popfq', [0x9D]) { |o| o.props[:auto64] = true }
|
60
62
|
addop 'swapgs', [0x0F, 0x01, 0xF8]
|
61
63
|
|
62
64
|
addop('movq', [0x0F, 0x6E], :mrmmmx, {:d => [1, 4]}) { |o| o.args = [:regmmx, :modrm] ; o.props[:opsz] = o.props[:argsz] = 64 }
|
data/metasm/decode.rb
CHANGED
@@ -63,24 +63,25 @@ class Indirection < ExpressionType
|
|
63
63
|
@target.externals
|
64
64
|
end
|
65
65
|
|
66
|
-
def match_rec(
|
67
|
-
return false if not
|
68
|
-
|
69
|
-
if vars[
|
70
|
-
return false if @target != vars[
|
71
|
-
elsif vars.has_key?
|
72
|
-
vars[
|
73
|
-
elsif
|
74
|
-
return false if not @target.match_rec(
|
66
|
+
def match_rec(pattern, vars)
|
67
|
+
return false if not pattern.kind_of? Indirection
|
68
|
+
pt = pattern.target
|
69
|
+
if vars[pt]
|
70
|
+
return false if @target != vars[pt]
|
71
|
+
elsif vars.has_key? pt
|
72
|
+
vars[pt] = @target
|
73
|
+
elsif pt.kind_of? ExpressionType
|
74
|
+
return false if not @target.match_rec(pt, vars)
|
75
75
|
else
|
76
|
-
return false if
|
76
|
+
return false if pt != @target
|
77
77
|
end
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
78
|
+
pl = pattern.len
|
79
|
+
if vars[pl]
|
80
|
+
return false if @len != vars[pl]
|
81
|
+
elsif vars.has_key? pl
|
82
|
+
vars[pl] = @len
|
82
83
|
else
|
83
|
-
return false if
|
84
|
+
return false if pl != @len
|
84
85
|
end
|
85
86
|
vars
|
86
87
|
end
|
data/metasm/decompile.rb
CHANGED
@@ -181,7 +181,7 @@ class Decompiler
|
|
181
181
|
addr = @dasm.normalize(addr)
|
182
182
|
|
183
183
|
# (almost) NULL ptr
|
184
|
-
return if addr.kind_of?
|
184
|
+
return if addr.kind_of? Integer and addr >= 0 and addr < 32
|
185
185
|
|
186
186
|
# check preceding structure we're hitting
|
187
187
|
# TODO check what we step over when defining a new static struct
|
data/metasm/disassemble.rb
CHANGED
@@ -26,6 +26,8 @@ class DecodedInstruction
|
|
26
26
|
attr_accessor :backtrace_binding
|
27
27
|
# used during fixed-size instruction decoding to hold the decoded raw opcode
|
28
28
|
attr_accessor :raw_data
|
29
|
+
# arbitrary data used during decoding, architecture-specific
|
30
|
+
attr_accessor :misc
|
29
31
|
|
30
32
|
# create a new DecodedInstruction with an Instruction whose cpu is the argument
|
31
33
|
# can take an existing Instruction as argument
|
@@ -544,7 +546,6 @@ class Disassembler
|
|
544
546
|
def normalize(addr)
|
545
547
|
return addr if not addr or addr == :default
|
546
548
|
addr = Expression[addr].bind(@old_prog_binding).reduce if not addr.kind_of? Integer
|
547
|
-
addr %= 1 << [@cpu.size, 32].max if @cpu and addr.kind_of? Integer
|
548
549
|
addr
|
549
550
|
end
|
550
551
|
|
@@ -1571,6 +1572,7 @@ puts " backtrace end #{ev} #{expr}" if debug_backtrace
|
|
1571
1572
|
oldexpr = t[0][0]
|
1572
1573
|
next false if expr == oldexpr # unmodifying loop
|
1573
1574
|
puts " bt loop at #{Expression[t[0][1]]}: #{oldexpr} => #{expr} (#{t.map { |z| Expression[z[1]] }.join(' <- ')})" if debug_backtrace
|
1575
|
+
bt_log << [:loop, expr, oldexpr, t.map { |z| z[1] }] if bt_log
|
1574
1576
|
false
|
1575
1577
|
when :up
|
1576
1578
|
next false if only_upto and h[:to] != only_upto
|
data/metasm/disassemble_api.rb
CHANGED
@@ -665,6 +665,8 @@ class Disassembler
|
|
665
665
|
b1.to_indirect.to_a == [] and b2.from_indirect.to_a == []
|
666
666
|
b2.list.each { |di| b1.add_di di }
|
667
667
|
b1.to_normal = b2.to_normal
|
668
|
+
b1.to_subfuncret = b2.to_subfuncret
|
669
|
+
b1.to_indirect = b2.to_indirect
|
668
670
|
b2.list.clear
|
669
671
|
@addrs_done.delete_if { |ad| normalize(ad[0]) == b2.address }
|
670
672
|
true
|
@@ -1042,7 +1044,7 @@ class Disassembler
|
|
1042
1044
|
fd.puts "decoded #{t.length}", t
|
1043
1045
|
|
1044
1046
|
t = @comment.map { |a, c|
|
1045
|
-
c.map { |l| l.chomp }.join("\n").split("\n").map { |lc| "#{Expression[a]} #{lc.chomp}" }
|
1047
|
+
c.to_a.map { |l| l.chomp }.join("\n").split("\n").map { |lc| "#{Expression[a]} #{lc.chomp}" }
|
1046
1048
|
}.join("\n")
|
1047
1049
|
fd.puts "comment #{t.length}", t
|
1048
1050
|
|
data/metasm/dynldr.rb
CHANGED
@@ -85,7 +85,13 @@ extern VALUE *rb_eArgError __attribute__((import));
|
|
85
85
|
#define ARY_LEN(o) (RArray(o)->len)
|
86
86
|
#endif
|
87
87
|
|
88
|
-
#
|
88
|
+
#if #{nil.object_id == 4 ? 1 : 0}
|
89
|
+
// ruby1.8
|
90
|
+
#define TYPE(x) (((VALUE)(x) & 1) ? T_FIXNUM : (((VALUE)(x) < 0x07) || (((VALUE)(x) & 0xf) == 0xe)) ? 0x40 : RString(x)->flags & T_MASK)
|
91
|
+
#else
|
92
|
+
// ruby2.0+, USE_FLONUM, world is hell
|
93
|
+
#define TYPE(x) (((VALUE)(x) & 1) ? T_FIXNUM : (((VALUE)(x) < 0x3f) || (((VALUE)(x) & 0xf) == 0xc) || (((VALUE)(x) & 3) == 2)) ? 0x40 : RString(x)->flags & T_MASK)
|
94
|
+
#endif
|
89
95
|
|
90
96
|
VALUE rb_uint2inum(VALUE);
|
91
97
|
VALUE rb_ull2inum(unsigned long long);
|
@@ -604,7 +610,7 @@ EOS
|
|
604
610
|
|
605
611
|
binmodule = find_bin_path
|
606
612
|
|
607
|
-
if not File.
|
613
|
+
if not File.exist?(binmodule) or File.stat(binmodule).mtime < File.stat(__FILE__).mtime
|
608
614
|
compile_binary_module(host_exe, host_cpu, binmodule)
|
609
615
|
end
|
610
616
|
|
@@ -727,7 +733,7 @@ EOS
|
|
727
733
|
fname = ['dynldr', host_arch, host_cpu.shortname, RUBY_VERSION.gsub('.', '')].join('-') + '.so'
|
728
734
|
dir = File.dirname(__FILE__)
|
729
735
|
binmodule = File.join(dir, fname)
|
730
|
-
if not File.
|
736
|
+
if not File.exist? binmodule or File.stat(binmodule).mtime < File.stat(__FILE__).mtime
|
731
737
|
if not dir = find_write_dir
|
732
738
|
raise LoadError, "no writable dir to put the DynLdr ruby module, try to run as root"
|
733
739
|
end
|
data/metasm/encode.rb
CHANGED
@@ -42,7 +42,7 @@ class ExeFormat
|
|
42
42
|
edata
|
43
43
|
end
|
44
44
|
|
45
|
-
#
|
45
|
+
# choose among multiple possible sub-EncodedData
|
46
46
|
# assumes all ambiguous edata have the equivallent relocations in the same order
|
47
47
|
def assemble_resolve(ary)
|
48
48
|
startlabel = new_label('section_start')
|
@@ -167,7 +167,7 @@ class ExeFormat
|
|
167
167
|
# for linear expressions of internal variables (ie differences of labels from the ary):
|
168
168
|
# - calc target numeric bounds, and reject relocs not accepting worst case value
|
169
169
|
# - else reject all but largest place available
|
170
|
-
# then
|
170
|
+
# then choose the shortest overall EData left
|
171
171
|
ary.map! { |elem|
|
172
172
|
case elem
|
173
173
|
when Array
|
data/metasm/exe_format/coff.rb
CHANGED
@@ -46,9 +46,11 @@ class COFF < ExeFormat
|
|
46
46
|
}
|
47
47
|
|
48
48
|
DLL_CHARACTERISTIC_BITS = {
|
49
|
+
0x20 => 'HIGH_ENTROPY_VA',
|
49
50
|
0x40 => 'DYNAMIC_BASE', 0x80 => 'FORCE_INTEGRITY', 0x100 => 'NX_COMPAT',
|
50
51
|
0x200 => 'NO_ISOLATION', 0x400 => 'NO_SEH', 0x800 => 'NO_BIND',
|
51
|
-
|
52
|
+
0x1000 => 'APPCONTAINER', 0x2000 => 'WDM_DRIVER',
|
53
|
+
0x4000 => 'GUARD_CF', 0x8000 => 'TERMINAL_SERVER_AWARE'
|
52
54
|
}
|
53
55
|
|
54
56
|
BASE_RELOCATION_TYPE = { 0 => 'ABSOLUTE', 1 => 'HIGH', 2 => 'LOW', 3 => 'HIGHLOW',
|
@@ -66,7 +66,7 @@ class COFF
|
|
66
66
|
class RelocObj
|
67
67
|
def decode(coff)
|
68
68
|
super(coff)
|
69
|
-
@sym = coff.symbols[@symidx]
|
69
|
+
@sym = coff.symbols[@symidx] if coff.symbols
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
@@ -89,7 +89,7 @@ class COFF
|
|
89
89
|
addr = addrs[i]
|
90
90
|
if addr >= coff.directory['export_table'][0] and addr < coff.directory['export_table'][0] + coff.directory['export_table'][1] and coff.sect_at_rva(addr)
|
91
91
|
name = coff.decode_strz
|
92
|
-
e.forwarder_lib, name = name.split('.', 2)
|
92
|
+
e.forwarder_lib, name = name.split('.', 2) if name.index('.')
|
93
93
|
if name[0] == ?#
|
94
94
|
e.forwarder_ordinal = name[1..-1].to_i
|
95
95
|
else
|
@@ -111,6 +111,7 @@ class COFF
|
|
111
111
|
end
|
112
112
|
if namep and ords
|
113
113
|
namep.zip(ords).each { |np, oi|
|
114
|
+
next if not @exports[oi]
|
114
115
|
@exports[oi].name_p = np
|
115
116
|
if coff.sect_at_rva(np)
|
116
117
|
@exports[oi].name = coff.decode_strz
|
@@ -429,7 +430,7 @@ class COFF
|
|
429
430
|
# may return self when rva points to the coff header
|
430
431
|
# returns nil if none match, 0 never matches
|
431
432
|
def sect_at_rva(rva)
|
432
|
-
return if not rva or rva <= 0
|
433
|
+
return if not rva or not rva.kind_of?(::Integer) or rva <= 0
|
433
434
|
if sections and not @sections.empty?
|
434
435
|
if s = @sections.find { |s_| s_.virtaddr <= rva and s_.virtaddr + EncodedData.align_size((s_.virtsize == 0 ? s_.rawsize : s_.virtsize), @optheader.sect_align) > rva }
|
435
436
|
s.encoded.ptr = rva - s.virtaddr
|
@@ -551,6 +552,7 @@ class COFF
|
|
551
552
|
s.relocnr.times { s.relocs << RelocObj.decode(self) }
|
552
553
|
new_label 'pcrel'
|
553
554
|
s.relocs.each { |r|
|
555
|
+
next if not r.sym
|
554
556
|
case r.type
|
555
557
|
when 'DIR32'
|
556
558
|
s.encoded.reloc[r.va] = Metasm::Relocation.new(Expression[r.sym.name], :u32, @endianness)
|
data/metasm/exe_format/elf.rb
CHANGED
@@ -9,6 +9,7 @@ require 'metasm/exe_format/main'
|
|
9
9
|
module Metasm
|
10
10
|
class ELF < ExeFormat
|
11
11
|
MAGIC = "\x7fELF" # 0x7f454c46
|
12
|
+
MAGIC.force_encoding('BINARY') if MAGIC.respond_to?(:force_encoding)
|
12
13
|
CLASS = { 0 => 'NONE', 1 => '32', 2 => '64', 200 => '64_icc' }
|
13
14
|
DATA = { 0 => 'NONE', 1 => 'LSB', 2 => 'MSB' }
|
14
15
|
VERSION = { 0 => 'INVALID', 1 => 'CURRENT' }
|
@@ -395,6 +396,8 @@ class ELF < ExeFormat
|
|
395
396
|
|
396
397
|
DEFAULT_INTERP = '/lib/ld-linux.so.2'
|
397
398
|
DEFAULT_INTERP64 = '/lib64/ld-linux-x86-64.so.2'
|
399
|
+
DEFAULT_INTERP.force_encoding('BINARY') if DEFAULT_INTERP.respond_to?(:force_encoding)
|
400
|
+
DEFAULT_INTERP64.force_encoding('BINARY') if DEFAULT_INTERP64.respond_to?(:force_encoding)
|
398
401
|
|
399
402
|
class SerialStruct < Metasm::SerialStruct
|
400
403
|
new_int_field :addr, :off, :xword, :sword, :sxword
|
@@ -682,6 +685,7 @@ end
|
|
682
685
|
|
683
686
|
class FatELF < ExeFormat
|
684
687
|
MAGIC = "\xfa\x70\x0e\x1f" # 0xfat..elf
|
688
|
+
MAGIC.force_encoding('BINARY') if MAGIC.respond_to?(:force_encoding)
|
685
689
|
|
686
690
|
class SerialStruct < Metasm::SerialStruct
|
687
691
|
new_int_field :qword
|