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
@@ -51,7 +51,7 @@ class XCoff < ExeFormat
|
|
51
51
|
@nsec ||= xcoff.sections.size
|
52
52
|
@symptr ||= xcoff.symbols ? xcoff.new_label('symptr') : 0
|
53
53
|
@nsym ||= xcoff.symbols ? xcoff.symbols.length : 0
|
54
|
-
@opthdr ||= xcoff.optheader ?
|
54
|
+
@opthdr ||= xcoff.optheader ? xcoff.optheader.sizeof(xcoff) : 0
|
55
55
|
super(xcoff)
|
56
56
|
end
|
57
57
|
end
|
@@ -61,13 +61,9 @@ class XCoff < ExeFormat
|
|
61
61
|
xwords :tsize, :dsize, :bsize, :entry, :text_start, :data_start, :toc
|
62
62
|
halfs :snentry, :sntext, :sndata, :sntoc, :snloader, :snbss, :aligntext, :aligndata, :modtype, :cpu
|
63
63
|
xwords :maxstack, :maxdata
|
64
|
-
new_field(:res, lambda { |exe, me| exe.encoded.read(exe.intsize == 32 ? 8 : 120) }, lambda { |exe, me, val| val }, '')
|
64
|
+
new_field(:res, lambda { |exe, me| exe.encoded.read(exe.intsize == 32 ? 8 : 120) }, lambda { |exe, me, val| val }, lambda { |exe, me| exe.intsize == 32 ? 8 : 120 }, '')
|
65
65
|
|
66
66
|
|
67
|
-
def self.size(xcoff)
|
68
|
-
xcoff.intsize == 32 ? 2*2+7*4+10*2+2*4+2+8 : 2*2+7*8+10*2+2*8+2+120
|
69
|
-
end
|
70
|
-
|
71
67
|
def set_default_values(xcoff)
|
72
68
|
@vstamp ||= 1
|
73
69
|
@snentry ||= 1
|
@@ -99,12 +95,16 @@ class XCoff < ExeFormat
|
|
99
95
|
# basic immediates decoding functions
|
100
96
|
def decode_half( edata = @encoded) edata.decode_imm(:u16, @endianness) end
|
101
97
|
def decode_word( edata = @encoded) edata.decode_imm(:u32, @endianness) end
|
102
|
-
def decode_xhalf(edata = @encoded) edata.
|
98
|
+
def decode_xhalf(edata = @encoded) edata.decode_imm((@intsize == 32 ? :u16 : :u32), @endianness) end
|
103
99
|
def decode_xword(edata = @encoded) edata.decode_imm((@intsize == 32 ? :u32 : :u64), @endianness) end
|
104
100
|
def encode_half(w) Expression[w].encode(:u16, @endianness) end
|
105
101
|
def encode_word(w) Expression[w].encode(:u32, @endianness) end
|
106
102
|
def encode_xhalf(w) Expression[w].encode((@intsize == 32 ? :u16 : :u32), @endianness) end
|
107
103
|
def encode_xword(w) Expression[w].encode((@intsize == 32 ? :u32 : :u64), @endianness) end
|
104
|
+
def sizeof_half ; 2 ; end
|
105
|
+
def sizeof_word ; 4 ; end
|
106
|
+
def sizeof_xhalf ; @intsize == 32 ? 2 : 4 ; end
|
107
|
+
def sizeof_xword ; @intsize == 32 ? 4 : 8 ; end
|
108
108
|
|
109
109
|
|
110
110
|
attr_accessor :header, :segments, :relocs, :intsize, :endianness
|
@@ -0,0 +1,335 @@
|
|
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/exe_format/main'
|
7
|
+
require 'metasm/encode'
|
8
|
+
require 'metasm/decode'
|
9
|
+
begin
|
10
|
+
require 'zlib'
|
11
|
+
rescue LoadError
|
12
|
+
end
|
13
|
+
|
14
|
+
# generic ZIP file, may be an APK or JAR
|
15
|
+
# supports only a trivial subset of the whole ZIP specification
|
16
|
+
# single file archive
|
17
|
+
# deflate or no compression
|
18
|
+
# no encryption
|
19
|
+
# 32bit offsets/sizes
|
20
|
+
|
21
|
+
module Metasm
|
22
|
+
class ZIP < ExeFormat
|
23
|
+
MAGIC_LOCALHEADER = 0x04034b50
|
24
|
+
COMPRESSION_METHOD = { 0 => 'NONE', 1 => 'SHRUNK', 2 => 'REDUCE1', 3 => 'REDUCE2',
|
25
|
+
4 => 'REDUCE3', 5 => 'REDUCE4', 6 => 'IMPLODE', 7 => 'TOKENIZED',
|
26
|
+
8 => 'DEFLATE', 9 => 'DEFLATE64', 10 => 'OLDTERSE', 12 => 'BZIP2', 14 => 'LZMA',
|
27
|
+
18 => 'TERSE', 19 => 'LZ77', 97 => 'WAVPACK', 98 => 'PPMD' }
|
28
|
+
|
29
|
+
# zip file format:
|
30
|
+
#
|
31
|
+
# [local header 1]
|
32
|
+
# compressed data 1
|
33
|
+
#
|
34
|
+
# [local header 2]
|
35
|
+
# compressed data 2
|
36
|
+
#
|
37
|
+
# [central header 1]
|
38
|
+
# [central header 2]
|
39
|
+
#
|
40
|
+
# [end of central directory]
|
41
|
+
|
42
|
+
class LocalHeader < SerialStruct
|
43
|
+
word :signature, MAGIC_LOCALHEADER
|
44
|
+
half :verneed, 10
|
45
|
+
half :flags # bit 3 => has data descriptor following the compressed data
|
46
|
+
half :compress_method, 0, COMPRESSION_METHOD
|
47
|
+
halfs :mtime, :mdate
|
48
|
+
word :crc32
|
49
|
+
words :compressed_sz, :uncompressed_sz
|
50
|
+
halfs :fname_len, :extra_len
|
51
|
+
attr_accessor :fname, :extra
|
52
|
+
attr_accessor :compressed_off
|
53
|
+
|
54
|
+
def decode(zip)
|
55
|
+
super(zip)
|
56
|
+
raise "Invalid ZIP signature #{@signature.to_s(16)}" if @signature != MAGIC_LOCALHEADER
|
57
|
+
@fname = zip.encoded.read(@fname_len) if @fname_len > 0
|
58
|
+
@extra = zip.encoded.read(@extra_len) if @extra_len > 0
|
59
|
+
@compressed_off = zip.encoded.ptr
|
60
|
+
end
|
61
|
+
|
62
|
+
def set_default_values(zip)
|
63
|
+
@fname_len = fname ? @fname.length : 0
|
64
|
+
@extra_len = extra ? @extra.length : 0
|
65
|
+
super(zip)
|
66
|
+
end
|
67
|
+
|
68
|
+
def encode(zip)
|
69
|
+
ed = super(zip)
|
70
|
+
ed << fname << extra
|
71
|
+
end
|
72
|
+
|
73
|
+
# return a new LocalHeader with all fields copied from a CentralHeader
|
74
|
+
def self.from_central(f)
|
75
|
+
l = new
|
76
|
+
l.verneed = f.verneed
|
77
|
+
l.flags = f.flags
|
78
|
+
l.compress_method = f.compress_method
|
79
|
+
l.mtime = f.mtime
|
80
|
+
l.mdate = f.mdate
|
81
|
+
l.crc32 = f.crc32
|
82
|
+
l.compressed_sz = f.compressed_sz
|
83
|
+
l.uncompressed_sz = f.uncompressed_sz
|
84
|
+
l.fname = f.fname
|
85
|
+
l.extra = f.extra
|
86
|
+
l
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
MAGIC_CENTRALHEADER = 0x02014b50
|
91
|
+
class CentralHeader < SerialStruct
|
92
|
+
word :signature, MAGIC_CENTRALHEADER
|
93
|
+
half :vermade, 10
|
94
|
+
half :verneed, 10
|
95
|
+
half :flags
|
96
|
+
half :compress_method, 0, COMPRESSION_METHOD
|
97
|
+
halfs :mtime, :mdate
|
98
|
+
word :crc32
|
99
|
+
words :compressed_sz, :uncompressed_sz
|
100
|
+
halfs :fname_len, :extra_len, :comment_len
|
101
|
+
half :disk_nr
|
102
|
+
half :file_attr_intern
|
103
|
+
word :file_attr_extern
|
104
|
+
word :localhdr_off
|
105
|
+
attr_accessor :fname, :extra, :comment
|
106
|
+
attr_accessor :data
|
107
|
+
|
108
|
+
def decode(zip)
|
109
|
+
super(zip)
|
110
|
+
raise "Invalid ZIP signature #{@signature.to_s(16)}" if @signature != MAGIC_CENTRALHEADER
|
111
|
+
@fname = zip.encoded.read(@fname_len) if @fname_len > 0
|
112
|
+
@extra = zip.encoded.read(@extra_len) if @extra_len > 0
|
113
|
+
@comment = zip.encoded.read(@comment_len) if @comment_len > 0
|
114
|
+
end
|
115
|
+
|
116
|
+
def set_default_values(zip)
|
117
|
+
@fname_len = fname ? @fname.length : 0
|
118
|
+
@extra_len = extra ? @extra.length : 0
|
119
|
+
@comment_len = comment ? @comment.length : 0
|
120
|
+
super(zip)
|
121
|
+
end
|
122
|
+
|
123
|
+
def encode(zip)
|
124
|
+
ed = super(zip)
|
125
|
+
ed << fname << extra << comment
|
126
|
+
end
|
127
|
+
|
128
|
+
# reads the raw file data from the archive
|
129
|
+
def file_data(zip)
|
130
|
+
return @data if data
|
131
|
+
|
132
|
+
zip.encoded.ptr = @localhdr_off
|
133
|
+
LocalHeader.decode(zip)
|
134
|
+
raw = zip.encoded.read(@compressed_sz)
|
135
|
+
@data = case @compress_method
|
136
|
+
when 'NONE'
|
137
|
+
raw
|
138
|
+
when 'DEFLATE'
|
139
|
+
z = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
140
|
+
z.inflate(raw)
|
141
|
+
else
|
142
|
+
raise "Unsupported zip compress method #@compress_method"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def zlib_deflate(data, level=Zlib::DEFAULT_COMPRESSION)
|
147
|
+
z = Zlib::Deflate.new(level, -Zlib::MAX_WBITS)
|
148
|
+
z.deflate(data) + z.finish
|
149
|
+
end
|
150
|
+
|
151
|
+
# encode the data, fixup related fields
|
152
|
+
def encode_data(zip)
|
153
|
+
data = file_data(zip)
|
154
|
+
@compress_method = 'NONE' if data == ''
|
155
|
+
|
156
|
+
@crc32 = Zlib.crc32(data)
|
157
|
+
@uncompressed_sz = data.length
|
158
|
+
|
159
|
+
case compress_method
|
160
|
+
when 'NONE'
|
161
|
+
when 'DEFLATE'
|
162
|
+
data = zlib_deflate(data)
|
163
|
+
when nil
|
164
|
+
# autodetect compression method
|
165
|
+
# compress if we win more than 10% space
|
166
|
+
cdata = zlib_deflate(data)
|
167
|
+
ratio = cdata.length * 100 / data.length
|
168
|
+
if ratio < 90
|
169
|
+
@compress_method = 'DEFLATE'
|
170
|
+
data = cdata
|
171
|
+
else
|
172
|
+
@compress_method = 'NONE'
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
@compressed_sz = data.length
|
177
|
+
|
178
|
+
data
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
MAGIC_ENDCENTRALDIRECTORY = 0x06054b50
|
183
|
+
class EndCentralDirectory < SerialStruct
|
184
|
+
word :signature, MAGIC_ENDCENTRALDIRECTORY
|
185
|
+
halfs :disk_nr, :disk_centraldir, :entries_nr_thisdisk, :entries_nr
|
186
|
+
word :directory_sz
|
187
|
+
word :directory_off
|
188
|
+
half :comment_len
|
189
|
+
attr_accessor :comment
|
190
|
+
|
191
|
+
def decode(zip)
|
192
|
+
super(zip)
|
193
|
+
raise "Invalid ZIP end signature #{@signature.to_s(16)}" if @signature != MAGIC_ENDCENTRALDIRECTORY
|
194
|
+
@comment = zip.encoded.read(@comment_len) if @comment_len > 0
|
195
|
+
end
|
196
|
+
|
197
|
+
def set_default_values(zip)
|
198
|
+
@entries_nr_thisdisk = zip.files.length
|
199
|
+
@entries_nr = zip.files.length
|
200
|
+
@comment_len = comment ? @comment.length : 0
|
201
|
+
super(zip)
|
202
|
+
end
|
203
|
+
|
204
|
+
def encode(zip)
|
205
|
+
ed = super(zip)
|
206
|
+
ed << comment
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def decode_half(edata=@encoded) edata.decode_imm(:u16, @endianness) end
|
211
|
+
def decode_word(edata=@encoded) edata.decode_imm(:u32, @endianness) end
|
212
|
+
def encode_half(w) Expression[w].encode(:u16, @endianness) end
|
213
|
+
def encode_word(w) Expression[w].encode(:u32, @endianness) end
|
214
|
+
def sizeof_half ; 2 ; end
|
215
|
+
def sizeof_word ; 4 ; end
|
216
|
+
|
217
|
+
attr_accessor :files, :header
|
218
|
+
|
219
|
+
def initialize(cpu = nil)
|
220
|
+
@endianness = :little
|
221
|
+
@header = EndCentralDirectory.new
|
222
|
+
@files = []
|
223
|
+
super(cpu)
|
224
|
+
end
|
225
|
+
|
226
|
+
# scan and decode the 'end of central directory' header
|
227
|
+
def decode_header
|
228
|
+
if not @encoded.ptr = @encoded.data.rindex([MAGIC_ENDCENTRALDIRECTORY].pack('V'))
|
229
|
+
raise "ZIP: no end of central directory record"
|
230
|
+
end
|
231
|
+
@header = EndCentralDirectory.decode(self)
|
232
|
+
end
|
233
|
+
|
234
|
+
# read the whole central directory file descriptors
|
235
|
+
def decode
|
236
|
+
decode_header
|
237
|
+
@encoded.ptr = @header.directory_off
|
238
|
+
while @encoded.ptr < @header.directory_off + @header.directory_sz
|
239
|
+
@files << CentralHeader.decode(self)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
# checks if a given file name exists in the archive
|
244
|
+
# returns the CentralHeader or nil
|
245
|
+
# case-insensitive if lcase is false
|
246
|
+
def has_file(fname, lcase=true)
|
247
|
+
decode if @files.empty?
|
248
|
+
if lcase
|
249
|
+
@files.find { |f| f.fname == fname }
|
250
|
+
else
|
251
|
+
fname = fname.downcase
|
252
|
+
@files.find { |f| f.fname.downcase == fname }
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
# returns the uncompressed raw file content from a given name
|
257
|
+
# nil if name not found
|
258
|
+
# case-insensitive if lcase is false
|
259
|
+
def file_data(fname, lcase=true)
|
260
|
+
if f = has_file(fname, lcase)
|
261
|
+
f.file_data(self)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
# add a new file to the zip archive
|
266
|
+
def add_file(fname, data, compress=:auto)
|
267
|
+
f = CentralHeader.new
|
268
|
+
|
269
|
+
case compress
|
270
|
+
when 'NONE', false; f.compress_method = 'NONE'
|
271
|
+
when 'DEFLATE', true; f.compress_method = 'DEFLATE'
|
272
|
+
end
|
273
|
+
|
274
|
+
f.fname = fname
|
275
|
+
f.data = data
|
276
|
+
|
277
|
+
@files << f
|
278
|
+
f
|
279
|
+
end
|
280
|
+
|
281
|
+
# create a new zip file
|
282
|
+
def encode
|
283
|
+
edata = EncodedData.new
|
284
|
+
central_dir = EncodedData.new
|
285
|
+
|
286
|
+
@files.each { |f|
|
287
|
+
encode_entry(f, edata, central_dir)
|
288
|
+
}
|
289
|
+
|
290
|
+
@header.directory_off = edata.length
|
291
|
+
@header.directory_sz = central_dir.length
|
292
|
+
|
293
|
+
edata << central_dir << @header.encode(self)
|
294
|
+
|
295
|
+
@encoded = edata
|
296
|
+
end
|
297
|
+
|
298
|
+
# add one file to the zip stream
|
299
|
+
def encode_entry(f, edata, central_dir)
|
300
|
+
f.localhdr_off = edata.length
|
301
|
+
|
302
|
+
# may autodetect compression method
|
303
|
+
raw = f.encode_data(self)
|
304
|
+
|
305
|
+
zipalign(f, edata)
|
306
|
+
|
307
|
+
central_dir << f.encode(self) # calls f.set_default_values
|
308
|
+
|
309
|
+
l = LocalHeader.from_central(f)
|
310
|
+
edata << l.encode(self)
|
311
|
+
|
312
|
+
edata << raw
|
313
|
+
end
|
314
|
+
|
315
|
+
# zipalign: ensure uncompressed data starts on a 4-aligned offset
|
316
|
+
def zipalign(f, edata)
|
317
|
+
if f.compress_method == 'NONE' and not f.extra
|
318
|
+
o = (edata.length + f.fname.length + 2) & 3
|
319
|
+
f.extra = " "*(4-o) if o > 0
|
320
|
+
end
|
321
|
+
|
322
|
+
end
|
323
|
+
|
324
|
+
# when called as AutoExe, try to find a meaningful exefmt
|
325
|
+
def self.autoexe_load(bin)
|
326
|
+
z = decode(bin)
|
327
|
+
if dex = z.file_data('classes.dex')
|
328
|
+
puts "ZIP: APK file, loading 'classes.dex'" if $VERBOSE
|
329
|
+
AutoExe.load(dex)
|
330
|
+
else
|
331
|
+
z
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
data/metasm/gui.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
backend = ENV['METASM_GUI'] || (
|
2
|
+
if RUBY_PLATFORM =~ /(i.86|x(86_)?64)-(mswin|mingw|cygwin)/i
|
3
|
+
'win32'
|
4
|
+
else
|
5
|
+
begin
|
6
|
+
require 'gtk2'
|
7
|
+
'gtk'
|
8
|
+
rescue LoadError
|
9
|
+
raise LoadError, 'No GUI ruby binding installed - please install ruby-gtk2'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
)
|
13
|
+
require "metasm/gui/#{backend}"
|
@@ -23,8 +23,7 @@ class CStructWidget < DrawableWidget
|
|
23
23
|
@cwidth = @cheight = 1 # widget size in chars
|
24
24
|
@structdepth = 2
|
25
25
|
|
26
|
-
@default_color_association =
|
27
|
-
:background => :white, :hl_word => :palered, :comment => :darkblue }
|
26
|
+
@default_color_association = ColorTheme.merge :keyword => :blue
|
28
27
|
end
|
29
28
|
|
30
29
|
def click(x, y)
|
@@ -90,19 +89,7 @@ class CStructWidget < DrawableWidget
|
|
90
89
|
elsif cx < @view_x
|
91
90
|
else
|
92
91
|
t = t[(@view_x - cx + t.length)..-1] if cx-t.length < @view_x
|
93
|
-
|
94
|
-
stmp = t
|
95
|
-
pre_x = 0
|
96
|
-
while stmp =~ /^(.*?)(\b#{Regexp.escape @hl_word}\b)/
|
97
|
-
s1, s2 = $1, $2
|
98
|
-
pre_x += s1.length*@font_width
|
99
|
-
hl_w = s2.length*@font_width
|
100
|
-
draw_rectangle_color(:hl_word, x+pre_x, y, hl_w, @font_height)
|
101
|
-
pre_x += hl_w
|
102
|
-
stmp = stmp[s1.length+s2.length..-1]
|
103
|
-
end
|
104
|
-
end
|
105
|
-
draw_string_color(c, x, y, t)
|
92
|
+
draw_string_hl(c, x, y, t)
|
106
93
|
x += t.length * @font_width
|
107
94
|
end
|
108
95
|
}
|
@@ -116,7 +103,7 @@ class CStructWidget < DrawableWidget
|
|
116
103
|
cy = (@caret_y-@view_y)*@font_height
|
117
104
|
draw_line_color(:caret, cx, cy, cx, cy+@font_height-1)
|
118
105
|
end
|
119
|
-
|
106
|
+
|
120
107
|
@oldcaret_x, @oldcaret_y = @caret_x, @caret_y
|
121
108
|
end
|
122
109
|
|
@@ -179,28 +166,31 @@ class CStructWidget < DrawableWidget
|
|
179
166
|
when ?l
|
180
167
|
liststructs
|
181
168
|
when ?t
|
182
|
-
inputbox('new struct name to use', :text => (@curstruct.name rescue '')) { |n|
|
183
|
-
lst = @dasm.c_parser.toplevel.struct.keys.grep(String)
|
184
|
-
if fn = lst.find { |ln| ln == n } || lst.find { |ln| ln.downcase == n.downcase }
|
185
|
-
focus_addr(@curaddr, @dasm.c_parser.toplevel.struct[fn])
|
186
|
-
else
|
187
|
-
lst = @dasm.c_parser.toplevel.symbol.keys.grep(String).find_all { |ln|
|
188
|
-
s = @dasm.c_parser.toplevel.symbol[ln]
|
189
|
-
s.kind_of?(C::TypeDef) and s.untypedef.kind_of?(C::Union)
|
190
|
-
}
|
191
|
-
if fn = lst.find { |ln| ln == n } || lst.find { |ln| ln.downcase == n.downcase }
|
192
|
-
focus_addr(@curaddr, @dasm.c_parser.toplevel.symbol[fn].untypedef)
|
193
|
-
else
|
194
|
-
liststructs(n)
|
195
|
-
end
|
196
|
-
end
|
197
|
-
}
|
169
|
+
inputbox('new struct name to use', :text => (@curstruct.name rescue '')) { |n| focus_struct_byname(n) }
|
198
170
|
else return false
|
199
171
|
end
|
200
172
|
true
|
201
173
|
end
|
202
174
|
|
203
|
-
|
175
|
+
# display the struct or pop a list of matching struct names if ambiguous
|
176
|
+
def focus_struct_byname(n, addr=@curaddr)
|
177
|
+
lst = @dasm.c_parser.toplevel.struct.keys.grep(String)
|
178
|
+
if fn = lst.find { |ln| ln == n } || lst.find { |ln| ln.downcase == n.downcase }
|
179
|
+
focus_addr(addr, @dasm.c_parser.toplevel.struct[fn])
|
180
|
+
else
|
181
|
+
lst = @dasm.c_parser.toplevel.symbol.keys.grep(String).find_all { |ln|
|
182
|
+
s = @dasm.c_parser.toplevel.symbol[ln]
|
183
|
+
s.kind_of?(C::TypeDef) and s.untypedef.kind_of?(C::Union)
|
184
|
+
}
|
185
|
+
if fn = lst.find { |ln| ln == n } || lst.find { |ln| ln.downcase == n.downcase }
|
186
|
+
focus_addr(addr, @dasm.c_parser.toplevel.symbol[fn].untypedef)
|
187
|
+
else
|
188
|
+
liststructs(n, addr)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def liststructs(partname=nil, addr=@curaddr)
|
204
194
|
tl = @dasm.c_parser.toplevel
|
205
195
|
list = [['name', 'size']]
|
206
196
|
list += tl.struct.keys.grep(String).sort.map { |stn|
|
@@ -216,12 +206,12 @@ class CStructWidget < DrawableWidget
|
|
216
206
|
}.compact
|
217
207
|
|
218
208
|
if partname and list.length == 2
|
219
|
-
focus_addr(
|
209
|
+
focus_addr(addr, tl.struct[list[1][0]] || tl.symbol[list[1][0]].untypedef)
|
220
210
|
return
|
221
211
|
end
|
222
212
|
|
223
213
|
listwindow('structs', list) { |stn|
|
224
|
-
focus_addr(
|
214
|
+
focus_addr(addr, tl.struct[stn[0]] || tl.symbol[stn[0]].untypedef)
|
225
215
|
}
|
226
216
|
end
|
227
217
|
|
@@ -240,7 +230,7 @@ class CStructWidget < DrawableWidget
|
|
240
230
|
def update_caret
|
241
231
|
if @caret_x < @view_x or @caret_x >= @view_x + @cwidth or @caret_y < @view_y or @caret_y >= @view_y + @cheight
|
242
232
|
redraw
|
243
|
-
elsif update_hl_word(@line_text[@caret_y], @caret_x)
|
233
|
+
elsif update_hl_word(@line_text[@caret_y], @caret_x, :c)
|
244
234
|
redraw
|
245
235
|
else
|
246
236
|
invalidate_caret(@oldcaret_x-@view_x, @oldcaret_y-@view_y)
|
@@ -254,9 +244,14 @@ class CStructWidget < DrawableWidget
|
|
254
244
|
def focus_addr(addr, struct=@curstruct)
|
255
245
|
return if @parent_widget and not addr = @parent_widget.normalize(addr)
|
256
246
|
@curaddr = addr
|
257
|
-
@curstruct = struct
|
258
247
|
@caret_x = @caret_y = 0
|
259
|
-
|
248
|
+
if struct.kind_of? String
|
249
|
+
@curstruct = nil
|
250
|
+
focus_struct_byname(struct)
|
251
|
+
else
|
252
|
+
@curstruct = struct
|
253
|
+
gui_update
|
254
|
+
end
|
260
255
|
true
|
261
256
|
end
|
262
257
|
|
@@ -278,7 +273,7 @@ class CStructWidget < DrawableWidget
|
|
278
273
|
@line_text_col << []
|
279
274
|
render[indent * [@structdepth - maxdepth, 0].max, :text]
|
280
275
|
}
|
281
|
-
|
276
|
+
|
282
277
|
if not obj
|
283
278
|
@line_text_col = [[]]
|
284
279
|
@line_dereference = []
|
@@ -308,7 +303,6 @@ class CStructWidget < DrawableWidget
|
|
308
303
|
elsif struct.kind_of?(C::Struct)
|
309
304
|
render["struct #{struct.name || '_'} st_#{Expression[@curaddr]} = ", :text] if not off
|
310
305
|
fldoff = struct.fldoffset
|
311
|
-
fbo = struct.fldbitoffset || {}
|
312
306
|
else
|
313
307
|
render["union #{struct.name || '_'} un_#{Expression[@curaddr]} = ", :text] if not off
|
314
308
|
end
|
@@ -363,7 +357,7 @@ class CStructWidget < DrawableWidget
|
|
363
357
|
else
|
364
358
|
@line_text_col = [[[:text, '/* no struct selected (list with "l") */']]]
|
365
359
|
end
|
366
|
-
|
360
|
+
|
367
361
|
@line_text = @line_text_col.map { |l| l.map { |c, s| s }.join }
|
368
362
|
update_caret
|
369
363
|
redraw
|