metasm 1.0.0 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +3 -0
- data/.gitignore +3 -0
- data/.hgtags +3 -0
- data/Gemfile +3 -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 +3 -1
- 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 +23 -0
- data/{lib/metasm.rb → metasm.rb} +15 -3
- data/{lib/metasm → metasm}/compile_c.rb +15 -9
- data/metasm/cpu/arc.rb +8 -0
- data/metasm/cpu/arc/decode.rb +404 -0
- data/metasm/cpu/arc/main.rb +191 -0
- data/metasm/cpu/arc/opcodes.rb +588 -0
- data/metasm/cpu/arm.rb +14 -0
- data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
- data/{lib/metasm → metasm/cpu}/arm/decode.rb +15 -18
- data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
- data/{lib/metasm → metasm/cpu}/arm/main.rb +3 -6
- 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 +285 -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/mips/compile_c.rb → metasm/cpu/bpf.rb} +4 -2
- data/metasm/cpu/bpf/decode.rb +110 -0
- data/metasm/cpu/bpf/main.rb +60 -0
- data/metasm/cpu/bpf/opcodes.rb +81 -0
- data/metasm/cpu/bpf/render.rb +30 -0
- data/{lib/metasm/ppc.rb → metasm/cpu/cy16.rb} +2 -4
- data/metasm/cpu/cy16/decode.rb +247 -0
- data/metasm/cpu/cy16/main.rb +63 -0
- data/metasm/cpu/cy16/opcodes.rb +78 -0
- data/metasm/cpu/cy16/render.rb +30 -0
- data/metasm/cpu/dalvik.rb +11 -0
- data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +34 -34
- data/{lib/metasm → metasm/cpu}/dalvik/main.rb +71 -4
- data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +21 -12
- data/{lib/metasm/mips.rb → metasm/cpu/ebpf.rb} +3 -4
- data/metasm/cpu/ebpf/debug.rb +61 -0
- data/metasm/cpu/ebpf/decode.rb +142 -0
- data/metasm/cpu/ebpf/main.rb +58 -0
- data/metasm/cpu/ebpf/opcodes.rb +97 -0
- data/metasm/cpu/ebpf/render.rb +36 -0
- data/metasm/cpu/ia32.rb +17 -0
- data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +23 -9
- data/{lib/metasm → metasm/cpu}/ia32/debug.rb +44 -6
- data/{lib/metasm → metasm/cpu}/ia32/decode.rb +342 -128
- data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +75 -53
- data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
- data/{lib/metasm → metasm/cpu}/ia32/main.rb +66 -8
- data/metasm/cpu/ia32/opcodes.rb +1424 -0
- data/{lib/metasm → metasm/cpu}/ia32/parse.rb +55 -17
- data/{lib/metasm → metasm/cpu}/ia32/render.rb +32 -5
- data/metasm/cpu/mcs51.rb +8 -0
- data/metasm/cpu/mcs51/decode.rb +99 -0
- data/metasm/cpu/mcs51/main.rb +87 -0
- data/metasm/cpu/mcs51/opcodes.rb +120 -0
- data/metasm/cpu/mips.rb +14 -0
- data/metasm/cpu/mips/debug.rb +42 -0
- data/{lib/metasm → metasm/cpu}/mips/decode.rb +59 -38
- data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
- data/{lib/metasm → metasm/cpu}/mips/main.rb +13 -6
- data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +87 -18
- 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 +243 -0
- data/metasm/cpu/msp430/main.rb +62 -0
- data/metasm/cpu/msp430/opcodes.rb +101 -0
- data/metasm/cpu/openrisc.rb +11 -0
- data/metasm/cpu/openrisc/debug.rb +106 -0
- data/metasm/cpu/openrisc/decode.rb +182 -0
- data/metasm/cpu/openrisc/decompile.rb +350 -0
- data/metasm/cpu/openrisc/main.rb +70 -0
- data/metasm/cpu/openrisc/opcodes.rb +109 -0
- data/metasm/cpu/openrisc/render.rb +37 -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/metasm/cpu/ppc.rb +11 -0
- data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -37
- 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 +23 -18
- data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -6
- data/metasm/cpu/ppc/parse.rb +55 -0
- data/metasm/cpu/python.rb +8 -0
- data/metasm/cpu/python/decode.rb +116 -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 +50 -23
- data/{lib/metasm → metasm/cpu}/sh4/main.rb +38 -27
- data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
- data/metasm/cpu/st20.rb +9 -0
- data/metasm/cpu/st20/decode.rb +173 -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/{lib/metasm/arm.rb → metasm/cpu/webasm.rb} +4 -5
- data/metasm/cpu/webasm/debug.rb +31 -0
- data/metasm/cpu/webasm/decode.rb +321 -0
- data/metasm/cpu/webasm/decompile.rb +386 -0
- data/metasm/cpu/webasm/encode.rb +104 -0
- data/metasm/cpu/webasm/main.rb +81 -0
- data/metasm/cpu/webasm/opcodes.rb +214 -0
- data/metasm/cpu/x86_64.rb +15 -0
- data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +40 -25
- data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
- data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +58 -15
- data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +59 -28
- data/{lib/metasm → metasm/cpu}/x86_64/main.rb +18 -6
- data/metasm/cpu/x86_64/opcodes.rb +138 -0
- data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +12 -4
- data/metasm/cpu/x86_64/render.rb +35 -0
- data/metasm/cpu/z80.rb +9 -0
- data/metasm/cpu/z80/decode.rb +286 -0
- data/metasm/cpu/z80/main.rb +67 -0
- data/metasm/cpu/z80/opcodes.rb +224 -0
- data/metasm/cpu/z80/render.rb +48 -0
- data/{lib/metasm/os/main.rb → metasm/debug.rb} +201 -407
- data/{lib/metasm → metasm}/decode.rb +104 -24
- data/{lib/metasm → metasm}/decompile.rb +804 -478
- data/{lib/metasm → metasm}/disassemble.rb +385 -170
- data/{lib/metasm → metasm}/disassemble_api.rb +684 -105
- data/{lib/metasm → metasm}/dynldr.rb +231 -138
- data/{lib/metasm → metasm}/encode.rb +20 -5
- data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
- data/{lib/metasm → metasm}/exe_format/autoexe.rb +3 -0
- data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
- data/{lib/metasm → metasm}/exe_format/coff.rb +35 -7
- data/{lib/metasm → metasm}/exe_format/coff_decode.rb +70 -23
- data/{lib/metasm → metasm}/exe_format/coff_encode.rb +24 -22
- data/{lib/metasm → metasm}/exe_format/dex.rb +26 -8
- data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/elf.rb +108 -58
- data/{lib/metasm → metasm}/exe_format/elf_decode.rb +202 -36
- data/{lib/metasm → metasm}/exe_format/elf_encode.rb +126 -32
- data/metasm/exe_format/gb.rb +65 -0
- data/metasm/exe_format/javaclass.rb +424 -0
- data/{lib/metasm → metasm}/exe_format/macho.rb +218 -16
- data/{lib/metasm → metasm}/exe_format/main.rb +28 -3
- data/{lib/metasm → metasm}/exe_format/mz.rb +2 -0
- data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
- data/{lib/metasm → metasm}/exe_format/pe.rb +96 -11
- 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/metasm/exe_format/wasm.rb +402 -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 +177 -114
- data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
- data/metasm/gui/dasm_graph.rb +1754 -0
- data/{lib/metasm → metasm}/gui/dasm_hex.rb +16 -12
- data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
- data/{lib/metasm → metasm}/gui/dasm_main.rb +360 -77
- data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
- data/{lib/metasm → metasm}/gui/debug.rb +109 -34
- data/{lib/metasm → metasm}/gui/gtk.rb +174 -44
- data/{lib/metasm → metasm}/gui/qt.rb +14 -4
- data/{lib/metasm → metasm}/gui/win32.rb +180 -43
- data/{lib/metasm → metasm}/gui/x11.rb +59 -59
- data/{lib/metasm → metasm}/main.rb +421 -286
- data/metasm/os/emulator.rb +175 -0
- 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 +335 -0
- data/{lib/metasm → metasm}/os/windows.rb +151 -58
- data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
- data/{lib/metasm → metasm}/parse.rb +49 -36
- data/{lib/metasm → metasm}/parse_c.rb +405 -246
- data/{lib/metasm → metasm}/preprocessor.rb +71 -41
- data/{lib/metasm → metasm}/render.rb +14 -38
- data/misc/hexdump.rb +4 -3
- data/misc/lint.rb +58 -0
- data/misc/objdiff.rb +4 -1
- data/misc/objscan.rb +1 -1
- data/misc/openrisc-parser.rb +79 -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 +29 -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 +48 -7
- data/samples/disassemble.rb +31 -6
- data/samples/dump_upx.rb +24 -12
- data/samples/dynamic_ruby.rb +35 -27
- data/samples/elfencode.rb +15 -0
- data/samples/emubios.rb +251 -0
- data/samples/emudbg.rb +127 -0
- data/samples/exeencode.rb +6 -5
- data/samples/factorize-headers-peimports.rb +1 -1
- data/samples/lindebug.rb +186 -391
- data/samples/metasm-shell.rb +68 -57
- 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 +57 -0
- data/tests/graph_layout.rb +285 -0
- data/tests/ia32.rb +80 -26
- data/tests/mcs51.rb +27 -0
- data/tests/mips.rb +10 -3
- data/tests/preprocessor.rb +18 -0
- data/tests/x86_64.rb +66 -18
- metadata +465 -219
- metadata.gz.sig +2 -0
- 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 -872
- 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
@@ -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
|
@@ -214,8 +214,14 @@ class ExeFormat
|
|
214
214
|
|
215
215
|
raise EncodeError, "cannot find candidate in #{elem.inspect}, immediate too big #{wantsize.inspect} #{target_bounds.inspect}" if acceptable.empty?
|
216
216
|
|
217
|
-
# keep the shortest
|
218
|
-
|
217
|
+
# keep the shortest, use a hack make sort consistent in all cases
|
218
|
+
# see https://8thlight.com/blog/will-warner/2013/03/26/stable-sorting-in-ruby.html
|
219
|
+
n = 0
|
220
|
+
mod_map = acceptable.map { |edata| n += 1 ; [[edata.virtsize, n], edata] }
|
221
|
+
interm_sort = mod_map.sort { |left, right| left[0] <=> right[0] }
|
222
|
+
mod_sort_result = interm_sort.collect { |edata| edata[1] }
|
223
|
+
result = mod_sort_result.first
|
224
|
+
result
|
219
225
|
else
|
220
226
|
elem
|
221
227
|
end
|
@@ -271,7 +277,16 @@ class Expression
|
|
271
277
|
def encode(type, endianness, backtrace=nil)
|
272
278
|
case val = reduce
|
273
279
|
when Integer; EncodedData.new Expression.encode_imm(val, type, endianness, backtrace)
|
274
|
-
else
|
280
|
+
else
|
281
|
+
str = case INT_SIZE[type]
|
282
|
+
when 8; "\0"
|
283
|
+
when 16; "\0\0"
|
284
|
+
when 32; "\0\0\0\0"
|
285
|
+
when 64; "\0\0\0\0\0\0\0\0"
|
286
|
+
else [0].pack('C')*(INT_SIZE[type]/8)
|
287
|
+
end
|
288
|
+
str = str.force_encoding('BINARY') if str.respond_to?(:force_encoding)
|
289
|
+
EncodedData.new(str, :reloc => {0 => Relocation.new(self, type, endianness, backtrace)})
|
275
290
|
end
|
276
291
|
end
|
277
292
|
|
@@ -58,7 +58,7 @@ class AOut < ExeFormat
|
|
58
58
|
class Relocation < SerialStruct
|
59
59
|
word :address
|
60
60
|
bitfield :word, 0 => :symbolnum, 24 => :pcrel, 25 => :length,
|
61
|
-
|
61
|
+
27 => :extern, 28 => :baserel, 29 => :jmptable, 30 => :relative, 31 => :rtcopy
|
62
62
|
fld_enum :length, 0 => 1, 1 => 2, 2 => 4, 3 => 8
|
63
63
|
fld_default :length, 4
|
64
64
|
end
|
@@ -68,7 +68,7 @@ class AOut < ExeFormat
|
|
68
68
|
bitfield :byte, 0 => :extern, 1 => :type, 5 => :stab
|
69
69
|
byte :other
|
70
70
|
half :desc
|
71
|
-
|
71
|
+
word :value
|
72
72
|
attr_accessor :name
|
73
73
|
|
74
74
|
def decode(aout, strings=nil)
|
@@ -93,6 +93,9 @@ class AOut < ExeFormat
|
|
93
93
|
def encode_byte(w) Expression[w].encode(:u8 , @endianness) end
|
94
94
|
def encode_half(w) Expression[w].encode(:u16, @endianness) end
|
95
95
|
def encode_word(w) Expression[w].encode(:u32, @endianness) end
|
96
|
+
def sizeof_byte ; 1 ; end
|
97
|
+
def sizeof_half ; 2 ; end
|
98
|
+
def sizeof_word ; 4 ; end
|
96
99
|
|
97
100
|
def initialize(cpu = nil)
|
98
101
|
@endianness = cpu ? cpu.endianness : :little
|
@@ -119,11 +122,11 @@ class AOut < ExeFormat
|
|
119
122
|
|
120
123
|
@data = EncodedData.new << @encoded.read(@header.data)
|
121
124
|
|
122
|
-
textrel = @encoded.read @header.trsz
|
123
|
-
datarel = @encoded.read @header.drsz
|
124
|
-
syms = @encoded.read @header.syms
|
125
|
-
strings = @encoded.read
|
126
125
|
# TODO
|
126
|
+
#textrel = @encoded.read @header.trsz
|
127
|
+
#datarel = @encoded.read @header.drsz
|
128
|
+
#syms = @encoded.read @header.syms
|
129
|
+
#strings = @encoded.read
|
127
130
|
end
|
128
131
|
|
129
132
|
def encode
|
@@ -37,6 +37,7 @@ end
|
|
37
37
|
|
38
38
|
# register a new binary file signature
|
39
39
|
def self.register_signature(sig, exe=nil, &b)
|
40
|
+
sig.force_encoding('binary') if sig.respond_to?(:force_encoding)
|
40
41
|
(@signatures ||= []) << [sig, exe || b]
|
41
42
|
end
|
42
43
|
|
@@ -58,6 +59,8 @@ register_signature("\xca\xfe\xba\xbe") { UniversalBinary }
|
|
58
59
|
register_signature("dex\n") { DEX }
|
59
60
|
register_signature("dey\n") { DEY }
|
60
61
|
register_signature("\xfa\x70\x0e\x1f") { FatELF }
|
62
|
+
register_signature("\x50\x4b\x03\x04") { ZIP }
|
63
|
+
register_signature("\0asm") { WasmFile }
|
61
64
|
register_signature('Metasm.dasm') { Disassembler }
|
62
65
|
|
63
66
|
# replacement for AutoExe where #load defaults to a Shellcode of the specified CPU
|
@@ -9,6 +9,7 @@ require 'metasm/decode'
|
|
9
9
|
|
10
10
|
module Metasm
|
11
11
|
# BFLT is the binary flat format used by the uClinux
|
12
|
+
# from examining a v4 binary, it looks like the header is discarded and the file is mapped from 0x40 to memory address 0 (wrt relocations)
|
12
13
|
class Bflt < ExeFormat
|
13
14
|
MAGIC = 'bFLT'
|
14
15
|
FLAGS = { 1 => 'RAM', 2 => 'GOTPIC', 4 => 'GZIP' }
|
@@ -29,13 +30,20 @@ class Bflt < ExeFormat
|
|
29
30
|
when MAGIC
|
30
31
|
else raise InvalidExeFormat, "Bad bFLT signature #@magic"
|
31
32
|
end
|
33
|
+
|
34
|
+
if @rev >= 0x01000000 and (@rev & 0x00f0ffff) == 0
|
35
|
+
puts "Bflt: probable wrong endianness, retrying" if $VERBOSE
|
36
|
+
exe.endianness = { :big => :little, :little => :big }[exe.endianness]
|
37
|
+
exe.encoded.ptr -= 4*16
|
38
|
+
super(exe)
|
39
|
+
end
|
32
40
|
end
|
33
41
|
|
34
42
|
def set_default_values(exe)
|
35
43
|
@magic ||= MAGIC
|
36
44
|
@rev ||= 4
|
37
45
|
@entry ||= 0x40
|
38
|
-
@data_start ||=
|
46
|
+
@data_start ||= 0x40 + exe.text.length if exe.text
|
39
47
|
@data_end ||= @data_start + exe.data.data.length if exe.data
|
40
48
|
@bss_end ||= @data_start + exe.data.length if exe.data
|
41
49
|
@stack_size ||= 0x1000
|
@@ -49,7 +57,9 @@ class Bflt < ExeFormat
|
|
49
57
|
|
50
58
|
def decode_word(edata = @encoded) edata.decode_imm(:u32, @endianness) end
|
51
59
|
def encode_word(w) Expression[w].encode(:u32, @endianness) end
|
60
|
+
def sizeof_word ; 4 ; end
|
52
61
|
|
62
|
+
attr_accessor :endianness
|
53
63
|
def initialize(cpu = nil)
|
54
64
|
@endianness = cpu ? cpu.endianness : :little
|
55
65
|
@header = Header.new
|
@@ -61,17 +71,17 @@ class Bflt < ExeFormat
|
|
61
71
|
def decode_header
|
62
72
|
@encoded.ptr = 0
|
63
73
|
@header.decode(self)
|
74
|
+
@encoded.add_export(new_label('entrypoint'), @header.entry)
|
64
75
|
end
|
65
76
|
|
66
77
|
def decode
|
67
78
|
decode_header
|
68
79
|
|
69
|
-
@
|
70
|
-
@
|
71
|
-
@data
|
72
|
-
@data.virtsize += (@header.bss_end - @header.data_end)
|
80
|
+
@text = @encoded[0x40...@header.data_start]
|
81
|
+
@data = @encoded[@header.data_start...@header.data_end]
|
82
|
+
@data.virtsize += @header.bss_end - @header.data_end
|
73
83
|
|
74
|
-
if @header.flags.include?
|
84
|
+
if @header.flags.include?('GZIP')
|
75
85
|
# TODO gzip
|
76
86
|
raise 'bFLT decoder: gzip format not supported'
|
77
87
|
end
|
@@ -79,7 +89,7 @@ class Bflt < ExeFormat
|
|
79
89
|
@reloc = []
|
80
90
|
@encoded.ptr = @header.reloc_start
|
81
91
|
@header.reloc_count.times { @reloc << decode_word }
|
82
|
-
if @header.
|
92
|
+
if @header.rev == 2
|
83
93
|
@reloc.map! { |r| r & 0x3fff_ffff }
|
84
94
|
end
|
85
95
|
|
@@ -87,32 +97,29 @@ class Bflt < ExeFormat
|
|
87
97
|
end
|
88
98
|
|
89
99
|
def decode_interpret_relocs
|
100
|
+
textsz = @header.data_start-0x40
|
90
101
|
@reloc.each { |r|
|
91
102
|
# where the reloc is
|
92
|
-
if r
|
103
|
+
if r < textsz
|
93
104
|
section = @text
|
94
|
-
|
95
|
-
elsif r >= @header.data_start and r < @header.data_end
|
96
|
-
section = @data
|
97
|
-
base = @header.data_start
|
105
|
+
off = section.ptr = r
|
98
106
|
else
|
99
|
-
|
100
|
-
|
107
|
+
section = @data
|
108
|
+
off = section.ptr = r-textsz
|
101
109
|
end
|
102
110
|
|
103
111
|
# what it points to
|
104
|
-
section.ptr = r-base
|
105
112
|
target = decode_word(section)
|
106
|
-
if target
|
107
|
-
target = label_at(@text, target
|
108
|
-
elsif target
|
109
|
-
target = label_at(@data, target
|
113
|
+
if target < textsz
|
114
|
+
target = label_at(@text, target, "xref_#{Expression[target]}")
|
115
|
+
elsif target < @header.bss_end-0x40
|
116
|
+
target = label_at(@data, target-textsz, "xref_#{Expression[target]}")
|
110
117
|
else
|
111
|
-
puts "out of bounds reloc target at #{Expression[r]}" if $VERBOSE
|
118
|
+
puts "out of bounds reloc target #{Expression[target]} at #{Expression[r]}" if $VERBOSE
|
112
119
|
next
|
113
120
|
end
|
114
121
|
|
115
|
-
|
122
|
+
section.reloc[off] = Relocation.new(Expression[target], :u32, @endianness)
|
116
123
|
}
|
117
124
|
end
|
118
125
|
|
@@ -127,8 +134,8 @@ class Bflt < ExeFormat
|
|
127
134
|
|
128
135
|
@encoded = EncodedData.new
|
129
136
|
@encoded << @header.encode(self)
|
130
|
-
|
131
|
-
binding = @text.binding(
|
137
|
+
|
138
|
+
binding = @text.binding(0x40).merge(@data.binding(@header.data_start))
|
132
139
|
@encoded << @text << @data.data
|
133
140
|
@encoded.fixup! binding
|
134
141
|
@encoded.reloc.clear
|
@@ -143,7 +150,7 @@ class Bflt < ExeFormat
|
|
143
150
|
mapaddr = new_label('mapaddr')
|
144
151
|
binding = @text.binding(mapaddr).merge(@data.binding(mapaddr))
|
145
152
|
[@text, @data].each { |section|
|
146
|
-
base =
|
153
|
+
base = 0x40 # XXX maybe 0 ?
|
147
154
|
base = @header.data_start || base+@text.length if section == @data
|
148
155
|
section.reloc.each { |o, r|
|
149
156
|
if r.endianness == @endianness and [:u32, :a32, :i32].include? r.type and
|
@@ -167,7 +174,16 @@ class Bflt < ExeFormat
|
|
167
174
|
case instr.raw.downcase
|
168
175
|
when '.text'; @cursource = @textsrc
|
169
176
|
when '.data'; @cursource = @datasrc
|
170
|
-
|
177
|
+
when '.entrypoint'
|
178
|
+
# ".entrypoint <somelabel/expression>" or ".entrypoint" (here)
|
179
|
+
@lexer.skip_space
|
180
|
+
if tok = @lexer.nexttok and tok.type == :string
|
181
|
+
raise instr if not entrypoint = Expression.parse(@lexer)
|
182
|
+
else
|
183
|
+
entrypoint = new_label('entrypoint')
|
184
|
+
@cursource << Label.new(entrypoint, instr.backtrace.dup)
|
185
|
+
end
|
186
|
+
@header.entry = entrypoint
|
171
187
|
else super(instr)
|
172
188
|
end
|
173
189
|
end
|
@@ -181,9 +197,23 @@ class Bflt < ExeFormat
|
|
181
197
|
self
|
182
198
|
end
|
183
199
|
|
200
|
+
def get_default_entrypoints
|
201
|
+
['entrypoint']
|
202
|
+
end
|
203
|
+
|
184
204
|
def each_section
|
185
|
-
yield @text,
|
186
|
-
yield @data, @header.data_start
|
205
|
+
yield @text, 0
|
206
|
+
yield @data, @header.data_start - @header.entry
|
207
|
+
end
|
208
|
+
|
209
|
+
def section_info
|
210
|
+
[['.text', 0, @text.length, 'rx'],
|
211
|
+
['.data', @header.data_addr-0x40, @data.data.length, 'rw'],
|
212
|
+
['.bss', @header.data_end-0x40, @data.length-@data.data.length, 'rw']]
|
213
|
+
end
|
214
|
+
|
215
|
+
def module_symbols
|
216
|
+
['entrypoint', @header.entry-0x40]
|
187
217
|
end
|
188
218
|
end
|
189
219
|
end
|
@@ -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',
|
@@ -81,7 +83,7 @@ class COFF < ExeFormat
|
|
81
83
|
11 => 'UNION_MEMBER', 12 => 'UNION_TAG', 13 => 'TYPEDEF', 14 => 'UNDEF_STATIC',
|
82
84
|
15 => 'ENUM_TAG', 16 => 'ENUM_MEMBER', 17 => 'REG_PARAM', 18 => 'BIT_FIELD',
|
83
85
|
100 => 'BLOCK', 101 => 'FUNCTION', 102 => 'END_STRUCT',
|
84
|
-
|
86
|
+
103 => 'FILE', 104 => 'SECTION', 105 => 'WEAK_EXT',
|
85
87
|
}
|
86
88
|
|
87
89
|
DEBUG_TYPE = { 0 => 'UNKNOWN', 1 => 'COFF', 2 => 'CODEVIEW', 3 => 'FPO', 4 => 'MISC',
|
@@ -140,7 +142,7 @@ class COFF < ExeFormat
|
|
140
142
|
bytes :link_ver_maj, :link_ver_min
|
141
143
|
words :code_size, :data_size, :udata_size, :entrypoint, :base_of_code
|
142
144
|
# base_of_data does not exist in 64-bit
|
143
|
-
new_field(:base_of_data, lambda { |exe, hdr| exe.decode_word if exe.bitsize != 64 }, lambda { |exe, hdr, val| exe.encode_word(val) if exe.bitsize != 64 }, 0)
|
145
|
+
new_field(:base_of_data, lambda { |exe, hdr| exe.decode_word if exe.bitsize != 64 }, lambda { |exe, hdr, val| exe.encode_word(val) if exe.bitsize != 64 }, lambda { |exe, hdr| exe.bitsize != 64 ? 4 : 0 }, 0)
|
144
146
|
# NT-specific fields
|
145
147
|
xword :image_base
|
146
148
|
words :sect_align, :file_align
|
@@ -211,7 +213,7 @@ class COFF < ExeFormat
|
|
211
213
|
end
|
212
214
|
|
213
215
|
# tree-like structure, holds all misc data the program might need (icons, cursors, version information)
|
214
|
-
#
|
216
|
+
# conventionally structured in a 3-level depth structure:
|
215
217
|
# I resource type (icon/cursor/etc, see +TYPES+)
|
216
218
|
# II resource id (icon n1, icon 'toto', ...)
|
217
219
|
# III language-specific version (icon n1 en, icon n1 en-dvorak...)
|
@@ -228,6 +230,12 @@ class COFF < ExeFormat
|
|
228
230
|
end
|
229
231
|
end
|
230
232
|
|
233
|
+
# unwind info
|
234
|
+
class ExceptionEntry < SerialStruct
|
235
|
+
# function start RVA, function end RVA, UNWIND_INFO RVA
|
236
|
+
words :func, :func_end, :unwind
|
237
|
+
end
|
238
|
+
|
231
239
|
# array of relocations to apply to an executable file
|
232
240
|
# when it is loaded at an address that is not its preferred_base_address
|
233
241
|
class RelocationTable < SerialStruct
|
@@ -256,15 +264,26 @@ class COFF < ExeFormat
|
|
256
264
|
end
|
257
265
|
|
258
266
|
class RSDS < SerialStruct
|
259
|
-
|
267
|
+
word :guid_03
|
268
|
+
halfs :guid_45, :guid_67
|
269
|
+
bytes :guid_8, :guid_9, :guid_a, :guid_b, :guid_c, :guid_d, :guid_e, :guid_f
|
260
270
|
word :age
|
261
271
|
strz :pdbfilename
|
272
|
+
|
273
|
+
def guid
|
274
|
+
"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X" % [guid_03, guid_45, guid_67, guid_8, guid_9, guid_a, guid_b, guid_c, guid_d, guid_e, guid_f]
|
275
|
+
end
|
276
|
+
|
277
|
+
# http path to pdb (compressed)
|
278
|
+
def msdl_url
|
279
|
+
"http://msdl.microsoft.com/download/symbols/#{pdbfilename}/#{guid.delete("-")}#{age}/#{pdbfilename.chop}_"
|
280
|
+
end
|
262
281
|
end
|
263
282
|
end
|
264
283
|
|
265
284
|
class TLSDirectory < SerialStruct
|
266
285
|
xwords :start_va, :end_va, :index_addr, :callback_p
|
267
|
-
|
286
|
+
words :zerofill_sz, :characteristics
|
268
287
|
|
269
288
|
attr_accessor :callbacks
|
270
289
|
end
|
@@ -394,7 +413,8 @@ class COFF < ExeFormat
|
|
394
413
|
end
|
395
414
|
|
396
415
|
attr_accessor :header, :optheader, :directory, :sections, :endianness, :symbols, :bitsize,
|
397
|
-
:export, :imports, :resource, :
|
416
|
+
:export, :imports, :resource, :exception_table, :certificates,
|
417
|
+
:relocations, :debug, :tls, :loadconfig, :delayimports, :com_header
|
398
418
|
|
399
419
|
# boolean, set to true to have #decode() ignore the base_relocs directory
|
400
420
|
attr_accessor :nodecode_relocs
|
@@ -413,6 +433,11 @@ class COFF < ExeFormat
|
|
413
433
|
end
|
414
434
|
|
415
435
|
def shortname; 'coff'; end
|
436
|
+
|
437
|
+
def sizeof_byte ; 1 ; end
|
438
|
+
def sizeof_half ; 2 ; end
|
439
|
+
def sizeof_word ; 4 ; end
|
440
|
+
def sizeof_xword ; @bitsize == 32 ? 4 : 8 ; end
|
416
441
|
end
|
417
442
|
|
418
443
|
# the COFF archive file format
|
@@ -448,6 +473,9 @@ class COFFArchive < ExeFormat
|
|
448
473
|
def member(name)
|
449
474
|
@members.find { |m| m.name == name }
|
450
475
|
end
|
476
|
+
|
477
|
+
def sizeof_half ; 2 ; end
|
478
|
+
def sizeof_word ; 4 ; end
|
451
479
|
end
|
452
480
|
end
|
453
481
|
|
@@ -17,13 +17,15 @@ class COFF
|
|
17
17
|
# decodes a COFF optional header from coff.cursection
|
18
18
|
# also decodes directories in coff.directory
|
19
19
|
def decode(coff)
|
20
|
-
return set_default_values(coff) if coff.header.size_opthdr == 0
|
20
|
+
return set_default_values(coff) if coff.header.size_opthdr == 0 and not coff.header.characteristics.include?('EXECUTABLE_IMAGE')
|
21
|
+
off = coff.curencoded.ptr
|
21
22
|
super(coff)
|
23
|
+
nrva = (coff.header.size_opthdr - (coff.curencoded.ptr - off)) / 8
|
24
|
+
nrva = @numrva if nrva < 0
|
22
25
|
|
23
|
-
nrva
|
24
|
-
|
25
|
-
|
26
|
-
nrva = DIRECTORIES.length
|
26
|
+
if nrva > DIRECTORIES.length or nrva != @numrva
|
27
|
+
puts "W: COFF: Weird directories count #{@numrva}" if $VERBOSE
|
28
|
+
nrva = DIRECTORIES.length if nrva > DIRECTORIES.length
|
27
29
|
end
|
28
30
|
|
29
31
|
coff.directory = {}
|
@@ -64,7 +66,7 @@ class COFF
|
|
64
66
|
class RelocObj
|
65
67
|
def decode(coff)
|
66
68
|
super(coff)
|
67
|
-
@sym = coff.symbols[@symidx]
|
69
|
+
@sym = coff.symbols[@symidx] if coff.symbols
|
68
70
|
end
|
69
71
|
end
|
70
72
|
|
@@ -87,7 +89,7 @@ class COFF
|
|
87
89
|
addr = addrs[i]
|
88
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)
|
89
91
|
name = coff.decode_strz
|
90
|
-
e.forwarder_lib, name = name.split('.', 2)
|
92
|
+
e.forwarder_lib, name = name.split('.', 2) if name.index('.')
|
91
93
|
if name[0] == ?#
|
92
94
|
e.forwarder_ordinal = name[1..-1].to_i
|
93
95
|
else
|
@@ -109,6 +111,7 @@ class COFF
|
|
109
111
|
end
|
110
112
|
if namep and ords
|
111
113
|
namep.zip(ords).each { |np, oi|
|
114
|
+
next if not @exports[oi]
|
112
115
|
@exports[oi].name_p = np
|
113
116
|
if coff.sect_at_rva(np)
|
114
117
|
@exports[oi].name = coff.decode_strz
|
@@ -171,17 +174,17 @@ class COFF
|
|
171
174
|
end
|
172
175
|
|
173
176
|
class ResourceDirectory
|
174
|
-
def decode(coff, edata = coff.curencoded, startptr = edata.ptr)
|
177
|
+
def decode(coff, edata = coff.curencoded, startptr = edata.ptr, maxdepth=3)
|
175
178
|
super(coff, edata)
|
176
179
|
|
177
180
|
@entries = []
|
178
181
|
|
179
182
|
nrnames = @nr_names if $DEBUG
|
180
183
|
(@nr_names+@nr_id).times {
|
181
|
-
|
184
|
+
e = Entry.new
|
182
185
|
|
183
|
-
|
184
|
-
|
186
|
+
e_id = coff.decode_word(edata)
|
187
|
+
e_ptr = coff.decode_word(edata)
|
185
188
|
|
186
189
|
if not e_id.kind_of? Integer or not e_ptr.kind_of? Integer
|
187
190
|
puts 'W: COFF: relocs in the rsrc directory?' if $VERBOSE
|
@@ -213,10 +216,12 @@ class COFF
|
|
213
216
|
e.subdir_p = e_ptr & 0x7fff_ffff
|
214
217
|
if startptr + e.subdir_p >= edata.length
|
215
218
|
puts 'W: COFF: invalid resource structure: directory too far' if $VERBOSE
|
216
|
-
|
219
|
+
elsif maxdepth > 0
|
217
220
|
edata.ptr = startptr + e.subdir_p
|
218
221
|
e.subdir = ResourceDirectory.new
|
219
|
-
e.subdir.decode coff, edata, startptr
|
222
|
+
e.subdir.decode coff, edata, startptr, maxdepth-1
|
223
|
+
else
|
224
|
+
puts 'W: COFF: recursive resource section' if $VERBOSE
|
220
225
|
end
|
221
226
|
else
|
222
227
|
e.dataentry_p = e_ptr
|
@@ -244,7 +249,8 @@ class COFF
|
|
244
249
|
|
245
250
|
decode_tllv = lambda { |ed, state|
|
246
251
|
sptr = ed.ptr
|
247
|
-
len, vlen
|
252
|
+
len, vlen = coff.decode_half(ed), coff.decode_half(ed)
|
253
|
+
coff.decode_half(ed) # type
|
248
254
|
tagname = ''
|
249
255
|
while c = coff.decode_half(ed) and c != 0
|
250
256
|
tagname << (c&255)
|
@@ -273,7 +279,7 @@ class COFF
|
|
273
279
|
when :str
|
274
280
|
val = ed.read(vlen*2).unpack('v*')
|
275
281
|
val.pop if val[-1] == 0
|
276
|
-
val = val.pack('C*') if val.all? { |c_| c_ > 0 and c_ < 256 }
|
282
|
+
val = val.pack('C*') if val.all? { |c_| c_ > 0 and c_ < 256 }
|
277
283
|
vers[tagname] = val
|
278
284
|
when :var
|
279
285
|
val = ed.read(vlen).unpack('V*')
|
@@ -424,10 +430,9 @@ class COFF
|
|
424
430
|
# may return self when rva points to the coff header
|
425
431
|
# returns nil if none match, 0 never matches
|
426
432
|
def sect_at_rva(rva)
|
427
|
-
return if not rva or rva <= 0
|
433
|
+
return if not rva or not rva.kind_of?(::Integer) or rva <= 0
|
428
434
|
if sections and not @sections.empty?
|
429
|
-
|
430
|
-
if s = @sections.find { |s_| s_.virtaddr <= rva and s_.virtaddr + valign[s_.virtsize] > rva }
|
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 }
|
431
436
|
s.encoded.ptr = rva - s.virtaddr
|
432
437
|
@cursection = s
|
433
438
|
elsif rva < @sections.map { |s_| s_.virtaddr }.min
|
@@ -479,7 +484,7 @@ class COFF
|
|
479
484
|
end
|
480
485
|
|
481
486
|
def each_section
|
482
|
-
if @header.size_opthdr == 0
|
487
|
+
if @header.size_opthdr == 0 and not @header.characteristics.include?('EXECUTABLE_IMAGE')
|
483
488
|
@sections.each { |s|
|
484
489
|
next if not s.encoded
|
485
490
|
l = new_label(s.name)
|
@@ -490,7 +495,9 @@ class COFF
|
|
490
495
|
end
|
491
496
|
base = @optheader.image_base
|
492
497
|
base = 0 if not base.kind_of? Integer
|
493
|
-
|
498
|
+
sz = @optheader.headers_size
|
499
|
+
sz = EncodedData.align_size(@optheader.image_size, 4096) if @sections.empty?
|
500
|
+
yield @encoded[0, sz], base
|
494
501
|
@sections.each { |s| yield s.encoded, base + s.virtaddr }
|
495
502
|
end
|
496
503
|
|
@@ -545,6 +552,7 @@ class COFF
|
|
545
552
|
s.relocnr.times { s.relocs << RelocObj.decode(self) }
|
546
553
|
new_label 'pcrel'
|
547
554
|
s.relocs.each { |r|
|
555
|
+
next if not r.sym
|
548
556
|
case r.type
|
549
557
|
when 'DIR32'
|
550
558
|
s.encoded.reloc[r.va] = Metasm::Relocation.new(Expression[r.sym.name], :u32, @endianness)
|
@@ -566,8 +574,10 @@ class COFF
|
|
566
574
|
# decodes a section content (allows simpler LoadedPE override)
|
567
575
|
def decode_section_body(s)
|
568
576
|
raw = EncodedData.align_size(s.rawsize, @optheader.file_align)
|
569
|
-
virt =
|
577
|
+
virt = s.virtsize
|
570
578
|
virt = raw = s.rawsize if @header.size_opthdr == 0
|
579
|
+
virt = raw if virt == 0
|
580
|
+
virt = EncodedData.align_size(virt, @optheader.sect_align)
|
571
581
|
s.encoded = @encoded[s.rawaddr, [raw, virt].min] || EncodedData.new
|
572
582
|
s.encoded.virtsize = virt
|
573
583
|
end
|
@@ -629,13 +639,29 @@ class COFF
|
|
629
639
|
resource.decode_version(self, lang)
|
630
640
|
end
|
631
641
|
|
642
|
+
# decode the exception table, holding the start and end of every function in the binary (x64)
|
643
|
+
# includes a pointer to the UNWIND_INFO structure for exception handling
|
644
|
+
def decode_exception_table
|
645
|
+
if et = @directory['exception_table'] and sect_at_rva(et[0])
|
646
|
+
@exception_table = []
|
647
|
+
(et[1]/12).times {
|
648
|
+
@exception_table << ExceptionEntry.decode(self)
|
649
|
+
}
|
650
|
+
end
|
651
|
+
end
|
652
|
+
|
632
653
|
# decodes certificate table
|
633
654
|
def decode_certificates
|
634
655
|
if ct = @directory['certificate_table']
|
635
656
|
@certificates = []
|
636
657
|
@cursection = self
|
658
|
+
if ct[0] > @encoded.length or ct[1] > @encoded.length - ct[0]
|
659
|
+
puts "W: COFF: invalid certificate_table #{'0x%X+0x%0X' % ct}" if $VERBOSE
|
660
|
+
ct = [ct[0], 1]
|
661
|
+
end
|
637
662
|
@encoded.ptr = ct[0]
|
638
663
|
off_end = ct[0]+ct[1]
|
664
|
+
off_end = @encoded.length if off_end > @encoded.length
|
639
665
|
while @encoded.ptr < off_end
|
640
666
|
certlen = decode_word
|
641
667
|
certrev = decode_half
|
@@ -704,6 +730,25 @@ class COFF
|
|
704
730
|
end
|
705
731
|
end
|
706
732
|
|
733
|
+
def decode_reloc_amd64(r)
|
734
|
+
case r.type
|
735
|
+
when 'ABSOLUTE'
|
736
|
+
when 'HIGHLOW'
|
737
|
+
addr = decode_word
|
738
|
+
if s = sect_at_va(addr)
|
739
|
+
label = label_at(s.encoded, s.encoded.ptr, "xref_#{Expression[addr]}")
|
740
|
+
Metasm::Relocation.new(Expression[label], :u32, @endianness)
|
741
|
+
end
|
742
|
+
when 'DIR64'
|
743
|
+
addr = decode_xword
|
744
|
+
if s = sect_at_va(addr)
|
745
|
+
label = label_at(s.encoded, s.encoded.ptr, "xref_#{Expression[addr]}")
|
746
|
+
Metasm::Relocation.new(Expression[label], :u64, @endianness)
|
747
|
+
end
|
748
|
+
else puts "W: COFF: Unsupported amd64 relocation #{r.inspect}" if $VERBOSE
|
749
|
+
end
|
750
|
+
end
|
751
|
+
|
707
752
|
def decode_debug
|
708
753
|
if dd = @directory['debug'] and sect_at_rva(dd[0])
|
709
754
|
@debug = []
|
@@ -719,11 +764,11 @@ class COFF
|
|
719
764
|
def decode_tls
|
720
765
|
if @directory['tls_table'] and sect_at_rva(@directory['tls_table'][0])
|
721
766
|
@tls = TLSDirectory.decode(self)
|
722
|
-
|
767
|
+
if s = sect_at_va(@tls.callback_p)
|
723
768
|
s.encoded.add_export 'tls_callback_table'
|
724
769
|
@tls.callbacks.each_with_index { |cb, i|
|
725
770
|
@tls.callbacks[i] = curencoded.add_export "tls_callback_#{i}" if sect_at_rva(cb)
|
726
|
-
|
771
|
+
}
|
727
772
|
end
|
728
773
|
end
|
729
774
|
end
|
@@ -748,6 +793,7 @@ class COFF
|
|
748
793
|
decode_exports
|
749
794
|
decode_imports
|
750
795
|
decode_resources
|
796
|
+
decode_exception_table
|
751
797
|
decode_certificates
|
752
798
|
decode_debug
|
753
799
|
decode_tls
|
@@ -815,6 +861,7 @@ class COFFArchive
|
|
815
861
|
ar.encoded.ptr += 1 if @size & 1 == 1
|
816
862
|
end
|
817
863
|
|
864
|
+
# TODO XXX are those actually used ?
|
818
865
|
def decode_half ; @encoded.decode_imm(:u16, :big) end
|
819
866
|
def decode_word ; @encoded.decode_imm(:u32, :big) end
|
820
867
|
|