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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/Gemfile +1 -0
  4. data/doc/code_organisation.txt +1 -1
  5. data/metasm.gemspec +1 -1
  6. data/metasm.rb +2 -1
  7. data/metasm/cpu/arc/decode.rb +3 -3
  8. data/metasm/cpu/arm/decode.rb +2 -2
  9. data/metasm/cpu/ia32/compile_c.rb +18 -2
  10. data/metasm/cpu/ia32/decode.rb +9 -4
  11. data/metasm/cpu/ia32/decompile.rb +22 -8
  12. data/metasm/cpu/ia32/opcodes.rb +5 -5
  13. data/metasm/cpu/mcs51.rb +8 -0
  14. data/metasm/cpu/mcs51/decode.rb +99 -0
  15. data/metasm/cpu/mcs51/main.rb +76 -0
  16. data/metasm/cpu/mcs51/opcodes.rb +120 -0
  17. data/metasm/cpu/mips/decode.rb +5 -4
  18. data/metasm/cpu/st20.rb +9 -0
  19. data/metasm/cpu/st20/decode.rb +180 -0
  20. data/metasm/cpu/st20/decompile.rb +283 -0
  21. data/metasm/cpu/st20/main.rb +37 -0
  22. data/metasm/cpu/st20/opcodes.rb +140 -0
  23. data/metasm/cpu/x86_64/encode.rb +4 -2
  24. data/metasm/cpu/x86_64/opcodes.rb +4 -2
  25. data/metasm/decode.rb +16 -15
  26. data/metasm/decompile.rb +1 -1
  27. data/metasm/disassemble.rb +3 -1
  28. data/metasm/disassemble_api.rb +3 -1
  29. data/metasm/dynldr.rb +9 -3
  30. data/metasm/encode.rb +2 -2
  31. data/metasm/exe_format/coff.rb +3 -1
  32. data/metasm/exe_format/coff_decode.rb +5 -3
  33. data/metasm/exe_format/elf.rb +4 -0
  34. data/metasm/exe_format/elf_decode.rb +1 -2
  35. data/metasm/exe_format/elf_encode.rb +4 -1
  36. data/metasm/exe_format/macho.rb +20 -6
  37. data/metasm/exe_format/pe.rb +1 -1
  38. data/metasm/exe_format/serialstruct.rb +1 -1
  39. data/metasm/gui.rb +1 -1
  40. data/metasm/gui/dasm_hex.rb +2 -2
  41. data/metasm/gui/dasm_main.rb +8 -8
  42. data/metasm/gui/debug.rb +4 -4
  43. data/metasm/gui/gtk.rb +1 -1
  44. data/metasm/gui/qt.rb +2 -2
  45. data/metasm/gui/win32.rb +1 -1
  46. data/metasm/main.rb +11 -6
  47. data/metasm/os/windows.rb +26 -23
  48. data/misc/hexdump.rb +2 -2
  49. data/misc/objdiff.rb +4 -1
  50. data/misc/objscan.rb +1 -1
  51. data/samples/dasm-plugins/bindiff.rb +1 -1
  52. data/samples/dasm-plugins/scanxrefs.rb +2 -1
  53. data/samples/dynamic_ruby.rb +24 -25
  54. data/samples/elfencode.rb +15 -0
  55. data/samples/exeencode.rb +2 -2
  56. data/samples/metasm-shell.rb +67 -55
  57. data/tests/mcs51.rb +27 -0
  58. 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
@@ -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, :a32, endianness)]
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(:a32, endianness)
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
- popad].include?(o.name.split('.')[0])
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 }
@@ -63,24 +63,25 @@ class Indirection < ExpressionType
63
63
  @target.externals
64
64
  end
65
65
 
66
- def match_rec(target, vars)
67
- return false if not target.kind_of? Indirection
68
- t = target.target
69
- if vars[t]
70
- return false if @target != vars[t]
71
- elsif vars.has_key? t
72
- vars[t] = @target
73
- elsif t.kind_of? ExpressionType
74
- return false if not @target.match_rec(t, vars)
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 targ != @target
76
+ return false if pt != @target
77
77
  end
78
- if vars[target.len]
79
- return false if @len != vars[target.len]
80
- elsif vars.has_key? target.len
81
- vars[target.len] = @len
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 target.len != @len
84
+ return false if pl != @len
84
85
  end
85
86
  vars
86
87
  end
@@ -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? Fixnum and addr >= 0 and addr < 32
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
@@ -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
@@ -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
 
@@ -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
- #define TYPE(x) (((VALUE)(x) & 1) ? T_FIXNUM : (((VALUE)(x) & 3) || ((VALUE)(x) < 7)) ? 0x40 : RString(x)->flags & T_MASK)
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.exists?(binmodule) or File.stat(binmodule).mtime < File.stat(__FILE__).mtime
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.exists? binmodule or File.stat(binmodule).mtime < File.stat(__FILE__).mtime
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
@@ -42,7 +42,7 @@ class ExeFormat
42
42
  edata
43
43
  end
44
44
 
45
- # chose among multiple possible sub-EncodedData
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 chose the shortest overall EData left
170
+ # then choose the shortest overall EData left
171
171
  ary.map! { |elem|
172
172
  case elem
173
173
  when Array
@@ -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
- 0x2000 => 'WDM_DRIVER', 0x8000 => 'TERMINAL_SERVER_AWARE'
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)
@@ -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