metasm 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/samples/exeencode.rb
CHANGED
@@ -26,7 +26,8 @@ $opts = {
|
|
26
26
|
|
27
27
|
OptionParser.new { |opt|
|
28
28
|
opt.on('-o file', 'output filename') { |f| $opts[:outfilename] = f }
|
29
|
-
opt.on('-
|
29
|
+
opt.on('-i', 'dont overwrite existing outfile') { $opts[:nooverwrite_outfile] = true }
|
30
|
+
opt.on('-f', 'overwrite existing outfile (default)') { $opts.delete :nooverwrite_outfile } # without this, optparse autocomplete to --fno-pic and break older scripts...
|
30
31
|
opt.on('--c', 'parse source as a C file') { $opts[:srctype] = 'c' }
|
31
32
|
opt.on('--asm', 'parse asm as an ASM file') { $opts[:srctype] = 'asm' }
|
32
33
|
opt.on('--stdin', 'parse source on stdin') { ARGV << '-' }
|
@@ -44,7 +45,7 @@ OptionParser.new { |opt|
|
|
44
45
|
opt.on('--le', 'set cpu in little-endian mode') { $opts[:cpu].endianness = :little }
|
45
46
|
opt.on('--be', 'set cpu in big-endian mode') { $opts[:cpu].endianness = :big }
|
46
47
|
opt.on('--fno-pic', 'generate position-dependant code') { $opts[:cpu].generate_PIC = false }
|
47
|
-
opt.on('--shared', 'generate shared library') { $opts[:exetype] = :lib }
|
48
|
+
opt.on('--shared', '--lib', '--dll', 'generate shared library') { $opts[:exetype] = :lib }
|
48
49
|
opt.on('--ruby-module-hack', 'use the dynldr module hack to use any ruby lib available for ruby symbols') { $opts[:dldrhack] = true }
|
49
50
|
}.parse!
|
50
51
|
|
@@ -62,7 +63,7 @@ else
|
|
62
63
|
src << DATA.read # the text after __END__ in this file
|
63
64
|
end
|
64
65
|
|
65
|
-
if $opts[:outfilename] and
|
66
|
+
if $opts[:outfilename] and $opts[:nooverwrite_outfile] and File.exist?($opts[:outfilename])
|
66
67
|
abort "Error: target file exists !"
|
67
68
|
end
|
68
69
|
|
@@ -93,7 +94,7 @@ if $opts[:to_string]
|
|
93
94
|
end
|
94
95
|
|
95
96
|
if of = $opts[:outfilename]
|
96
|
-
abort "Error: target file #{of.inspect} exists !" if File.exists?
|
97
|
+
abort "Error: target file #{of.inspect} exists !" if File.exists?(of) and $opts[:nooverwrite_outfile]
|
97
98
|
File.open(of, 'w') { |fd| fd.puts str }
|
98
99
|
puts "saved to file #{of.inspect}"
|
99
100
|
else
|
@@ -101,7 +102,7 @@ if $opts[:to_string]
|
|
101
102
|
end
|
102
103
|
else
|
103
104
|
of = $opts[:outfilename] ||= 'a.out'
|
104
|
-
abort "Error: target file #{of.inspect} exists !" if File.exists?
|
105
|
+
abort "Error: target file #{of.inspect} exists !" if File.exists?(of) and $opts[:nooverwrite_outfile]
|
105
106
|
Metasm::DynLdr.compile_binary_module_hack(exe) if $opts[:dldrhack]
|
106
107
|
exe.encode_file(of, $opts[:exetype])
|
107
108
|
puts "saved to file #{of.inspect}"
|
data/samples/lindebug.rb
CHANGED
@@ -47,14 +47,15 @@ module Ansi
|
|
47
47
|
$stdin.ioctl(TIOCGWINSZ, s) >= 0 ? s.unpack('SS') : [80, 25]
|
48
48
|
end
|
49
49
|
def self.set_term_canon(bool)
|
50
|
-
|
51
|
-
$stdin.ioctl(TCGETS,
|
50
|
+
ttys = ''.ljust(256)
|
51
|
+
$stdin.ioctl(TCGETS, ttys)
|
52
|
+
tty = ttys.unpack('C*')
|
52
53
|
if bool
|
53
54
|
tty[12] &= ~(ECHO|CANON)
|
54
55
|
else
|
55
56
|
tty[12] |= ECHO|CANON
|
56
57
|
end
|
57
|
-
$stdin.ioctl(TCSETS, tty)
|
58
|
+
$stdin.ioctl(TCSETS, tty.pack('C*'))
|
58
59
|
end
|
59
60
|
|
60
61
|
ESC_SEQ = {'A' => :up, 'B' => :down, 'C' => :right, 'D' => :left,
|
@@ -85,49 +86,11 @@ module Ansi
|
|
85
86
|
end
|
86
87
|
end
|
87
88
|
|
88
|
-
class Indirect < Metasm::ExpressionType
|
89
|
-
attr_accessor :ptr, :sz
|
90
|
-
UNPACK_STR = {1 => 'C', 2 => 'S', 4 => 'L'}
|
91
|
-
def initialize(ptr, sz) @ptr, @sz = ptr, sz end
|
92
|
-
def bind(bd)
|
93
|
-
raw = bd['tracer_memory'][@ptr.bind(bd).reduce, @sz]
|
94
|
-
Metasm::Expression[raw.unpack(UNPACK_STR[@sz]).first]
|
95
|
-
end
|
96
|
-
def externals ; @ptr.externals end
|
97
|
-
end
|
98
|
-
|
99
|
-
class ExprParser < Metasm::Expression
|
100
|
-
def self.parse_intfloat(lex, tok)
|
101
|
-
case tok.raw
|
102
|
-
when 'byte', 'word', 'dword'
|
103
|
-
nil while ntok = lex.readtok and ntok.type == :space
|
104
|
-
nil while ntok = lex.readtok and ntok.type == :space if ntok and ntok.raw == 'ptr'
|
105
|
-
if ntok and ntok.raw == '['
|
106
|
-
tok.value = Indirect.new(parse(lex), {'byte' => 1, 'word' => 2, 'dword' => 4}[tok.raw])
|
107
|
-
nil while ntok = lex.readtok and ntok.type == :space
|
108
|
-
nil while ntok = lex.readtok and ntok.type == :space if ntok and ntok.raw == ']'
|
109
|
-
lex.unreadtok ntok
|
110
|
-
end
|
111
|
-
else super(lex, tok)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
def self.parse_value(lex)
|
115
|
-
nil while tok = lex.readtok and tok.type == :space
|
116
|
-
lex.unreadtok tok
|
117
|
-
if tok and tok.type == :punct and tok.raw == '['
|
118
|
-
tt = tok.dup
|
119
|
-
tt.type = :string
|
120
|
-
tt.raw = 'dword'
|
121
|
-
lex.unreadtok tt
|
122
|
-
end
|
123
|
-
super(lex)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
89
|
class LinDebug
|
128
|
-
attr_accessor :win_data_height, :win_code_height, :win_prpt_height
|
90
|
+
attr_accessor :win_reg_height, :win_data_height, :win_code_height, :win_prpt_height
|
129
91
|
def init_screen
|
130
92
|
Ansi.set_term_canon(true)
|
93
|
+
@win_reg_height = 2
|
131
94
|
@win_data_height = 20
|
132
95
|
@win_code_height = 20
|
133
96
|
resize
|
@@ -139,7 +102,7 @@ class LinDebug
|
|
139
102
|
$stdout.flush
|
140
103
|
end
|
141
104
|
|
142
|
-
def win_data_start;
|
105
|
+
def win_data_start; @win_reg_height end
|
143
106
|
def win_code_start; win_data_start+win_data_height end
|
144
107
|
def win_prpt_start; win_code_start+win_code_height end
|
145
108
|
|
@@ -164,9 +127,8 @@ class LinDebug
|
|
164
127
|
attr_accessor :dataptr, :codeptr, :rs, :promptlog, :command
|
165
128
|
def initialize(rs)
|
166
129
|
@rs = rs
|
167
|
-
@rs.
|
130
|
+
@rs.set_log_proc { |l| add_log l }
|
168
131
|
@datafmt = 'db'
|
169
|
-
@watch = nil
|
170
132
|
|
171
133
|
@prompthistlen = 20
|
172
134
|
@prompthistory = []
|
@@ -176,6 +138,7 @@ class LinDebug
|
|
176
138
|
@promptpos = 0
|
177
139
|
@log_off = 0
|
178
140
|
@console_width = 80
|
141
|
+
@oldregs = {}
|
179
142
|
|
180
143
|
@running = false
|
181
144
|
@focus = :prompt
|
@@ -185,7 +148,7 @@ class LinDebug
|
|
185
148
|
end
|
186
149
|
|
187
150
|
def init_rs
|
188
|
-
@codeptr = @dataptr = @rs.
|
151
|
+
@codeptr = @dataptr = @rs.pc # avoid initial faults
|
189
152
|
end
|
190
153
|
|
191
154
|
def main_loop
|
@@ -201,9 +164,9 @@ class LinDebug
|
|
201
164
|
$stdout.print Ansi.set_cursor_pos(@console_height, 1)
|
202
165
|
end
|
203
166
|
rescue
|
204
|
-
|
167
|
+
puts $!, $!.backtrace
|
205
168
|
end
|
206
|
-
|
169
|
+
puts @promptlog.last
|
207
170
|
end
|
208
171
|
|
209
172
|
# optimize string to display to stdout
|
@@ -218,7 +181,7 @@ class LinDebug
|
|
218
181
|
def display_screen(screenlines, cursx, cursy)
|
219
182
|
|
220
183
|
@oldscreenbuf ||= []
|
221
|
-
lines = screenlines.
|
184
|
+
lines = screenlines.lines
|
222
185
|
oldlines = @oldscreenbuf
|
223
186
|
@oldscreenbuf = lines
|
224
187
|
screenlines = lines.zip(oldlines).map { |l, ol| l == ol ? "\n" : l }.join
|
@@ -247,41 +210,40 @@ class LinDebug
|
|
247
210
|
end
|
248
211
|
|
249
212
|
def _updateregs
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
text << (' '*([@console_width-x, 0].max)) << "\n" << ' '
|
262
|
-
x = 1
|
263
|
-
%w[esi edi ebp esp].each { |r|
|
264
|
-
text << Color[:changed] if @rs.regs_cache[r] != @rs.oldregs[r]
|
265
|
-
text << r << ?=
|
266
|
-
text << ('%08X' % @rs.regs_cache[r])
|
267
|
-
text << Color[:normal] if @rs.regs_cache[r] != @rs.oldregs[r]
|
268
|
-
text << ' '
|
269
|
-
x += r.length + 11
|
213
|
+
pvrsz = 0
|
214
|
+
words = @rs.register_list.map { |r|
|
215
|
+
rs = r.to_s.rjust(pvrsz)
|
216
|
+
pvrsz = rs.length
|
217
|
+
rv = @rs[r]
|
218
|
+
["#{rs}=%0#{@rs.register_size[r]/4}X " % rv,
|
219
|
+
(@oldregs[r] != rv)]
|
220
|
+
} + @rs.flag_list.map { |fl|
|
221
|
+
fv = @rs.get_flag(fl)
|
222
|
+
[fv ? fl.to_s.upcase : fl.to_s.downcase,
|
223
|
+
(@oldregs[fl] != fv)]
|
270
224
|
}
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
text <<
|
225
|
+
|
226
|
+
text = ' '
|
227
|
+
linelen = 1 # line length w/o ansi colors
|
228
|
+
|
229
|
+
owr = @win_reg_height
|
230
|
+
@win_reg_height = 1
|
231
|
+
words.each { |w, changed|
|
232
|
+
if linelen + w.length >= @console_width - 1
|
233
|
+
text << (' '*([@console_width-linelen, 0].max)) << "\n "
|
234
|
+
linelen = 1
|
235
|
+
@win_reg_height += 1
|
280
236
|
end
|
237
|
+
|
238
|
+
text << Color[:changed] if changed
|
239
|
+
text << w
|
240
|
+
text << Color[:normal] if changed
|
281
241
|
text << ' '
|
282
|
-
|
242
|
+
|
243
|
+
linelen += w.length+1
|
283
244
|
}
|
284
|
-
|
245
|
+
resize if owr != @win_reg_height
|
246
|
+
text << (' '*([@console_width-linelen, 0].max)) << "\n"
|
285
247
|
end
|
286
248
|
|
287
249
|
def updatecode
|
@@ -291,21 +253,23 @@ class LinDebug
|
|
291
253
|
def _updatecode
|
292
254
|
if @codeptr
|
293
255
|
addr = @codeptr
|
294
|
-
elsif @rs.
|
295
|
-
addr = @rs.
|
256
|
+
elsif @oldregs[@rs.register_pc] and @oldregs[@rs.register_pc] < @rs.pc and @oldregs[@rs.register_pc] + 8 >= @rs.pc
|
257
|
+
addr = @oldregs[@rs.register_pc]
|
296
258
|
else
|
297
|
-
addr = @rs.
|
259
|
+
addr = @rs.pc
|
298
260
|
end
|
299
261
|
@codeptr = addr
|
300
262
|
|
301
|
-
|
302
|
-
|
263
|
+
addrsz = @rs.register_size[@rs.register_pc]
|
264
|
+
addrfmt = "%0#{addrsz/4}X"
|
265
|
+
if not @rs.addr2module(addr) and @rs.shortname !~ /remote/
|
266
|
+
base = addr & ((1 << addrsz) - 0x1000)
|
303
267
|
@noelfsig ||= {} # cache elfmagic notfound
|
304
|
-
if not @noelfsig[base] and base <
|
305
|
-
self.statusline = " scanning for elf header at #{
|
268
|
+
if not @noelfsig[base] and base < ((1 << addrsz) - 0x1_0000)
|
269
|
+
self.statusline = " scanning for elf header at #{addrfmt % base}"
|
306
270
|
128.times {
|
307
|
-
@statusline = " scanning for elf header at #{
|
308
|
-
if not @noelfsig[base] and @rs[base,
|
271
|
+
@statusline = " scanning for elf header at #{addrfmt % base}"
|
272
|
+
if not @noelfsig[base] and @rs[base, Metasm::ELF::MAGIC.length] == Metasm::ELF::MAGIC
|
309
273
|
@rs.loadsyms(base, base.to_s(16))
|
310
274
|
break
|
311
275
|
else
|
@@ -320,36 +284,43 @@ class LinDebug
|
|
320
284
|
|
321
285
|
text = ''
|
322
286
|
text << Color[:border]
|
323
|
-
title = @rs.
|
287
|
+
title = @rs.addrname(addr)
|
324
288
|
pre = [@console_width-100, 6].max
|
325
289
|
post = @console_width - (pre + title.length + 2)
|
326
290
|
text << Ansi.hline(pre) << ' ' << title << ' ' << Ansi.hline(post) << Color[:normal] << "\n"
|
327
291
|
|
292
|
+
seg = ''
|
293
|
+
seg = ('%04X' % @rs['cs']) << ':' if @rs.cpu.shortname =~ /ia32|x64/
|
294
|
+
|
328
295
|
cnt = @win_code_height
|
329
296
|
while (cnt -= 1) > 0
|
330
297
|
if @rs.symbols[addr]
|
331
298
|
text << (' ' << @rs.symbols[addr] << ?:) << Ansi::ClearLineAfter << "\n"
|
332
299
|
break if (cnt -= 1) <= 0
|
333
300
|
end
|
334
|
-
text << Color[:hilight] if addr == @rs.
|
335
|
-
text <<
|
336
|
-
|
337
|
-
|
338
|
-
|
301
|
+
text << Color[:hilight] if addr == @rs.pc
|
302
|
+
text << seg
|
303
|
+
if @rs.shortname =~ /remote/ and @rs.realmode
|
304
|
+
text << (addrfmt % (addr - 16*@rs['cs']))
|
305
|
+
else
|
306
|
+
text << (addrfmt % addr)
|
307
|
+
end
|
308
|
+
di = @rs.di_at(addr)
|
309
|
+
di = nil if di and addr < @rs.pc and addr+di.bin_length > @rs.pc
|
339
310
|
len = (di ? di.bin_length : 1)
|
340
311
|
text << ' '
|
341
|
-
text << @rs[addr, [len, 10].min].unpack('C*').map { |c| '%02X' % c }.join.ljust(22)
|
312
|
+
text << @rs.memory[addr, [len, 10].min].to_s.unpack('C*').map { |c| '%02X' % c }.join.ljust(22)
|
342
313
|
if di
|
343
314
|
text <<
|
344
|
-
if addr == @rs.
|
345
|
-
"*#{di.instruction}".ljust([@console_width-
|
315
|
+
if addr == @rs.pc
|
316
|
+
"*#{di.instruction}".ljust([@console_width-(addrsz/4+seg.length+24), 0].max)
|
346
317
|
else
|
347
318
|
" #{di.instruction}" << Ansi::ClearLineAfter
|
348
319
|
end
|
349
320
|
else
|
350
321
|
text << ' <unk>' << Ansi::ClearLineAfter
|
351
322
|
end
|
352
|
-
text << Color[:normal] if addr == @rs.
|
323
|
+
text << Color[:normal] if addr == @rs.pc
|
353
324
|
addr += len
|
354
325
|
text << "\n"
|
355
326
|
end
|
@@ -361,27 +332,33 @@ class LinDebug
|
|
361
332
|
end
|
362
333
|
|
363
334
|
def _updatedata
|
364
|
-
|
335
|
+
addrsz = @rs.register_size[@rs.register_pc]
|
336
|
+
addrfmt = "%0#{addrsz/4}X"
|
337
|
+
|
338
|
+
@dataptr &= ((1 << addrsz) - 1)
|
365
339
|
addr = @dataptr
|
366
340
|
|
367
341
|
text = ''
|
368
342
|
text << Color[:border]
|
369
|
-
title = @rs.
|
343
|
+
title = @rs.addrname(addr)
|
370
344
|
pre = [@console_width-100, 6].max
|
371
345
|
post = [@console_width - (pre + title.length + 2), 0].max
|
372
346
|
text << Ansi.hline(pre) << ' ' << title << ' ' << Ansi.hline(post) << Color[:normal] << "\n"
|
373
347
|
|
348
|
+
seg = ''
|
349
|
+
seg = ('%04X' % @rs['ds']) << ':' if @rs.cpu.shortname =~ /^ia32/
|
350
|
+
|
374
351
|
cnt = @win_data_height
|
375
352
|
while (cnt -= 1) > 0
|
376
|
-
raw = @rs[addr, 16].to_s
|
377
|
-
text <<
|
353
|
+
raw = @rs.memory[addr, 16].to_s
|
354
|
+
text << seg << (addrfmt % addr) << ' '
|
378
355
|
case @datafmt
|
379
356
|
when 'db'; text << raw[0,8].unpack('C*').map { |c| '%02x ' % c }.join << ' ' <<
|
380
357
|
raw[8,8].to_s.unpack('C*').map { |c| '%02x ' % c }.join
|
381
358
|
when 'dw'; text << raw.unpack('S*').map { |c| '%04x ' % c }.join
|
382
359
|
when 'dd'; text << raw.unpack('L*').map { |c| '%08x ' % c }.join
|
383
360
|
end
|
384
|
-
text << ' ' << raw.unpack('C*').map { |c| (0x20..0x7e).include?(c) ? c :
|
361
|
+
text << ' ' << raw.unpack('C*').map { |c| (0x20..0x7e).include?(c) ? c : 0x2e }.pack('C*')
|
385
362
|
text << Ansi::ClearLineAfter << "\n"
|
386
363
|
addr += 16
|
387
364
|
end
|
@@ -420,17 +397,17 @@ class LinDebug
|
|
420
397
|
@console_height, @console_width = Ansi.get_terminal_size
|
421
398
|
@win_data_height = 1 if @win_data_height < 1
|
422
399
|
@win_code_height = 1 if @win_code_height < 1
|
423
|
-
if @win_data_height + @win_code_height +
|
400
|
+
if @win_data_height + @win_code_height + @win_reg_height + 3 > @console_height
|
424
401
|
@win_data_height = @console_height/2 - 4
|
425
402
|
@win_code_height = @console_height/2 - 4
|
426
403
|
end
|
427
|
-
@win_prpt_height = @console_height-(@win_data_height+@win_code_height
|
404
|
+
@win_prpt_height = @console_height-(@win_data_height+@win_code_height+@win_reg_height) - 1
|
428
405
|
@oldscreenbuf = []
|
429
406
|
update
|
430
407
|
end
|
431
408
|
|
432
409
|
def log(*strs)
|
433
|
-
|
410
|
+
strs.each { |str|
|
434
411
|
raise str.inspect if not str.kind_of? ::String
|
435
412
|
str = str.chomp
|
436
413
|
if str.length > @console_width
|
@@ -440,85 +417,52 @@ class LinDebug
|
|
440
417
|
end
|
441
418
|
@promptlog << str
|
442
419
|
@promptlog.shift if @promptlog.length > @promptloglen
|
443
|
-
|
420
|
+
}
|
444
421
|
end
|
445
422
|
|
446
|
-
def
|
447
|
-
|
448
|
-
|
449
|
-
update rescue
|
450
|
-
end
|
451
|
-
|
452
|
-
def mem_binding(expr)
|
453
|
-
b = @rs.regs_cache.dup
|
454
|
-
ext = expr.externals
|
455
|
-
(ext - @rs.regs_cache.keys).each { |ex|
|
456
|
-
if not s = @rs.symbols.index(ex)
|
457
|
-
near = @rs.symbols.values.grep(/#{ex}/i)
|
458
|
-
if near.length > 1
|
459
|
-
log "#{ex.inspect} is ambiguous: #{near.inspect}"
|
460
|
-
return {}
|
461
|
-
elsif near.empty?
|
462
|
-
log "unknown value #{ex.inspect}"
|
463
|
-
return {}
|
464
|
-
else
|
465
|
-
log "using #{near.first.inspect} for #{ex.inspect}"
|
466
|
-
s = @rs.symbols.index(near.first)
|
467
|
-
end
|
468
|
-
end
|
469
|
-
b[ex] = s
|
470
|
-
}
|
471
|
-
b['tracer_memory'] = @rs
|
472
|
-
b
|
423
|
+
def add_log(l)
|
424
|
+
log l
|
425
|
+
puts l if not @running
|
426
|
+
update rescue puts l
|
473
427
|
end
|
474
428
|
|
475
429
|
def exec_prompt
|
476
430
|
@log_off = 0
|
477
431
|
log ':'+@promptbuf
|
478
432
|
return if @promptbuf == ''
|
479
|
-
|
433
|
+
str = @promptbuf
|
480
434
|
@prompthistory << @promptbuf
|
481
435
|
@prompthistory.shift if @prompthistory.length > @prompthistlen
|
482
436
|
@promptbuf = ''
|
483
437
|
@promptpos = @promptbuf.length
|
484
|
-
argint = lambda {
|
485
|
-
begin
|
486
|
-
raise if not e = ExprParser.parse(lex)
|
487
|
-
rescue
|
488
|
-
log 'syntax error'
|
489
|
-
return
|
490
|
-
end
|
491
|
-
e = e.bind(mem_binding(e)).reduce
|
492
|
-
if e.kind_of? Integer; e
|
493
|
-
else log "could not resolve #{e.inspect}" ; nil
|
494
|
-
end
|
495
|
-
}
|
496
438
|
|
497
|
-
cmd =
|
498
|
-
cmd = cmd.raw if cmd
|
499
|
-
nil while ntok = lex.readtok and ntok.type == :space
|
500
|
-
lex.unreadtok ntok
|
439
|
+
cmd, str = str.split(/\s+/, 2)
|
501
440
|
if @command.has_key? cmd
|
502
|
-
@command[cmd].call(
|
441
|
+
@command[cmd].call(str.to_s)
|
503
442
|
else
|
504
443
|
if cmd and (poss = @command.keys.find_all { |c| c[0, cmd.length] == cmd }).length == 1
|
505
|
-
@command[poss.first].call(
|
444
|
+
@command[poss.first].call(str.to_s)
|
506
445
|
else
|
507
446
|
log 'unknown command'
|
508
447
|
end
|
509
448
|
end
|
510
449
|
end
|
511
450
|
|
451
|
+
def preupdate
|
452
|
+
@rs.register_list.each { |r| @oldregs[r] = @rs[r] }
|
453
|
+
@rs.flag_list.each { |fl| @oldregs[fl] = @rs.get_flag(fl) }
|
454
|
+
end
|
455
|
+
|
512
456
|
def updatecodeptr
|
513
|
-
@codeptr ||= @rs.
|
514
|
-
if @codeptr > @rs.
|
515
|
-
@codeptr = @rs.
|
516
|
-
elsif @codeptr != @rs.
|
457
|
+
@codeptr ||= @rs.pc
|
458
|
+
if @codeptr > @rs.pc or @codeptr < @rs.pc - 6*@win_code_height
|
459
|
+
@codeptr = @rs.pc
|
460
|
+
elsif @codeptr != @rs.pc
|
517
461
|
addr = @codeptr
|
518
462
|
addrs = []
|
519
|
-
while addr < @rs.
|
463
|
+
while addr < @rs.pc
|
520
464
|
addrs << addr
|
521
|
-
o = ((di = @rs.
|
465
|
+
o = ((di = @rs.di_at(addr)) ? di.bin_length : 0)
|
522
466
|
addr += ((o == 0) ? 1 : o)
|
523
467
|
end
|
524
468
|
if addrs.length > @win_code_height-4
|
@@ -529,36 +473,40 @@ class LinDebug
|
|
529
473
|
end
|
530
474
|
|
531
475
|
def updatedataptr
|
532
|
-
@dataptr = @watch.bind(mem_binding(@watch)).reduce if @watch
|
533
476
|
end
|
534
477
|
|
535
478
|
def singlestep
|
536
479
|
self.statusline = ' target singlestepping...'
|
537
|
-
|
480
|
+
preupdate
|
481
|
+
@rs.singlestep_wait
|
538
482
|
updatecodeptr
|
539
483
|
@statusline = nil
|
540
484
|
end
|
541
485
|
def stepover
|
542
486
|
self.statusline = ' target running...'
|
543
|
-
|
487
|
+
preupdate
|
488
|
+
@rs.stepover_wait
|
544
489
|
updatecodeptr
|
545
490
|
@statusline = nil
|
546
491
|
end
|
547
492
|
def cont(*a)
|
548
493
|
self.statusline = ' target running...'
|
549
|
-
|
494
|
+
preupdate
|
495
|
+
@rs.continue_wait(*a)
|
550
496
|
updatecodeptr
|
551
497
|
@statusline = nil
|
552
498
|
end
|
553
499
|
def stepout
|
554
500
|
self.statusline = ' target running...'
|
555
|
-
|
501
|
+
preupdate
|
502
|
+
@rs.stepout_wait
|
556
503
|
updatecodeptr
|
557
504
|
@statusline = nil
|
558
505
|
end
|
559
506
|
def syscall
|
560
507
|
self.statusline = ' target running to next syscall...'
|
561
|
-
|
508
|
+
preupdate
|
509
|
+
@rs.syscall_wait
|
562
510
|
updatecodeptr
|
563
511
|
@statusline = nil
|
564
512
|
end
|
@@ -578,17 +526,14 @@ class LinDebug
|
|
578
526
|
end
|
579
527
|
break if handle_keypress(Ansi.getkey)
|
580
528
|
end
|
581
|
-
@rs.checkbp
|
582
529
|
end
|
583
530
|
|
584
531
|
def handle_keypress(k)
|
585
532
|
case k
|
586
|
-
when 4; log 'exiting'; return true # eof
|
587
|
-
when ?\e; focus = :prompt
|
533
|
+
when ?\4; log 'exiting'; return true # eof
|
534
|
+
when ?\e; @focus = :prompt
|
588
535
|
when :f5; cont
|
589
|
-
when :f6
|
590
|
-
syscall
|
591
|
-
log @rs.syscallnr.index(@rs.regs_cache['orig_eax']) || @rs.regs_cache['orig_eax'].to_s
|
536
|
+
when :f6; syscall
|
592
537
|
when :f10; stepover
|
593
538
|
when :f11; singlestep
|
594
539
|
when :f12; stepout
|
@@ -607,9 +552,9 @@ class LinDebug
|
|
607
552
|
when :data
|
608
553
|
@dataptr -= 16
|
609
554
|
when :code
|
610
|
-
@codeptr ||= @rs.
|
555
|
+
@codeptr ||= @rs.pc
|
611
556
|
@codeptr -= (1..10).find { |off|
|
612
|
-
di = @rs.
|
557
|
+
di = @rs.di_at(@codeptr-off)
|
613
558
|
di.bin_length == off if di
|
614
559
|
} || 10
|
615
560
|
end
|
@@ -628,25 +573,25 @@ class LinDebug
|
|
628
573
|
when :data
|
629
574
|
@dataptr += 16
|
630
575
|
when :code
|
631
|
-
@codeptr ||= @rs.
|
632
|
-
di = @rs.
|
576
|
+
@codeptr ||= @rs.pc
|
577
|
+
di = @rs.di_at(@codeptr)
|
633
578
|
@codeptr += (di ? (di.bin_length || 1) : 1)
|
634
579
|
end
|
635
580
|
when :left; @promptpos -= 1 if @promptpos > 0
|
636
581
|
when :right; @promptpos += 1 if @promptpos < @promptbuf.length
|
637
582
|
when :home; @promptpos = 0
|
638
583
|
when :end; @promptpos = @promptbuf.length
|
639
|
-
when :backspace,
|
584
|
+
when :backspace, ?\x7f; @promptbuf[@promptpos-=1, 1] = '' if @promptpos > 0
|
640
585
|
when :suppr; @promptbuf[@promptpos, 1] = '' if @promptpos < @promptbuf.length
|
641
586
|
when :pgup
|
642
587
|
case @focus
|
643
588
|
when :prompt; @log_off += @win_prpt_height-3
|
644
589
|
when :data; @dataptr -= 16*(@win_data_height-1)
|
645
590
|
when :code
|
646
|
-
@codeptr ||= @rs.
|
591
|
+
@codeptr ||= @rs.pc
|
647
592
|
(@win_code_height-1).times {
|
648
593
|
@codeptr -= (1..10).find { |off|
|
649
|
-
di = @rs.
|
594
|
+
di = @rs.di_at(@codeptr-off)
|
650
595
|
di.bin_length == off if di
|
651
596
|
} || 10
|
652
597
|
}
|
@@ -656,8 +601,8 @@ class LinDebug
|
|
656
601
|
when :prompt; @log_off -= @win_prpt_height-3
|
657
602
|
when :data; @dataptr += 16*(@win_data_height-1)
|
658
603
|
when :code
|
659
|
-
@codeptr ||= @rs.
|
660
|
-
(@win_code_height-1).times { @codeptr += ((o = @rs.
|
604
|
+
@codeptr ||= @rs.pc
|
605
|
+
(@win_code_height-1).times { @codeptr += ((o = @rs.di_at(@codeptr)) ? [o.bin_length, 1].max : 1) }
|
661
606
|
end
|
662
607
|
when ?\t
|
663
608
|
if not @promptbuf[0, @promptpos].include? ' '
|
@@ -676,7 +621,7 @@ class LinDebug
|
|
676
621
|
rescue Exception
|
677
622
|
log "error: #$!", *$!.backtrace
|
678
623
|
end
|
679
|
-
when
|
624
|
+
when ?\ ..?~
|
680
625
|
@promptbuf[@promptpos, 0] = k.chr
|
681
626
|
@promptpos += 1
|
682
627
|
else log "unknown key pressed #{k.inspect}"
|
@@ -685,240 +630,89 @@ class LinDebug
|
|
685
630
|
end
|
686
631
|
|
687
632
|
def load_commands
|
688
|
-
|
689
|
-
@command['kill'] = lambda { |lex, int|
|
633
|
+
@command['kill'] = lambda { |str|
|
690
634
|
@rs.kill
|
691
635
|
@running = false
|
692
636
|
log 'killed'
|
693
637
|
}
|
694
|
-
@command['quit'] = @command['detach'] = @command['exit'] = lambda { |
|
638
|
+
@command['quit'] = @command['detach'] = @command['exit'] = lambda { |str|
|
695
639
|
@rs.detach
|
696
640
|
@running = false
|
697
641
|
}
|
698
|
-
@command['closeui'] = lambda { |
|
699
|
-
@rs.logger = nil
|
642
|
+
@command['closeui'] = lambda { |str|
|
700
643
|
@running = false
|
701
644
|
}
|
702
|
-
@command['bpx'] = lambda { |
|
703
|
-
|
704
|
-
@rs.bpx addr
|
705
|
-
}
|
706
|
-
@command['bphw'] = lambda { |lex, int|
|
707
|
-
type = lex.readtok.raw
|
708
|
-
addr = int[]
|
709
|
-
@rs.set_hwbp type, addr
|
710
|
-
}
|
711
|
-
@command['bl'] = lambda { |lex, int|
|
712
|
-
log "bpx at #{@rs.findsymbol(@rs.wantbp)}" if @rs.wantbp.kind_of? ::Integer
|
713
|
-
@rs.breakpoints.sort.each { |addr, oct|
|
714
|
-
log "bpx at #{@rs.findsymbol(addr)}"
|
715
|
-
}
|
716
|
-
(0..3).each { |dr|
|
717
|
-
if @rs.regs_cache['dr7'] & (1 << (2*dr)) != 0
|
718
|
-
log "bphw #{{0=>'x', 1=>'w', 2=>'?', 3=>'r'}[(@rs.regs_cache['dr7'] >> (16+4*dr)) & 3]} at #{@rs.findsymbol(@rs.regs_cache["dr#{dr}"])}"
|
719
|
-
end
|
720
|
-
}
|
645
|
+
@command['bpx'] = lambda { |str|
|
646
|
+
@rs.bpx @rs.resolve(str)
|
721
647
|
}
|
722
|
-
@command['
|
723
|
-
|
648
|
+
@command['bphw'] = @command['hwbp'] = lambda { |str|
|
649
|
+
type, str = str.split(/\s+/, 2)
|
650
|
+
@rs.hwbp @rs.resolve(str.to_s), type
|
724
651
|
}
|
725
|
-
@command['bt'] = lambda { |
|
726
|
-
@command['d'] = lambda { |
|
727
|
-
@command['db'] = lambda { |
|
728
|
-
@command['dw'] = lambda { |
|
729
|
-
@command['dd'] = lambda { |
|
730
|
-
@command['r'] = lambda { |
|
731
|
-
r =
|
732
|
-
nil while ntok = lex.readtok and ntok.type == :space
|
652
|
+
@command['bt'] = lambda { |str| @rs.stacktrace { |a,t| add_log "#{'%x' % a} #{t}" } }
|
653
|
+
@command['d'] = lambda { |str| @dataptr = @rs.resolve(str) if str.length > 0 }
|
654
|
+
@command['db'] = lambda { |str| @datafmt = 'db' ; @dataptr = @rs.resolve(str) if str.length > 0 }
|
655
|
+
@command['dw'] = lambda { |str| @datafmt = 'dw' ; @dataptr = @rs.resolve(str) if str.length > 0 }
|
656
|
+
@command['dd'] = lambda { |str| @datafmt = 'dd' ; @dataptr = @rs.resolve(str) if str.length > 0 }
|
657
|
+
@command['r'] = lambda { |str|
|
658
|
+
r, str = str.split(/\s+/, 2)
|
733
659
|
if r == 'fl'
|
734
|
-
|
735
|
-
|
736
|
-
@rs.eflags ^= 1 << i
|
737
|
-
@rs.readregs
|
738
|
-
else
|
739
|
-
log "bad flag #{flag}"
|
740
|
-
end
|
741
|
-
elsif not @rs.regs_cache[r]
|
660
|
+
@rs.toggle_flag(str.to_sym)
|
661
|
+
elsif not @rs[r]
|
742
662
|
log "bad reg #{r}"
|
743
|
-
elsif
|
744
|
-
|
745
|
-
newval = int[]
|
746
|
-
if newval and newval.kind_of? ::Integer
|
747
|
-
@rs.send r+'=', newval
|
748
|
-
@rs.readregs
|
749
|
-
end
|
663
|
+
elsif str and str.length > 0
|
664
|
+
@rs[r] = @rs.resolve(str)
|
750
665
|
else
|
751
|
-
log "#{r} = #{@rs
|
666
|
+
log "#{r} = #{@rs[r]}"
|
752
667
|
end
|
753
668
|
}
|
754
|
-
@command['
|
755
|
-
|
756
|
-
lex.unreadtok tok
|
757
|
-
cont int[]
|
758
|
-
else cont
|
759
|
-
end
|
760
|
-
}
|
761
|
-
@command['syscall'] = lambda { |lex, int| syscall }
|
762
|
-
@command['singlestep'] = lambda { |lex, int| singlestep }
|
763
|
-
@command['stepover'] = lambda { |lex, int| stepover }
|
764
|
-
@command['stepout'] = lambda { |lex, int| stepout }
|
765
|
-
@command['g'] = lambda { |lex, int|
|
766
|
-
target = int[]
|
767
|
-
@rs.singlestep if @rs.regs_cache['eip'] == target
|
768
|
-
@rs.bpx target, true
|
769
|
-
cont
|
770
|
-
}
|
771
|
-
@command['u'] = lambda { |lex, int| @codeptr = int[] || break }
|
772
|
-
@command['has_pax'] = lambda { |lex, int|
|
773
|
-
if tok = lex.readtok
|
774
|
-
lex.unreadtok tok
|
775
|
-
if (int[] == 0)
|
776
|
-
@rs.set_pax false
|
777
|
-
else
|
778
|
-
@rs.set_pax true
|
779
|
-
end
|
780
|
-
else @rs.set_pax !@rs.has_pax
|
781
|
-
end
|
782
|
-
log "has_pax now #{@rs.has_pax}"
|
783
|
-
}
|
784
|
-
@command['loadsyms'] = lambda { |lex, int|
|
785
|
-
mapfile = ''
|
786
|
-
mapfile << ntok.raw while ntok = lex.readtok
|
787
|
-
if mapfile != ''
|
788
|
-
@rs.loadmap mapfile
|
789
|
-
else
|
790
|
-
@rs.loadallsyms
|
791
|
-
end
|
669
|
+
@command['g'] = lambda { |str|
|
670
|
+
@rs.go @rs.resolve(str)
|
792
671
|
}
|
793
|
-
@command['
|
794
|
-
@command['
|
795
|
-
|
796
|
-
sym << ntok.raw while ntok = lex.readtok
|
797
|
-
s = []
|
798
|
-
@rs.symbols.each { |k, v|
|
799
|
-
s << k if v =~ /#{sym}/
|
800
|
-
}
|
801
|
-
if s.empty?
|
802
|
-
log "unknown symbol #{sym}"
|
803
|
-
else
|
804
|
-
s.sort.each { |s_| log "#{'%08x' % s_} #{@rs.symbols_len[s_].to_s.ljust 6} #{@rs.findsymbol(s_)}" }
|
805
|
-
end
|
806
|
-
}
|
807
|
-
@command['delsym'] = lambda { |lex, int|
|
808
|
-
addr = int[]
|
809
|
-
log "deleted #{@rs.symbols.delete addr}"
|
810
|
-
@rs.symbols_len.delete addr
|
811
|
-
}
|
812
|
-
@command['addsym'] = lambda { |lex, int|
|
813
|
-
name = lex.readtok.raw
|
814
|
-
addr = int[]
|
815
|
-
if t = lex.readtok
|
816
|
-
lex.unreadtok t
|
817
|
-
@rs.symbols_len[addr] = int[]
|
818
|
-
else
|
819
|
-
@rs.symbols_len[addr] = 1
|
820
|
-
end
|
821
|
-
@rs.symbols[addr] = name
|
822
|
-
}
|
823
|
-
@command['help'] = lambda { |lex, int|
|
824
|
-
log 'commands: (addr/values are things like dword ptr [ebp+(4*byte [eax])] ), type <tab> to see all commands'
|
825
|
-
log ' bpx <addr>'
|
826
|
-
log ' bphw [r|w|x] <addr>: debug register breakpoint'
|
827
|
-
log ' bl: list breakpoints'
|
828
|
-
log ' bc: clear breakpoints'
|
829
|
-
log ' cont [<signr>]: continue the target sending a signal'
|
830
|
-
log ' d/db/dw/dd [<addr>]: change data type/address'
|
831
|
-
log ' g <addr>: set a bp at <addr> and run'
|
832
|
-
log ' has_pax [0|1]: set has_pax flag'
|
833
|
-
log ' loadsyms: load symbol information from mapped files (from /proc and disk)'
|
834
|
-
log ' ma <addr> <ascii>: write memory'
|
835
|
-
log ' mx <addr> <hex>: write memory'
|
836
|
-
log ' maps: list maps'
|
837
|
-
log ' r <reg> [<value>]: show/change register'
|
838
|
-
log ' r fl <flag>: toggle eflags bit'
|
839
|
-
log ' scansyms: scan memory for ELF headers'
|
840
|
-
log ' sym <symbol regex>: show symbol information'
|
841
|
-
log ' addsym <name> <addr> [<size>]'
|
842
|
-
log ' delsym <addr>'
|
843
|
-
log ' u <addr>: disassemble addr'
|
844
|
-
log ' reload: reload lindebug source'
|
845
|
-
log ' ruby <ruby code>: instance_evals ruby code in current instance'
|
846
|
-
log ' closeui: detach from the underlying RubStop'
|
847
|
-
log 'keys:'
|
848
|
-
log ' F5: continue'
|
849
|
-
log ' F6: syscall'
|
850
|
-
log ' F10: step over'
|
851
|
-
log ' F11: single step'
|
852
|
-
log ' F12: step out (til next ret)'
|
853
|
-
log ' pgup/pgdown: move command history'
|
854
|
-
}
|
855
|
-
@command['reload'] = lambda { |lex, int| load $0 ; load_commands }
|
856
|
-
@command['ruby'] = lambda { |lex, int|
|
857
|
-
str = ''
|
858
|
-
str << ntok.raw while ntok = lex.readtok
|
859
|
-
instance_eval str
|
860
|
-
}
|
861
|
-
@command['maps'] = lambda { |lex, int|
|
862
|
-
@rs.filemap.sort_by { |f, (b, e)| b }.each { |f, (b, e)|
|
863
|
-
log "#{f.ljust 20} #{'%08x' % b} - #{'%08x' % e}"
|
864
|
-
}
|
865
|
-
}
|
866
|
-
@command['ma'] = lambda { |lex, int|
|
867
|
-
addr = int[]
|
868
|
-
str = ''
|
869
|
-
str << ntok.raw while ntok = lex.readtok
|
870
|
-
@rs[addr, str.length] = str
|
871
|
-
}
|
872
|
-
@command['mx'] = lambda { |lex, int|
|
873
|
-
addr = int[]
|
874
|
-
data = [lex.readtok.raw].pack('H*')
|
875
|
-
@rs[addr, data.length] = data
|
876
|
-
}
|
877
|
-
@command['resize'] = lambda { |lex, int| resize }
|
878
|
-
@command['watch'] = lambda { |lex, int| @watch = ExprParser.parse(lex) ; updatedataptr }
|
879
|
-
@command['wd'] = lambda { |lex, int|
|
672
|
+
@command['u'] = lambda { |str| @codeptr = @rs.resolve(str) }
|
673
|
+
@command['ruby'] = lambda { |str| instance_eval str }
|
674
|
+
@command['wd'] = lambda { |str|
|
880
675
|
@focus = :data
|
881
|
-
if
|
882
|
-
|
883
|
-
@win_data_height = int[] || return
|
676
|
+
if str.length > 0
|
677
|
+
@win_data_height = @rs.resolve(str)
|
884
678
|
resize
|
885
679
|
end
|
886
680
|
}
|
887
|
-
@command['wc'] = lambda { |
|
681
|
+
@command['wc'] = lambda { |str|
|
888
682
|
@focus = :code
|
889
|
-
if
|
890
|
-
|
891
|
-
@win_code_height = int[] || return
|
683
|
+
if str.length > 0
|
684
|
+
@win_code_height = @rs.resolve(str)
|
892
685
|
resize
|
893
686
|
end
|
894
687
|
}
|
895
|
-
@command['wp'] = lambda { |
|
896
|
-
@command['?'] = lambda { |
|
897
|
-
val =
|
688
|
+
@command['wp'] = lambda { |str| @focus = :prompt }
|
689
|
+
@command['?'] = lambda { |str|
|
690
|
+
val = @rs.resolve(str)
|
898
691
|
log "#{val} 0x#{val.to_s(16)} #{[val].pack('L').inspect}"
|
899
692
|
}
|
900
|
-
@command['
|
693
|
+
@command['syscall'] = lambda { |str|
|
694
|
+
@rs.syscall_wait(str)
|
695
|
+
}
|
901
696
|
end
|
902
697
|
end
|
903
698
|
|
904
699
|
|
905
700
|
if $0 == __FILE__
|
906
701
|
require 'optparse'
|
907
|
-
|
702
|
+
opts = { :sc_cpu => 'Ia32' }
|
908
703
|
OptionParser.new { |opt|
|
909
|
-
opt.on('-m map', '--map filemap') { |f| filemap = f }
|
704
|
+
opt.on('-m map', '--map filemap') { |f| opts[:filemap] = f }
|
705
|
+
opt.on('--cpu cpu') { |c| opts[:sc_cpu] = c }
|
910
706
|
}.parse!(ARGV)
|
911
707
|
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
708
|
+
case ARGV.first
|
709
|
+
when /^(tcp:|udp:)?..+:/, /^ser:/
|
710
|
+
opts[:sc_cpu] = eval(opts[:sc_cpu]) if opts[:sc_cpu] =~ /[.(\s:]/
|
711
|
+
opts[:sc_cpu] = opts[:sc_cpu].new if opts[:sc_cpu].kind_of?(::Class)
|
712
|
+
rs = Metasm::GdbRemoteDebugger.new(ARGV.first, opts[:sc_cpu])
|
713
|
+
else
|
714
|
+
rs = Metasm::LinDebugger.new(ARGV.join(' '))
|
919
715
|
end
|
920
|
-
|
921
|
-
rs = Rubstop.new(ARGV.join(' '))
|
922
|
-
rs.loadmap(filemap) if filemap
|
716
|
+
rs.load_map(opts[:filemap]) if opts[:filemap]
|
923
717
|
LinDebug.new(rs).main_loop
|
924
718
|
end
|