metasm 1.0.1 → 1.0.2
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 +7 -0
- data/.gitignore +1 -0
- data/.hgtags +3 -0
- data/Gemfile +1 -0
- data/INSTALL +61 -0
- data/LICENCE +458 -0
- data/README +29 -21
- data/Rakefile +10 -0
- data/TODO +10 -12
- data/doc/code_organisation.txt +2 -0
- data/doc/core/DynLdr.txt +247 -0
- data/doc/core/ExeFormat.txt +43 -0
- data/doc/core/Expression.txt +220 -0
- data/doc/core/GNUExports.txt +27 -0
- data/doc/core/Ia32.txt +236 -0
- data/doc/core/SerialStruct.txt +108 -0
- data/doc/core/VirtualString.txt +145 -0
- data/doc/core/WindowsExports.txt +61 -0
- data/doc/core/index.txt +1 -0
- data/doc/style.css +6 -3
- data/doc/usage/debugger.txt +327 -0
- data/doc/usage/index.txt +1 -0
- data/doc/use_cases.txt +2 -2
- data/metasm.gemspec +22 -0
- data/{lib/metasm.rb → metasm.rb} +11 -3
- data/{lib/metasm → metasm}/compile_c.rb +13 -7
- data/metasm/cpu/arc.rb +8 -0
- data/metasm/cpu/arc/decode.rb +425 -0
- data/metasm/cpu/arc/main.rb +191 -0
- data/metasm/cpu/arc/opcodes.rb +588 -0
- data/{lib/metasm → metasm/cpu}/arm.rb +7 -5
- data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
- data/{lib/metasm → metasm/cpu}/arm/decode.rb +13 -12
- data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
- data/{lib/metasm → metasm/cpu}/arm/main.rb +0 -3
- data/metasm/cpu/arm/opcodes.rb +324 -0
- data/{lib/metasm → metasm/cpu}/arm/parse.rb +25 -13
- data/{lib/metasm → metasm/cpu}/arm/render.rb +2 -2
- data/metasm/cpu/arm64.rb +15 -0
- data/metasm/cpu/arm64/debug.rb +38 -0
- data/metasm/cpu/arm64/decode.rb +289 -0
- data/metasm/cpu/arm64/encode.rb +41 -0
- data/metasm/cpu/arm64/main.rb +105 -0
- data/metasm/cpu/arm64/opcodes.rb +232 -0
- data/metasm/cpu/arm64/parse.rb +20 -0
- data/metasm/cpu/arm64/render.rb +95 -0
- data/{lib/metasm/ppc.rb → metasm/cpu/bpf.rb} +2 -4
- data/metasm/cpu/bpf/decode.rb +142 -0
- data/metasm/cpu/bpf/main.rb +60 -0
- data/metasm/cpu/bpf/opcodes.rb +81 -0
- data/metasm/cpu/bpf/render.rb +41 -0
- data/metasm/cpu/cy16.rb +9 -0
- data/metasm/cpu/cy16/decode.rb +253 -0
- data/metasm/cpu/cy16/main.rb +63 -0
- data/metasm/cpu/cy16/opcodes.rb +78 -0
- data/metasm/cpu/cy16/render.rb +41 -0
- data/metasm/cpu/dalvik.rb +11 -0
- data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +35 -13
- data/{lib/metasm → metasm/cpu}/dalvik/main.rb +51 -2
- data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +19 -11
- data/metasm/cpu/ia32.rb +17 -0
- data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +5 -7
- data/{lib/metasm → metasm/cpu}/ia32/debug.rb +5 -5
- data/{lib/metasm → metasm/cpu}/ia32/decode.rb +246 -59
- data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +7 -7
- data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
- data/{lib/metasm → metasm/cpu}/ia32/main.rb +51 -8
- data/metasm/cpu/ia32/opcodes.rb +1424 -0
- data/{lib/metasm → metasm/cpu}/ia32/parse.rb +47 -16
- data/{lib/metasm → metasm/cpu}/ia32/render.rb +31 -4
- data/metasm/cpu/mips.rb +14 -0
- data/{lib/metasm → metasm/cpu}/mips/compile_c.rb +1 -1
- data/metasm/cpu/mips/debug.rb +42 -0
- data/{lib/metasm → metasm/cpu}/mips/decode.rb +46 -16
- data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
- data/{lib/metasm → metasm/cpu}/mips/main.rb +11 -4
- data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +86 -17
- data/{lib/metasm → metasm/cpu}/mips/parse.rb +1 -1
- data/{lib/metasm → metasm/cpu}/mips/render.rb +1 -1
- data/{lib/metasm/dalvik.rb → metasm/cpu/msp430.rb} +1 -1
- data/metasm/cpu/msp430/decode.rb +247 -0
- data/metasm/cpu/msp430/main.rb +62 -0
- data/metasm/cpu/msp430/opcodes.rb +101 -0
- data/{lib/metasm → metasm/cpu}/pic16c/decode.rb +6 -7
- data/{lib/metasm → metasm/cpu}/pic16c/main.rb +0 -0
- data/{lib/metasm → metasm/cpu}/pic16c/opcodes.rb +1 -1
- data/{lib/metasm/mips.rb → metasm/cpu/ppc.rb} +4 -4
- data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -12
- data/{lib/metasm → metasm/cpu}/ppc/decompile.rb +3 -3
- data/{lib/metasm → metasm/cpu}/ppc/encode.rb +2 -2
- data/{lib/metasm → metasm/cpu}/ppc/main.rb +17 -12
- data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -5
- data/metasm/cpu/ppc/parse.rb +55 -0
- data/metasm/cpu/python.rb +8 -0
- data/metasm/cpu/python/decode.rb +136 -0
- data/metasm/cpu/python/main.rb +36 -0
- data/metasm/cpu/python/opcodes.rb +180 -0
- data/{lib/metasm → metasm/cpu}/sh4.rb +1 -1
- data/{lib/metasm → metasm/cpu}/sh4/decode.rb +48 -17
- data/{lib/metasm → metasm/cpu}/sh4/main.rb +13 -4
- data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
- data/metasm/cpu/x86_64.rb +15 -0
- data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +28 -17
- data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
- data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +57 -15
- data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +55 -26
- data/{lib/metasm → metasm/cpu}/x86_64/main.rb +14 -6
- data/metasm/cpu/x86_64/opcodes.rb +136 -0
- data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +10 -2
- data/metasm/cpu/x86_64/render.rb +35 -0
- data/metasm/cpu/z80.rb +9 -0
- data/metasm/cpu/z80/decode.rb +313 -0
- data/metasm/cpu/z80/main.rb +67 -0
- data/metasm/cpu/z80/opcodes.rb +224 -0
- data/metasm/cpu/z80/render.rb +59 -0
- data/{lib/metasm/os/main.rb → metasm/debug.rb} +160 -401
- data/{lib/metasm → metasm}/decode.rb +35 -4
- data/{lib/metasm → metasm}/decompile.rb +15 -16
- data/{lib/metasm → metasm}/disassemble.rb +201 -45
- data/{lib/metasm → metasm}/disassemble_api.rb +651 -87
- data/{lib/metasm → metasm}/dynldr.rb +220 -133
- data/{lib/metasm → metasm}/encode.rb +10 -1
- data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
- data/{lib/metasm → metasm}/exe_format/autoexe.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
- data/{lib/metasm → metasm}/exe_format/coff.rb +11 -3
- data/{lib/metasm → metasm}/exe_format/coff_decode.rb +53 -20
- data/{lib/metasm → metasm}/exe_format/coff_encode.rb +11 -13
- data/{lib/metasm → metasm}/exe_format/dex.rb +13 -5
- data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/elf.rb +93 -57
- data/{lib/metasm → metasm}/exe_format/elf_decode.rb +143 -34
- data/{lib/metasm → metasm}/exe_format/elf_encode.rb +122 -31
- data/metasm/exe_format/gb.rb +65 -0
- data/metasm/exe_format/javaclass.rb +424 -0
- data/{lib/metasm → metasm}/exe_format/macho.rb +204 -16
- data/{lib/metasm → metasm}/exe_format/main.rb +26 -3
- data/{lib/metasm → metasm}/exe_format/mz.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
- data/{lib/metasm → metasm}/exe_format/pe.rb +71 -8
- data/metasm/exe_format/pyc.rb +167 -0
- data/{lib/metasm → metasm}/exe_format/serialstruct.rb +67 -14
- data/{lib/metasm → metasm}/exe_format/shellcode.rb +7 -3
- data/metasm/exe_format/shellcode_rwx.rb +114 -0
- data/metasm/exe_format/swf.rb +205 -0
- data/{lib/metasm → metasm}/exe_format/xcoff.rb +7 -7
- data/metasm/exe_format/zip.rb +335 -0
- data/metasm/gui.rb +13 -0
- data/{lib/metasm → metasm}/gui/cstruct.rb +35 -41
- data/{lib/metasm → metasm}/gui/dasm_coverage.rb +11 -11
- data/{lib/metasm → metasm}/gui/dasm_decomp.rb +7 -20
- data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
- data/metasm/gui/dasm_graph.rb +1695 -0
- data/{lib/metasm → metasm}/gui/dasm_hex.rb +12 -8
- data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
- data/{lib/metasm → metasm}/gui/dasm_main.rb +310 -53
- data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
- data/{lib/metasm → metasm}/gui/debug.rb +93 -27
- data/{lib/metasm → metasm}/gui/gtk.rb +162 -40
- data/{lib/metasm → metasm}/gui/qt.rb +12 -2
- data/{lib/metasm → metasm}/gui/win32.rb +179 -42
- data/{lib/metasm → metasm}/gui/x11.rb +59 -59
- data/{lib/metasm → metasm}/main.rb +389 -264
- data/{lib/metasm/os/remote.rb → metasm/os/gdbremote.rb} +146 -54
- data/{lib/metasm → metasm}/os/gnu_exports.rb +1 -1
- data/{lib/metasm → metasm}/os/linux.rb +628 -151
- data/metasm/os/main.rb +330 -0
- data/{lib/metasm → metasm}/os/windows.rb +132 -42
- data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
- data/{lib/metasm → metasm}/parse.rb +26 -24
- data/{lib/metasm → metasm}/parse_c.rb +221 -116
- data/{lib/metasm → metasm}/preprocessor.rb +55 -40
- data/{lib/metasm → metasm}/render.rb +14 -38
- data/misc/hexdump.rb +2 -1
- data/misc/lint.rb +58 -0
- data/misc/txt2html.rb +9 -7
- data/samples/bindiff.rb +3 -4
- data/samples/dasm-plugins/bindiff.rb +15 -0
- data/samples/dasm-plugins/bookmark.rb +133 -0
- data/samples/dasm-plugins/c_constants.rb +57 -0
- data/samples/dasm-plugins/colortheme_solarized.rb +125 -0
- data/samples/dasm-plugins/cppobj_funcall.rb +60 -0
- data/samples/dasm-plugins/dasm_all.rb +70 -0
- data/samples/dasm-plugins/demangle_cpp.rb +31 -0
- data/samples/dasm-plugins/deobfuscate.rb +251 -0
- data/samples/dasm-plugins/dump_text.rb +35 -0
- data/samples/dasm-plugins/export_graph_svg.rb +86 -0
- data/samples/dasm-plugins/findgadget.rb +75 -0
- data/samples/dasm-plugins/hl_opcode.rb +32 -0
- data/samples/dasm-plugins/hotfix_gtk_dbg.rb +19 -0
- data/samples/dasm-plugins/imm2off.rb +34 -0
- data/samples/dasm-plugins/match_libsigs.rb +93 -0
- data/samples/dasm-plugins/patch_file.rb +95 -0
- data/samples/dasm-plugins/scanfuncstart.rb +36 -0
- data/samples/dasm-plugins/scanxrefs.rb +26 -0
- data/samples/dasm-plugins/selfmodify.rb +197 -0
- data/samples/dasm-plugins/stringsxrefs.rb +28 -0
- data/samples/dasmnavig.rb +1 -1
- data/samples/dbg-apihook.rb +24 -9
- data/samples/dbg-plugins/heapscan.rb +283 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_lin.c +155 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_win.c +128 -0
- data/samples/dbg-plugins/heapscan/graphheap.rb +616 -0
- data/samples/dbg-plugins/heapscan/heapscan.rb +709 -0
- data/samples/dbg-plugins/heapscan/winheap.h +174 -0
- data/samples/dbg-plugins/heapscan/winheap7.h +307 -0
- data/samples/dbg-plugins/trace_func.rb +214 -0
- data/samples/disassemble-gui.rb +35 -5
- data/samples/disassemble.rb +31 -6
- data/samples/dump_upx.rb +24 -12
- data/samples/dynamic_ruby.rb +12 -3
- data/samples/exeencode.rb +6 -5
- data/samples/factorize-headers-peimports.rb +1 -1
- data/samples/lindebug.rb +175 -381
- data/samples/metasm-shell.rb +1 -2
- data/samples/peldr.rb +2 -2
- data/tests/all.rb +1 -1
- data/tests/arc.rb +26 -0
- data/tests/dynldr.rb +22 -4
- data/tests/expression.rb +55 -0
- data/tests/graph_layout.rb +285 -0
- data/tests/ia32.rb +79 -26
- data/tests/mips.rb +9 -2
- data/tests/x86_64.rb +66 -18
- metadata +330 -218
- data/lib/metasm/arm/opcodes.rb +0 -177
- data/lib/metasm/gui.rb +0 -23
- data/lib/metasm/gui/dasm_graph.rb +0 -1354
- data/lib/metasm/ia32.rb +0 -14
- data/lib/metasm/ia32/opcodes.rb +0 -873
- data/lib/metasm/ppc/parse.rb +0 -52
- data/lib/metasm/x86_64.rb +0 -12
- data/lib/metasm/x86_64/opcodes.rb +0 -118
- data/samples/gdbclient.rb +0 -583
- data/samples/rubstop.rb +0 -399
|
@@ -17,6 +17,9 @@ class MachO < ExeFormat
|
|
|
17
17
|
|
|
18
18
|
MAGICS = [MAGIC, CIGAM, MAGIC64, CIGAM64]
|
|
19
19
|
|
|
20
|
+
# "a" != "a" lolz!
|
|
21
|
+
MAGICS.each { |s| s.force_encoding('BINARY') } if MAGIC.respond_to?(:force_encoding)
|
|
22
|
+
|
|
20
23
|
CPU = {
|
|
21
24
|
1 => 'VAX', 2 => 'ROMP',
|
|
22
25
|
4 => 'NS32032', 5 => 'NS32332',
|
|
@@ -44,7 +47,7 @@ class MachO < ExeFormat
|
|
|
44
47
|
3 => 'MMAX_APC_FPU', 4 => 'MMAX_APC_FPA', 5 => 'MMAX_XPC',
|
|
45
48
|
},
|
|
46
49
|
'I386' => { 3 => 'ALL', 4 => '486', 4+128 => '486SX',
|
|
47
|
-
|
|
50
|
+
0 => 'INTEL_MODEL_ALL', 10 => 'PENTIUM_4',
|
|
48
51
|
5 => 'PENT', 0x16 => 'PENTPRO', 0x36 => 'PENTII_M3', 0x56 => 'PENTII_M5',
|
|
49
52
|
},
|
|
50
53
|
'MIPS' => { 0 => 'ALL', 1 => 'R2300', 2 => 'R2600', 3 => 'R2800', 4 => 'R2000a', },
|
|
@@ -52,6 +55,7 @@ class MachO < ExeFormat
|
|
|
52
55
|
'HPPA' => { 0 => 'ALL', 1 => '7100LC', },
|
|
53
56
|
'ARM' => { 0 => 'ALL', 1 => 'A500_ARCH', 2 => 'A500', 3 => 'A440',
|
|
54
57
|
4 => 'M4', 5 => 'A680', 6 => 'ARMV6', 9 => 'ARMV7',
|
|
58
|
+
11 => 'ARMV7S',
|
|
55
59
|
},
|
|
56
60
|
'MC88000' => { 0 => 'ALL', 1 => 'MC88100', 2 => 'MC88110', },
|
|
57
61
|
:wtf => { 0 => 'MC98000_ALL', 1 => 'MC98601', },
|
|
@@ -82,7 +86,7 @@ class MachO < ExeFormat
|
|
|
82
86
|
0x10 => 'PREBOUND', 0x20 => 'SPLIT_SEGS', 0x40 => 'LAZY_INIT', 0x80 => 'TWOLEVEL',
|
|
83
87
|
0x100 => 'FORCE_FLAT', 0x200 => 'NOMULTIDEFS', 0x400 => 'NOFIXPREBINDING', 0x800 => 'PREBINDABLE',
|
|
84
88
|
0x1000 => 'ALLMODSBOUND', 0x2000 => 'SUBSECTIONS_VIA_SYMBOLS', 0x4000 => 'CANONICAL', 0x8000 => 'WEAK_DEFINES',
|
|
85
|
-
0x10000 => 'BINDS_TO_WEAK', 0x20000 => 'ALLOW_STACK_EXECUTION',
|
|
89
|
+
0x10000 => 'BINDS_TO_WEAK', 0x20000 => 'ALLOW_STACK_EXECUTION', 0x200000 => 'MH_PIE',
|
|
86
90
|
}
|
|
87
91
|
|
|
88
92
|
SEG_PROT = { 1 => 'READ', 2 => 'WRITE', 4 => 'EXECUTE' }
|
|
@@ -96,12 +100,13 @@ class MachO < ExeFormat
|
|
|
96
100
|
0x15 => 'SUB_LIBRARY', 0x16 => 'TWOLEVEL_HINTS', 0x17 => 'PREBIND_CKSUM',
|
|
97
101
|
0x8000_0018 => 'LOAD_WEAK_DYLIB', 0x19 => 'SEGMENT_64', 0x1a => 'ROUTINES_64',
|
|
98
102
|
0x1b => 'UUID', 0x8000_001c => 'RPATH', 0x1d => 'CODE_SIGNATURE_PTR', 0x1e => 'CODE_SEGMENT_SPLIT_INFO',
|
|
103
|
+
0x21 => 'ENCRYPTION_INFO',
|
|
99
104
|
0x8000_001f => 'REEXPORT_DYLIB',
|
|
100
105
|
#0x8000_0000 => 'REQ_DYLD',
|
|
101
106
|
}
|
|
102
107
|
|
|
103
108
|
THREAD_FLAVOR = {
|
|
104
|
-
'POWERPC' => {
|
|
109
|
+
'POWERPC' => {
|
|
105
110
|
1 => 'THREAD_STATE',
|
|
106
111
|
2 => 'FLOAT_STATE',
|
|
107
112
|
3 => 'EXCEPTION_STATE',
|
|
@@ -126,6 +131,15 @@ class MachO < ExeFormat
|
|
|
126
131
|
SYM_SCOPE = { 0 => 'LOCAL', 1 => 'GLOBAL' }
|
|
127
132
|
SYM_TYPE = { 0 => 'UNDF', 2/2 => 'ABS', 0xa/2 => 'INDR', 0xe/2 => 'SECT', 0x1e/2 => 'TYPE' }
|
|
128
133
|
SYM_STAB = { }
|
|
134
|
+
IND_SYM_IDX = { 0x4000_0000 => 'INDIRECT_SYMBOL_ABS', 0x8000_0000 => 'INDIRECT_SYMBOL_LOCAL' }
|
|
135
|
+
|
|
136
|
+
GENERIC_RELOC = { 0 => 'VANILLA', 1 => 'PAIR', 2 => 'SECTDIFF', 3 => 'LOCAL_SECTDIFF', 4 => 'PB_LA_PTR' }
|
|
137
|
+
|
|
138
|
+
SEC_TYPE = {
|
|
139
|
+
0 => 'REGULAR', 1 => 'ZEROFILL', 2 => 'CSTRING_LITERALS', 3 => '4BYTE_LITERALS',
|
|
140
|
+
4 => '8BYTE_LITERALS', 5 => 'LITERAL_POINTERS', 6 => 'NON_LAZY_SYMBOL_POINTERS',
|
|
141
|
+
7 => 'LAZY_SYMBOL_POINTERS', 8 => 'SYMBOL_STUBS', 9 => 'MOD_INIT_FUNC_POINTERS'
|
|
142
|
+
}
|
|
129
143
|
|
|
130
144
|
class SerialStruct < Metasm::SerialStruct
|
|
131
145
|
new_int_field :xword
|
|
@@ -180,7 +194,7 @@ class MachO < ExeFormat
|
|
|
180
194
|
def decode(m)
|
|
181
195
|
super(m)
|
|
182
196
|
ptr = m.encoded.ptr
|
|
183
|
-
if @cmd.kind_of?
|
|
197
|
+
if @cmd.kind_of?(String) and self.class.constants.map { |c| c.to_s }.include?(@cmd)
|
|
184
198
|
@data = self.class.const_get(@cmd).decode(m)
|
|
185
199
|
end
|
|
186
200
|
m.encoded.ptr = ptr + @cmdsize - 8
|
|
@@ -193,7 +207,7 @@ class MachO < ExeFormat
|
|
|
193
207
|
end
|
|
194
208
|
|
|
195
209
|
def encode(m)
|
|
196
|
-
ed = super(m)
|
|
210
|
+
ed = super(m)
|
|
197
211
|
ed << @data.encode(m) if @data
|
|
198
212
|
ed.align(m.size >> 3)
|
|
199
213
|
ed.fixup! @cmdsize => ed.length if @cmdsize.kind_of? String
|
|
@@ -243,7 +257,10 @@ class MachO < ExeFormat
|
|
|
243
257
|
str :name, 16
|
|
244
258
|
str :segname, 16
|
|
245
259
|
xwords :addr, :size
|
|
246
|
-
words :offset, :align, :reloff, :nreloc
|
|
260
|
+
words :offset, :align, :reloff, :nreloc
|
|
261
|
+
bitfield :word, 0 => :type, 8 => :attributes_sys, 24 => :attributes_usr
|
|
262
|
+
words :res1, :res2
|
|
263
|
+
fld_enum :type, SEC_TYPE
|
|
247
264
|
attr_accessor :res3 # word 64bit only
|
|
248
265
|
attr_accessor :segment, :encoded
|
|
249
266
|
|
|
@@ -258,10 +275,6 @@ class MachO < ExeFormat
|
|
|
258
275
|
# addr, offset, etc = @segment.virtaddr + 42
|
|
259
276
|
super(m)
|
|
260
277
|
end
|
|
261
|
-
|
|
262
|
-
def decode_inner(m)
|
|
263
|
-
@encoded = m.encoded[m.addr_to_off(@addr), @size]
|
|
264
|
-
end
|
|
265
278
|
end
|
|
266
279
|
SECTION_64 = SECTION
|
|
267
280
|
|
|
@@ -279,7 +292,7 @@ class MachO < ExeFormat
|
|
|
279
292
|
words :flavor, :count
|
|
280
293
|
fld_enum(:flavor) { |m, t| THREAD_FLAVOR[m.header.cputype] || {} }
|
|
281
294
|
attr_accessor :ctx
|
|
282
|
-
|
|
295
|
+
|
|
283
296
|
def entrypoint(m)
|
|
284
297
|
@ctx ||= {}
|
|
285
298
|
case m.header.cputype
|
|
@@ -346,6 +359,7 @@ class MachO < ExeFormat
|
|
|
346
359
|
end
|
|
347
360
|
LOAD_DYLIB = DYLIB
|
|
348
361
|
ID_DYLIB = DYLIB
|
|
362
|
+
LOAD_WEAK_DYLIB = DYLIB
|
|
349
363
|
|
|
350
364
|
class PREBOUND_DYLIB < STRING
|
|
351
365
|
word :stroff
|
|
@@ -356,6 +370,10 @@ class MachO < ExeFormat
|
|
|
356
370
|
LOAD_DYLINKER = STRING
|
|
357
371
|
ID_DYLINKER = STRING
|
|
358
372
|
|
|
373
|
+
class ENCRYPTION_INFO < SerialStruct
|
|
374
|
+
words :cryptoff, :cryptsize, :cryptid
|
|
375
|
+
end
|
|
376
|
+
|
|
359
377
|
class ROUTINES < SerialStruct
|
|
360
378
|
xwords :init_addr, :init_module, :res1, :res2, :res3, :res4, :res5, :res6
|
|
361
379
|
end
|
|
@@ -479,6 +497,12 @@ class MachO < ExeFormat
|
|
|
479
497
|
end
|
|
480
498
|
end
|
|
481
499
|
|
|
500
|
+
class Relocation < SerialStruct
|
|
501
|
+
word :address
|
|
502
|
+
bitfield :word, 0 => :symbolnum, 24 => :pcrel, 25 => :length, 27 => :extern, 28 => :type
|
|
503
|
+
fld_enum :type, GENERIC_RELOC
|
|
504
|
+
end
|
|
505
|
+
|
|
482
506
|
def encode_byte(val) Expression[val].encode( :u8, @endianness) end
|
|
483
507
|
def encode_half(val) Expression[val].encode(:u16, @endianness) end
|
|
484
508
|
def encode_word(val) Expression[val].encode(:u32, @endianness) end
|
|
@@ -487,6 +511,10 @@ class MachO < ExeFormat
|
|
|
487
511
|
def decode_half(edata = @encoded) edata.decode_imm(:u16, @endianness) end
|
|
488
512
|
def decode_word(edata = @encoded) edata.decode_imm(:u32, @endianness) end
|
|
489
513
|
def decode_xword(edata= @encoded) edata.decode_imm((@size == 32 ? :u32 : :u64), @endianness) end
|
|
514
|
+
def sizeof_byte ; 1 ; end
|
|
515
|
+
def sizeof_half ; 2 ; end
|
|
516
|
+
def sizeof_word ; 4 ; end
|
|
517
|
+
def sizeof_xword ; @size == 32 ? 4 : 8 ; end
|
|
490
518
|
|
|
491
519
|
|
|
492
520
|
attr_accessor :endianness, :size
|
|
@@ -494,6 +522,7 @@ class MachO < ExeFormat
|
|
|
494
522
|
attr_accessor :segments
|
|
495
523
|
attr_accessor :commands
|
|
496
524
|
attr_accessor :symbols
|
|
525
|
+
attr_accessor :relocs
|
|
497
526
|
|
|
498
527
|
def initialize(cpu=nil)
|
|
499
528
|
super(cpu)
|
|
@@ -523,6 +552,35 @@ class MachO < ExeFormat
|
|
|
523
552
|
decode_relocations
|
|
524
553
|
end
|
|
525
554
|
|
|
555
|
+
# return the segment containing address, set seg.encoded.ptr to the correct offset
|
|
556
|
+
def segment_at(addr)
|
|
557
|
+
return if not addr or addr <= 0
|
|
558
|
+
if seg = @segments.find { |seg_| addr >= seg_.virtaddr and addr < seg_.virtaddr + seg_.virtsize }
|
|
559
|
+
seg.encoded.ptr = addr - seg.virtaddr
|
|
560
|
+
seg
|
|
561
|
+
end
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
def addr_to_fileoff(addr)
|
|
565
|
+
s = @segments.find { |s_| s_.virtaddr <= addr and s_.virtaddr + s_.virtsize > addr } if addr
|
|
566
|
+
addr - s.virtaddr + s.fileoff if s
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
def fileoff_to_addr(foff)
|
|
570
|
+
if s = @segments.find { |s_| s_.fileoff <= foff and s_.fileoff + s_.filesize > foff }
|
|
571
|
+
s.virtaddr + module_address + foff - s.fileoff
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
def module_address
|
|
576
|
+
@segments.map { |s_| s_.virtaddr }.min || 0
|
|
577
|
+
end
|
|
578
|
+
|
|
579
|
+
def module_size
|
|
580
|
+
return 0 if not sz = @segments.map { |s_| s_.virtaddr + s_.virtsize }.max
|
|
581
|
+
sz - module_address
|
|
582
|
+
end
|
|
583
|
+
|
|
526
584
|
def decode_symbols
|
|
527
585
|
@symbols = []
|
|
528
586
|
ep_count = 0
|
|
@@ -537,30 +595,159 @@ class MachO < ExeFormat
|
|
|
537
595
|
when 'THREAD', 'UNIXTHREAD'
|
|
538
596
|
ep_count += 1
|
|
539
597
|
ep = cmd.data.entrypoint(self)
|
|
540
|
-
next if not seg =
|
|
541
|
-
seg.encoded.add_export("entrypoint#{"_#{ep_count}" if ep_count >= 2 }"
|
|
598
|
+
next if not seg = segment_at(ep)
|
|
599
|
+
seg.encoded.add_export("entrypoint#{"_#{ep_count}" if ep_count >= 2 }")
|
|
542
600
|
end
|
|
543
601
|
}
|
|
544
602
|
@symbols.each { |s|
|
|
545
603
|
next if s.value == 0 or not s.name
|
|
546
|
-
next if not seg =
|
|
547
|
-
seg.encoded.add_export(s.name
|
|
604
|
+
next if not seg = segment_at(s.value)
|
|
605
|
+
seg.encoded.add_export(s.name)
|
|
548
606
|
}
|
|
549
607
|
end
|
|
550
608
|
|
|
551
609
|
def decode_relocations
|
|
610
|
+
@relocs = []
|
|
611
|
+
indsymtab = []
|
|
612
|
+
@commands.each { |cmd|
|
|
613
|
+
if cmd.cmd == 'DYSYMTAB'
|
|
614
|
+
@encoded.ptr = cmd.data.extreloff
|
|
615
|
+
cmd.data.nextrel.times { @relocs << Relocation.decode(self) }
|
|
616
|
+
@encoded.ptr = cmd.data.locreloff
|
|
617
|
+
cmd.data.nlocrel.times { @relocs << Relocation.decode(self) }
|
|
618
|
+
@encoded.ptr = cmd.data.indirectsymoff
|
|
619
|
+
cmd.data.nindirectsyms.times { indsymtab << decode_word }
|
|
620
|
+
end
|
|
621
|
+
}
|
|
622
|
+
@segments.each { |seg|
|
|
623
|
+
seg.sections.each { |sec|
|
|
624
|
+
@encoded.ptr = sec.reloff
|
|
625
|
+
sec.nreloc.times { @relocs << Relocation.decode(self) }
|
|
626
|
+
|
|
627
|
+
case sec.type
|
|
628
|
+
when 'NON_LAZY_SYMBOL_POINTERS', 'LAZY_SYMBOL_POINTERS'
|
|
629
|
+
edata = seg.encoded
|
|
630
|
+
off = sec.offset - seg.fileoff
|
|
631
|
+
(sec.size / 4).times { |i|
|
|
632
|
+
sidx = indsymtab[sec.res1+i]
|
|
633
|
+
case IND_SYM_IDX[sidx]
|
|
634
|
+
when 'INDIRECT_SYMBOL_LOCAL' # base reloc: add delta from prefered image base
|
|
635
|
+
edata.ptr = off
|
|
636
|
+
addr = decode_word(edata)
|
|
637
|
+
if s = segment_at(addr)
|
|
638
|
+
label = label_at(s.encoded, s.encoded.ptr, "xref_#{Expression[addr]}")
|
|
639
|
+
seg.encoded.reloc[off] = Metasm::Relocation.new(Expression[label], :u32, @endianness)
|
|
640
|
+
end
|
|
641
|
+
when 'INDIRECT_SYMBOL_ABS' # nothing
|
|
642
|
+
else
|
|
643
|
+
sym = @symbols[sidx]
|
|
644
|
+
seg.encoded.reloc[off] = Metasm::Relocation.new(Expression[sym.name], :u32, @endianness)
|
|
645
|
+
end
|
|
646
|
+
off += 4
|
|
647
|
+
}
|
|
648
|
+
when 'SYMBOL_STUBS'
|
|
649
|
+
# TODO next unless arch == 386 and sec.attrs & SELF_MODIFYING_CODE and sec.res2 == 5
|
|
650
|
+
|
|
651
|
+
edata = seg.encoded
|
|
652
|
+
edata.data = edata.data.to_str.dup
|
|
653
|
+
off = sec.offset - seg.fileoff + 1
|
|
654
|
+
(sec.size / 5).times { |i|
|
|
655
|
+
sidx = indsymtab[sec.res1+i]
|
|
656
|
+
case IND_SYM_IDX[sidx]
|
|
657
|
+
when 'INDIRECT_SYMBOL_LOCAL' # base reloc: add delta from prefered image base
|
|
658
|
+
edata.ptr = off
|
|
659
|
+
addr = decode_word(edata)
|
|
660
|
+
if s = segment_at(addr)
|
|
661
|
+
label = label_at(s.encoded, s.encoded.ptr, "xref_#{Expression[addr]}")
|
|
662
|
+
seg.encoded.reloc[off] = Metasm::Relocation.new(Expression[label, :-, Expression[seg.virtaddr, :+, off+4].reduce], :u32, @endianness)
|
|
663
|
+
end
|
|
664
|
+
when 'INDIRECT_SYMBOL_ABS' # nothing
|
|
665
|
+
else
|
|
666
|
+
seg.encoded[off-1] = 0xe9
|
|
667
|
+
sym = @symbols[sidx]
|
|
668
|
+
seg.encoded.reloc[off] = Metasm::Relocation.new(Expression[sym.name, :-, Expression[seg.virtaddr, :+, off+4].reduce], :u32, @endianness)
|
|
669
|
+
end
|
|
670
|
+
off += 5
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
end
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
seg = nil
|
|
677
|
+
@relocs.each { |r|
|
|
678
|
+
if r.extern == 1
|
|
679
|
+
sym = @symbols[r.symbolnum]
|
|
680
|
+
seg = @segments.find { |sg| sg.virtaddr <= r.address and sg.virtaddr + sg.virtsize > r.address } unless seg and seg.virtaddr <= r.address and seg.virtaddr + seg.virtsize > r.address
|
|
681
|
+
if not seg
|
|
682
|
+
puts "macho: reloc to unmapped space #{r.inspect} #{sym.inspect}" if $VERBOSE
|
|
683
|
+
next
|
|
684
|
+
end
|
|
685
|
+
seg.encoded.reloc[r.address - seg.virtaddr] = Metasm::Relocation.new(Expression[sym.name], :u32, @endianness)
|
|
686
|
+
end
|
|
687
|
+
}
|
|
552
688
|
end
|
|
553
689
|
|
|
554
690
|
def decode_segment(s)
|
|
691
|
+
@encoded.add_export(s.name, s.fileoff)
|
|
555
692
|
s.encoded = @encoded[s.fileoff, s.filesize]
|
|
556
693
|
s.encoded.virtsize = s.virtsize
|
|
557
|
-
s.sections.each { |ss|
|
|
694
|
+
s.sections.each { |ss|
|
|
695
|
+
ss.encoded = @encoded[ss.offset, ss.size]
|
|
696
|
+
s.encoded.add_export(ss.name, ss.offset - s.fileoff)
|
|
697
|
+
}
|
|
558
698
|
end
|
|
559
699
|
|
|
560
700
|
def each_section(&b)
|
|
561
701
|
@segments.each { |s| yield s.encoded, s.virtaddr }
|
|
562
702
|
end
|
|
563
703
|
|
|
704
|
+
def section_info
|
|
705
|
+
ret = []
|
|
706
|
+
@segments.each { |seg|
|
|
707
|
+
ret.concat seg.sections.map { |s| [s.name, s.addr, s.size, s.type] }
|
|
708
|
+
}
|
|
709
|
+
ret
|
|
710
|
+
end
|
|
711
|
+
|
|
712
|
+
def init_disassembler
|
|
713
|
+
d = super()
|
|
714
|
+
case @cpu.shortname
|
|
715
|
+
when 'ia32', 'x64'
|
|
716
|
+
old_cp = d.c_parser
|
|
717
|
+
d.c_parser = nil
|
|
718
|
+
d.parse_c <<EOC
|
|
719
|
+
void *dlsym(int, char *); // has special callback
|
|
720
|
+
// standard noreturn, optimized by gcc
|
|
721
|
+
void __attribute__((noreturn)) exit(int);
|
|
722
|
+
void abort(void) __attribute__((noreturn));
|
|
723
|
+
EOC
|
|
724
|
+
d.function[Expression['_dlsym']] = d.function[Expression['dlsym']] = dls = @cpu.decode_c_function_prototype(d.c_parser, 'dlsym')
|
|
725
|
+
d.function[Expression['_exit']] = d.function[Expression['exit']] = @cpu.decode_c_function_prototype(d.c_parser, 'exit')
|
|
726
|
+
d.function[Expression['abort']] = @cpu.decode_c_function_prototype(d.c_parser, 'abort')
|
|
727
|
+
d.c_parser = old_cp
|
|
728
|
+
|
|
729
|
+
dls.btbind_callback = lambda { |dasm, bind, funcaddr, calladdr, expr, origin, maxdepth|
|
|
730
|
+
sz = @cpu.size/8
|
|
731
|
+
raise 'dlsym call error' if not dasm.decoded[calladdr]
|
|
732
|
+
if @cpu.shortname == 'x64'
|
|
733
|
+
arg2 = :rsi
|
|
734
|
+
else
|
|
735
|
+
arg2 = Indirection.new(Expression[:esp, :+, 2*sz], sz, calladdr)
|
|
736
|
+
end
|
|
737
|
+
fnaddr = dasm.backtrace(arg2, calladdr, :include_start => true, :maxdepth => maxdepth)
|
|
738
|
+
if fnaddr.kind_of?(::Array) and fnaddr.length == 1 and s = dasm.decode_strz(fnaddr.first, 64) and s.length > sz
|
|
739
|
+
bind = bind.merge @cpu.register_symbols[0] => Expression[s]
|
|
740
|
+
end
|
|
741
|
+
bind
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
df = d.function[:default] = @cpu.disassembler_default_func
|
|
745
|
+
df.backtrace_binding[@cpu.register_symbols[4]] = Expression[@cpu.register_symbols[4], :+, @cpu.size/8]
|
|
746
|
+
df.btbind_callback = nil
|
|
747
|
+
end
|
|
748
|
+
d
|
|
749
|
+
end
|
|
750
|
+
|
|
564
751
|
def get_default_entrypoints
|
|
565
752
|
@commands.find_all { |cmd| cmd.cmd == 'THREAD' or cmd.cmd == 'UNIXTHREAD' }.map { |cmd| cmd.data.entrypoint(self) }
|
|
566
753
|
end
|
|
@@ -795,6 +982,7 @@ class UniversalBinary < ExeFormat
|
|
|
795
982
|
|
|
796
983
|
def encode_word(val) Expression[val].encode(:u32, @endianness) end
|
|
797
984
|
def decode_word(edata = @encoded) edata.decode_imm(:u32, @endianness) end
|
|
985
|
+
def sizeof_word ; 4 ; end
|
|
798
986
|
|
|
799
987
|
attr_accessor :endianness, :encoded, :header, :archive
|
|
800
988
|
def initialize
|
|
@@ -16,7 +16,7 @@ class ExeFormat
|
|
|
16
16
|
# creates a new instance, populates self.encoded with the supplied string
|
|
17
17
|
def self.load(str, *a, &b)
|
|
18
18
|
e = new(*a, &b)
|
|
19
|
-
if str.kind_of?
|
|
19
|
+
if str.kind_of?(EncodedData); e.encoded = str
|
|
20
20
|
else e.encoded << str
|
|
21
21
|
end
|
|
22
22
|
e
|
|
@@ -63,6 +63,30 @@ class ExeFormat
|
|
|
63
63
|
e
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
+
def load(str)
|
|
67
|
+
if str.kind_of?(EncodedData); @encoded = str
|
|
68
|
+
else @encoded << str
|
|
69
|
+
end
|
|
70
|
+
self
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def load_file(path)
|
|
74
|
+
@filename ||= path
|
|
75
|
+
load(VirtualFile.read(path))
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def decode_file(path)
|
|
79
|
+
load_file(path)
|
|
80
|
+
decode
|
|
81
|
+
self
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def decode_file_header(path)
|
|
85
|
+
load_file(path)
|
|
86
|
+
decode_header
|
|
87
|
+
self
|
|
88
|
+
end
|
|
89
|
+
|
|
66
90
|
# creates a new object using the specified cpu, parses the asm source, and assemble
|
|
67
91
|
def self.assemble(cpu, source, file='<unk>', lineno=1)
|
|
68
92
|
source, cpu = cpu, source if source.kind_of? CPU
|
|
@@ -175,9 +199,8 @@ class ExeFormat
|
|
|
175
199
|
end
|
|
176
200
|
|
|
177
201
|
# saves the result of +encode_string+ in the specified file
|
|
178
|
-
#
|
|
202
|
+
# overwrites existing files
|
|
179
203
|
def encode_file(path, *a)
|
|
180
|
-
#raise Errno::EEXIST, path if File.exist? path # race, but cannot use O_EXCL, as O_BINARY is not defined in ruby
|
|
181
204
|
encode_string(*a)
|
|
182
205
|
File.open(path, 'wb') { |fd| fd.write(@encoded.data) }
|
|
183
206
|
end
|
|
@@ -51,6 +51,7 @@ class MZ < ExeFormat
|
|
|
51
51
|
def encode_word(val) Expression[val].encode(:u16, @endianness) end
|
|
52
52
|
# decodes a 16bits word from self.encoded
|
|
53
53
|
def decode_word(edata = @encoded) edata.decode_imm(:u16, @endianness) end
|
|
54
|
+
def sizeof_word ; 2 ; end
|
|
54
55
|
|
|
55
56
|
|
|
56
57
|
attr_accessor :endianness, :header, :source
|
|
@@ -30,7 +30,7 @@ class NDS < ExeFormat
|
|
|
30
30
|
mem :secareadisable, 8
|
|
31
31
|
words :endoff, :headersz
|
|
32
32
|
mem :reserved4, 56
|
|
33
|
-
|
|
33
|
+
mem :ninlogo, 156
|
|
34
34
|
half :logoCRC, 0xcf56
|
|
35
35
|
half :headerCRC
|
|
36
36
|
end
|
|
@@ -70,14 +70,17 @@ class NDS < ExeFormat
|
|
|
70
70
|
def decode_byte(edata = @encoded) edata.decode_imm(:u8, @endianness) end
|
|
71
71
|
def decode_half(edata = @encoded) edata.decode_imm(:u16, @endianness) end
|
|
72
72
|
def decode_word(edata = @encoded) edata.decode_imm(:u32, @endianness) end
|
|
73
|
+
def sizeof_byte ; 1 ; end
|
|
74
|
+
def sizeof_half ; 2 ; end
|
|
75
|
+
def sizeof_word ; 4 ; end
|
|
73
76
|
|
|
74
77
|
|
|
75
78
|
attr_accessor :header, :icon, :arm9, :arm7
|
|
76
79
|
attr_accessor :files, :fat
|
|
77
80
|
|
|
78
|
-
def initialize(
|
|
79
|
-
@endianness = endianness
|
|
80
|
-
|
|
81
|
+
def initialize(cpu=nil)
|
|
82
|
+
@endianness = (cpu ? cpu.endianness : :little)
|
|
83
|
+
super(cpu)
|
|
81
84
|
end
|
|
82
85
|
|
|
83
86
|
# decodes the header from the current offset in self.encoded
|