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
|
@@ -0,0 +1,15 @@
|
|
|
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
|
+
# metasm dasm plugin: asks to load a second program, and unleash the samples/bindiff fury
|
|
7
|
+
# usage: load the plugin, and a 2nd binary, disassemble functions in both, diff'em
|
|
8
|
+
|
|
9
|
+
require File.join(Metasm::Metasmdir, 'samples', 'bindiff.rb')
|
|
10
|
+
|
|
11
|
+
Gui::DasmWindow.new("bindiff target").promptopen("chose bindiff target") { |w|
|
|
12
|
+
w.title = "#{w.widget.dasm.program.filename} - metasm bindiff"
|
|
13
|
+
@bindiff_win = BinDiffWindow.new(self, w.widget.dasm)
|
|
14
|
+
}
|
|
15
|
+
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
|
2
|
+
# Copyright (C) 2006-2009 Yoann GUILLOT
|
|
3
|
+
#
|
|
4
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# metasm dasm GUI plugin:
|
|
8
|
+
# pops a list of bookmarked functions
|
|
9
|
+
# also allows the custom coloration of blocks/functions
|
|
10
|
+
|
|
11
|
+
if gui
|
|
12
|
+
class ColorWindow < Metasm::Gui::ToolWindow
|
|
13
|
+
def initialize_window(&b)
|
|
14
|
+
self.title = 'pick a color'
|
|
15
|
+
self.widget = ColorWidget.new(&b)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class ColorWidget < Metasm::Gui::DrawableWidget
|
|
20
|
+
attr_accessor :ph, :pw
|
|
21
|
+
def initialize_widget(&b)
|
|
22
|
+
super()
|
|
23
|
+
@action = b
|
|
24
|
+
@pw = 3
|
|
25
|
+
@ph = 8
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def initial_size
|
|
29
|
+
[@pw*256, @ph*16]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def paint
|
|
33
|
+
0x100.times { |x|
|
|
34
|
+
cx = x
|
|
35
|
+
if x & 0x10 > 0
|
|
36
|
+
cx = (x&0xf0) + (15-(x&0xf))
|
|
37
|
+
end
|
|
38
|
+
0x10.times { |y|
|
|
39
|
+
col = '%02x%x' % [cx, y]
|
|
40
|
+
draw_rectangle_color(col, x*@pw, y*@ph, @pw, @ph)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def xy_to_col(x, y)
|
|
46
|
+
x = x.to_i / @pw
|
|
47
|
+
y = y.to_i / @ph
|
|
48
|
+
if x >=0 and y >= 0 and x <= 0xff and y <= 0xf
|
|
49
|
+
if x & 0x10 > 0
|
|
50
|
+
x = (x&0xf0) + (15-(x&0xf))
|
|
51
|
+
end
|
|
52
|
+
col = '%02x%x' % [x, y]
|
|
53
|
+
toplevel.title = "color #{col}"
|
|
54
|
+
col
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def mousemove(x, y)
|
|
59
|
+
xy_to_col(x, y)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def mouserelease(x, y)
|
|
63
|
+
if c = xy_to_col(x, y)
|
|
64
|
+
toplevel.destroy
|
|
65
|
+
@action.call(c)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# list of user-specified addrs
|
|
71
|
+
@bookmarklist = []
|
|
72
|
+
# every single addr => color
|
|
73
|
+
@bookmarkcolor = {}
|
|
74
|
+
|
|
75
|
+
obg = gui.bg_color_callback # chain old callback
|
|
76
|
+
gui.bg_color_callback = lambda { |a|
|
|
77
|
+
if obg and col = obg[a]
|
|
78
|
+
col
|
|
79
|
+
else
|
|
80
|
+
# least priority
|
|
81
|
+
@bookmarkcolor[a]
|
|
82
|
+
end
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
popbookmarks = lambda { |*a|
|
|
86
|
+
list = [['address', 'color']] + @bookmarklist.map { |bm| [Expression[bm].to_s, @bookmarkcolor[bm].to_s] }
|
|
87
|
+
listcolcb = lambda { |e| [nil, @bookmarkcolor[Expression.parse_string(e[0]).reduce]] }
|
|
88
|
+
gui.listwindow('bookmarks', list, :color_callback => listcolcb) { |e| gui.focus_addr(e[0]) }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
# an api to bookmark a function
|
|
92
|
+
def bookmark_function(addr, color)
|
|
93
|
+
return if not fa = find_function_start(addr)
|
|
94
|
+
list = function_blocks(fa).map { |k, v| block_at(k).list.map { |di| di.address } }.flatten
|
|
95
|
+
bookmark_addrs list, color
|
|
96
|
+
end
|
|
97
|
+
def bookmark_addrs(list, color)
|
|
98
|
+
al = [list].flatten.uniq
|
|
99
|
+
gui.session_append("dasm.bookmark_addrs(#{list.inspect}, #{color.inspect})")
|
|
100
|
+
@bookmarklist |= [al.min]
|
|
101
|
+
al.each { |a| @bookmarkcolor[a] = color }
|
|
102
|
+
gui.gui_update
|
|
103
|
+
end
|
|
104
|
+
def bookmark_delete_function(addr)
|
|
105
|
+
return if not fa = find_function_start(addr)
|
|
106
|
+
list = function_blocks(fa).map { |k, v| block_at(k).list.map { |di| di.address } }.flatten
|
|
107
|
+
bookmark_delete list
|
|
108
|
+
end
|
|
109
|
+
def bookmark_delete(list)
|
|
110
|
+
@bookmarklist -= list
|
|
111
|
+
list.each { |a| @bookmarkcolor.delete a }
|
|
112
|
+
end
|
|
113
|
+
def bookmark_delete_color(col)
|
|
114
|
+
@bookmarkcolor.delete_if { |k, v| if v == col ; @bookmarklist.delete k ; true end }
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
w = gui.toplevel
|
|
119
|
+
w.addsubmenu(w.find_menu('Views'), '_Bookmarks', popbookmarks)
|
|
120
|
+
w.update_menu
|
|
121
|
+
gui.keyboard_callback[?B] = popbookmarks
|
|
122
|
+
gui.keyboard_callback[?C] = lambda { |a|
|
|
123
|
+
if s = gui.curview.instance_variable_get('@selected_boxes') and not s.empty?
|
|
124
|
+
al = s.map { |b| b[:line_address] }
|
|
125
|
+
elsif fa = find_function_start(gui.curaddr)
|
|
126
|
+
al = function_blocks(fa).map { |k, v| block_at(k).list.map { |di| di.address } }
|
|
127
|
+
else
|
|
128
|
+
next
|
|
129
|
+
end
|
|
130
|
+
# XXX also prompt for comment/bookmark name ?
|
|
131
|
+
ColorWindow.new(gui.toplevel) { |col| bookmark_addrs(al, col) }
|
|
132
|
+
}
|
|
133
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
|
2
|
+
# Copyright (C) 2006-2009 Yoann GUILLOT
|
|
3
|
+
#
|
|
4
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# metasm dasm plugin
|
|
8
|
+
# decompose immediate values from C constants, adds a comment with the decomposition
|
|
9
|
+
|
|
10
|
+
# find immediate exprs in the instruction at addr, yield them
|
|
11
|
+
def imm_to_const(addr)
|
|
12
|
+
return if not di = di_at(addr)
|
|
13
|
+
# TODO enter into memrefs ?
|
|
14
|
+
di.instruction.args.grep(Expression).each { |a|
|
|
15
|
+
i = a.reduce
|
|
16
|
+
next if not i.kind_of? Integer
|
|
17
|
+
next if not cstbase = yield(i)
|
|
18
|
+
if c = imm_to_const_decompose(i, cstbase)
|
|
19
|
+
di.add_comment c
|
|
20
|
+
end
|
|
21
|
+
}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# find the bitwise decomposition of imm into constants whose name include cstbase
|
|
25
|
+
def imm_to_const_decompose(imm, cstbase)
|
|
26
|
+
cstbase = /#{cstbase}/i if not cstbase.kind_of? Regexp
|
|
27
|
+
dict = {}
|
|
28
|
+
c_parser.lexer.definition.keys.grep(cstbase).each { |cst|
|
|
29
|
+
if i = c_parser.macro_numeric(cst)
|
|
30
|
+
dict[cst] = i
|
|
31
|
+
end
|
|
32
|
+
}
|
|
33
|
+
c_parser.toplevel.symbol.each { |k, v|
|
|
34
|
+
dict[k] = v if v.kind_of? Integer and k =~ cstbase
|
|
35
|
+
}
|
|
36
|
+
dict.delete_if { |k, v| imm & v != v }
|
|
37
|
+
if cst = dict.index(imm)
|
|
38
|
+
cst
|
|
39
|
+
else
|
|
40
|
+
# a => 1, b => 2, c => 4, all => 7: discard abc, keep 'all'
|
|
41
|
+
dict.delete_if { |k, v| dict.find { |kk, vv| vv > v and vv & v == v } }
|
|
42
|
+
dict.keys.join(' | ') if not dict.empty?
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
if gui
|
|
47
|
+
gui.keyboard_callback[?K] = lambda { |*a|
|
|
48
|
+
addr = gui.curaddr
|
|
49
|
+
imm_to_const(addr) { |i|
|
|
50
|
+
gui.inputbox("const name for #{Expression[i]}") { |name|
|
|
51
|
+
imm_to_const(addr) { |ii| name if ii == i }
|
|
52
|
+
gui.gui_update
|
|
53
|
+
}
|
|
54
|
+
nil
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
|
2
|
+
# Copyright (C) 2006-2009 Yoann GUILLOT
|
|
3
|
+
#
|
|
4
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# metasm gui plugin: change the colortheme used in the GUI
|
|
8
|
+
# based on solarized: http://ethanschoonover.com/solarized/
|
|
9
|
+
|
|
10
|
+
if gui
|
|
11
|
+
solarized = {
|
|
12
|
+
# name => hex RRGGBB
|
|
13
|
+
:base03 => '002b36',
|
|
14
|
+
:base02 => '073642',
|
|
15
|
+
:base01 => '586e75',
|
|
16
|
+
:base00 => '657b83',
|
|
17
|
+
:base0 => '839496',
|
|
18
|
+
:base1 => '93a1a1',
|
|
19
|
+
:base2 => 'eee8d5',
|
|
20
|
+
:base3 => 'fdf6e3',
|
|
21
|
+
:yellow => 'b58900',
|
|
22
|
+
:orange => 'cb4b16',
|
|
23
|
+
:red => 'dc322f',
|
|
24
|
+
:magenta => 'd33682',
|
|
25
|
+
:violet => '6c71c4',
|
|
26
|
+
:blue => '268bd2',
|
|
27
|
+
:cyan => '2aa198',
|
|
28
|
+
:green => '859900',
|
|
29
|
+
|
|
30
|
+
# personnal additions for more contrast
|
|
31
|
+
:base0C => '094048',
|
|
32
|
+
:base0D => '00151b',
|
|
33
|
+
|
|
34
|
+
:black => '002b36', # base03
|
|
35
|
+
:white => '93a1a1', # base1
|
|
36
|
+
|
|
37
|
+
:yellow_bg => '5a591b',# approx mean with black + manual tweak
|
|
38
|
+
:orange_bg => '553a16',
|
|
39
|
+
:red_bg => '461b1d',
|
|
40
|
+
:magenta_bg => '69305c',
|
|
41
|
+
:violet_bg => '364d7d',
|
|
42
|
+
:blue_bg => '135a84',
|
|
43
|
+
:cyan_bg => '156567',
|
|
44
|
+
:green_bg => '16510b',
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# all widget's colorscheme inherits from this one
|
|
48
|
+
# this is the dark background theme. For light background, change
|
|
49
|
+
# all 'baseX' into 'base0X' and 'base0X' into 'baseX'.
|
|
50
|
+
default = {
|
|
51
|
+
:background => :black,
|
|
52
|
+
:text => :white,
|
|
53
|
+
:instruction => :white,
|
|
54
|
+
:cursorline_bg => :base02,
|
|
55
|
+
:comment => :base01,
|
|
56
|
+
:caret => :base0,
|
|
57
|
+
:label => :violet,
|
|
58
|
+
:address => :blue,
|
|
59
|
+
:hl_word_bg => :white,
|
|
60
|
+
:hl_word => :black,
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
specific = {
|
|
64
|
+
# widget name => colortheme
|
|
65
|
+
# unspecified colors are taken from 'default'
|
|
66
|
+
# still unspecified colors are left unchanged
|
|
67
|
+
:listing => {
|
|
68
|
+
:raw_data => :white,
|
|
69
|
+
:arrows_bg => :base02,
|
|
70
|
+
:arrow_up => :cyan,
|
|
71
|
+
:arrow_dn => :blue,
|
|
72
|
+
:arrow_hl => :orange,
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
:opcodes => {
|
|
76
|
+
:raw_data => :white,
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
:decompile => {
|
|
80
|
+
:keyword => :blue,
|
|
81
|
+
:localvar => :red,
|
|
82
|
+
:globalvar => :green,
|
|
83
|
+
:intrinsic => :yellow,
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
:coverage => {
|
|
87
|
+
:code => :red,
|
|
88
|
+
:data => :blue,
|
|
89
|
+
:caret => :yellow,
|
|
90
|
+
:caret_col => :green,
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
:graph => {
|
|
94
|
+
:background => :base0D,
|
|
95
|
+
:hlbox_bg => :base02,
|
|
96
|
+
:box_bg => :base03,
|
|
97
|
+
:cursorline_bg => :base03,
|
|
98
|
+
:arrow_cond => :green,
|
|
99
|
+
:arrow_uncond => :cyan,
|
|
100
|
+
:arrow_direct => :blue,
|
|
101
|
+
:arrow_hl => :orange,
|
|
102
|
+
:box_bg_shadow => '000000',
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
:hex => {
|
|
106
|
+
:ascii => :white,
|
|
107
|
+
:data => :base1,
|
|
108
|
+
:write_pending => :red,
|
|
109
|
+
:caret_mirror => :base0C,
|
|
110
|
+
},
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
gui.view_indexes.each { |v|
|
|
114
|
+
cs = specific[v] || {}
|
|
115
|
+
view = gui.view(v)
|
|
116
|
+
# keep original view ':foo => :text' colors
|
|
117
|
+
legacy = view.default_color_association.dup
|
|
118
|
+
# but discard actual color defs (still present as fallback anyway)
|
|
119
|
+
legacy.delete_if { |k, c| c.kind_of?(::String) }
|
|
120
|
+
nca = solarized.merge(legacy).merge(default).merge(cs)
|
|
121
|
+
view.set_color_association(nca)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
true
|
|
125
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
|
2
|
+
# Copyright (C) 2006-2009 Yoann GUILLOT
|
|
3
|
+
#
|
|
4
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# metasm dasm plugin
|
|
8
|
+
# finds instances of indirect calls a la call [ecx+40h], backtraces ecx, comments with the C++ object function pointer name
|
|
9
|
+
# if the backtracked object has no type, prompt for a C structure name.
|
|
10
|
+
|
|
11
|
+
# TODO simpler gui interface to set [base+off] => ; struct->member
|
|
12
|
+
|
|
13
|
+
@indirect_call_struct = {}
|
|
14
|
+
def solve_indirect_call_set_struct(ptr, struct)
|
|
15
|
+
struct = @c_parser.toplevel.struct[struct] if struct.kind_of? String
|
|
16
|
+
raise 'no such struct' if not struct
|
|
17
|
+
@indirect_call_struct[ptr] = struct
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def solve_indirect_calls
|
|
21
|
+
@decoded.values.grep(DecodedInstruction).each { |di|
|
|
22
|
+
next if not di.opcode.props[:saveip] # only calls
|
|
23
|
+
fptr = get_xrefs_x(di)
|
|
24
|
+
next if fptr.to_a.length != 1
|
|
25
|
+
fptr = Expression[fptr.first].reduce_rec
|
|
26
|
+
next if not fptr.kind_of? Indirection
|
|
27
|
+
next if not fptr.pointer.lexpr.kind_of? Symbol
|
|
28
|
+
next if not fptr.pointer.rexpr.kind_of? Integer
|
|
29
|
+
obj = backtrace(fptr.pointer.lexpr, di.address)
|
|
30
|
+
obj.delete Expression::Unknown
|
|
31
|
+
next if obj.length != 1
|
|
32
|
+
obj = obj.first
|
|
33
|
+
obj = Expression[obj].reduce_rec
|
|
34
|
+
next if not obj.kind_of? Indirection
|
|
35
|
+
obj = obj.pointer # vtable ptr -> object ptr
|
|
36
|
+
|
|
37
|
+
if not struct = @indirect_call_struct[obj]
|
|
38
|
+
struct = yield obj if block_given?
|
|
39
|
+
solve_indirect_call_set_struct(obj, struct || :none)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
if struct.kind_of? C::Struct and fld = struct.members.find { |m| struct.offsetof(c_parser, m) == fptr.pointer.rexpr } and fld.name
|
|
43
|
+
di.add_comment "#{struct.name || obj}->#{fld.name}"
|
|
44
|
+
di.comment.delete 'x:unknown'
|
|
45
|
+
end
|
|
46
|
+
}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
if gui
|
|
50
|
+
solve_indirect_calls { |ptr|
|
|
51
|
+
gui.inputbox("struct name for object at #{ptr}") { |name|
|
|
52
|
+
solve_indirect_call_set_struct(ptr, name)
|
|
53
|
+
# re-solve everything, cause we're called only once but many indirect calls may use ptr
|
|
54
|
+
solve_indirect_calls
|
|
55
|
+
gui.gui_update
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
gui.gui_update
|
|
59
|
+
nil
|
|
60
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
|
2
|
+
# Copyright (C) 2006-2009 Yoann GUILLOT
|
|
3
|
+
#
|
|
4
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# metasm dasm plugin: retrieve a section section, and disassemble everything it can, skipping existing code and nops
|
|
8
|
+
# usage: load the plugin, then call (ruby snipped): dasm.dasm_all_section '.text'
|
|
9
|
+
def dasm_all(addrstart, length, method=:disassemble_fast_deep)
|
|
10
|
+
s = get_section_at(addrstart)
|
|
11
|
+
return if not s
|
|
12
|
+
s = s[0]
|
|
13
|
+
boff = s.ptr
|
|
14
|
+
off = 0
|
|
15
|
+
while off < length
|
|
16
|
+
if di = di_at(addrstart + off)
|
|
17
|
+
off += di.bin_length
|
|
18
|
+
elsif @decoded[addrstart+off]
|
|
19
|
+
off += 1
|
|
20
|
+
else
|
|
21
|
+
s.ptr = boff+off
|
|
22
|
+
maydi = cpu.decode_instruction(s, 0)
|
|
23
|
+
if not maydi
|
|
24
|
+
off += 1
|
|
25
|
+
elsif maydi.instruction.to_s =~ /nop|lea (.*), \[\1(?:\+0)?\]|mov (.*), \2|int 3/
|
|
26
|
+
off += maydi.bin_length
|
|
27
|
+
else
|
|
28
|
+
puts "dasm_all: found #{Expression[addrstart+off]}" if $VERBOSE
|
|
29
|
+
send(method, addrstart+off)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
Gui.main_iter if gui and off & 15 == 0
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
count = 0
|
|
36
|
+
off = 0
|
|
37
|
+
while off < length
|
|
38
|
+
addr = addrstart+off
|
|
39
|
+
if di = di_at(addr)
|
|
40
|
+
if di.block_head?
|
|
41
|
+
b = di.block
|
|
42
|
+
if not @function[addr] and b.from_subfuncret.to_a.empty? and b.from_normal.to_a.empty?
|
|
43
|
+
l = auto_label_at(addr, 'sub_orph')
|
|
44
|
+
puts "dasm_all: found orphan function #{l}"
|
|
45
|
+
@function[addrstart+off] = DecodedFunction.new
|
|
46
|
+
@function[addrstart+off].finalized = true
|
|
47
|
+
detect_function_thunk(addr)
|
|
48
|
+
count += 1
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
off += di.bin_length
|
|
52
|
+
else
|
|
53
|
+
off += 1
|
|
54
|
+
end
|
|
55
|
+
Gui.main_iter if gui and off & 15 == 0
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
puts "found #{count} orphan functions" if $VERBOSE
|
|
59
|
+
|
|
60
|
+
gui.gui_update if gui
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def dasm_all_section(name, method=:disassemble_fast_deep)
|
|
64
|
+
section_info.each { |n, a, l, i|
|
|
65
|
+
if name == n
|
|
66
|
+
dasm_all(Expression[a].reduce, l, method)
|
|
67
|
+
end
|
|
68
|
+
}
|
|
69
|
+
true
|
|
70
|
+
end
|