metasm 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +3 -0
- data.tar.gz.sig +0 -0
- data/Gemfile +3 -2
- data/metasm.gemspec +3 -2
- data/metasm.rb +4 -1
- data/metasm/compile_c.rb +2 -2
- data/metasm/cpu/arc/decode.rb +0 -21
- data/metasm/cpu/arc/main.rb +4 -4
- data/metasm/cpu/arm/decode.rb +1 -5
- data/metasm/cpu/arm/main.rb +3 -3
- data/metasm/cpu/arm64/decode.rb +2 -6
- data/metasm/cpu/arm64/main.rb +5 -5
- data/metasm/cpu/bpf/decode.rb +3 -35
- data/metasm/cpu/bpf/main.rb +5 -5
- data/metasm/cpu/bpf/render.rb +1 -12
- data/metasm/cpu/cy16/decode.rb +0 -6
- data/metasm/cpu/cy16/main.rb +3 -3
- data/metasm/cpu/cy16/render.rb +0 -11
- data/metasm/cpu/dalvik/decode.rb +4 -26
- data/metasm/cpu/dalvik/main.rb +20 -2
- data/metasm/cpu/dalvik/opcodes.rb +3 -2
- data/metasm/cpu/{mips/compile_c.rb → ebpf.rb} +5 -2
- 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/debug.rb +39 -1
- data/metasm/cpu/ia32/decode.rb +111 -90
- data/metasm/cpu/ia32/decompile.rb +45 -37
- data/metasm/cpu/ia32/main.rb +10 -0
- data/metasm/cpu/ia32/parse.rb +6 -0
- data/metasm/cpu/mcs51/decode.rb +1 -1
- data/metasm/cpu/mcs51/main.rb +11 -0
- data/metasm/cpu/mips/decode.rb +8 -18
- data/metasm/cpu/mips/main.rb +3 -3
- data/metasm/cpu/mips/opcodes.rb +1 -1
- data/metasm/cpu/msp430/decode.rb +2 -6
- data/metasm/cpu/msp430/main.rb +3 -3
- 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/metasm/cpu/ppc/decode.rb +0 -25
- data/metasm/cpu/ppc/main.rb +6 -6
- data/metasm/cpu/ppc/opcodes.rb +3 -4
- data/metasm/cpu/python/decode.rb +0 -20
- data/metasm/cpu/python/main.rb +1 -1
- data/metasm/cpu/sh4/decode.rb +2 -6
- data/metasm/cpu/sh4/main.rb +25 -23
- data/metasm/cpu/st20/decode.rb +0 -7
- data/metasm/cpu/webasm.rb +11 -0
- 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/compile_c.rb +13 -9
- data/metasm/cpu/x86_64/parse.rb +1 -1
- data/metasm/cpu/z80/decode.rb +0 -27
- data/metasm/cpu/z80/main.rb +3 -3
- data/metasm/cpu/z80/render.rb +0 -11
- data/metasm/debug.rb +43 -8
- data/metasm/decode.rb +62 -14
- data/metasm/decompile.rb +793 -466
- data/metasm/disassemble.rb +188 -131
- data/metasm/disassemble_api.rb +30 -17
- data/metasm/dynldr.rb +2 -2
- data/metasm/encode.rb +8 -2
- data/metasm/exe_format/autoexe.rb +2 -0
- data/metasm/exe_format/coff.rb +21 -3
- data/metasm/exe_format/coff_decode.rb +12 -0
- data/metasm/exe_format/coff_encode.rb +6 -3
- data/metasm/exe_format/dex.rb +13 -3
- data/metasm/exe_format/elf.rb +12 -2
- data/metasm/exe_format/elf_decode.rb +59 -1
- data/metasm/exe_format/main.rb +2 -0
- data/metasm/exe_format/mz.rb +1 -0
- data/metasm/exe_format/pe.rb +25 -3
- data/metasm/exe_format/wasm.rb +402 -0
- data/metasm/gui/dasm_decomp.rb +171 -95
- data/metasm/gui/dasm_graph.rb +61 -2
- data/metasm/gui/dasm_hex.rb +2 -2
- data/metasm/gui/dasm_main.rb +45 -19
- data/metasm/gui/debug.rb +13 -4
- data/metasm/gui/gtk.rb +12 -4
- data/metasm/main.rb +108 -103
- data/metasm/os/emulator.rb +175 -0
- data/metasm/os/main.rb +11 -6
- data/metasm/parse.rb +23 -12
- data/metasm/parse_c.rb +189 -135
- data/metasm/preprocessor.rb +16 -1
- data/misc/openrisc-parser.rb +79 -0
- data/samples/dasm-plugins/scanxrefs.rb +6 -4
- data/samples/dasm-plugins/selfmodify.rb +8 -8
- data/samples/dbg-plugins/trace_func.rb +1 -1
- data/samples/disassemble-gui.rb +14 -3
- data/samples/emubios.rb +251 -0
- data/samples/emudbg.rb +127 -0
- data/samples/lindebug.rb +79 -78
- data/samples/metasm-shell.rb +8 -8
- data/tests/all.rb +1 -1
- data/tests/expression.rb +2 -0
- data/tests/graph_layout.rb +1 -1
- data/tests/ia32.rb +1 -0
- data/tests/mips.rb +1 -1
- data/tests/preprocessor.rb +18 -0
- metadata +124 -6
- metadata.gz.sig +0 -0
data/samples/emudbg.rb
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
# Demo of using the EmuDebugger to work on the SSTIC2017 challenge (EBPF program)
|
4
|
+
|
5
|
+
require 'metasm'
|
6
|
+
include Metasm
|
7
|
+
require 'zlib'
|
8
|
+
|
9
|
+
bpf_prog = "eNrlWk9sVEUYn7f7nq8lxS5QpDZEinSxIUEKASnEhNYGQYS0WGsBY8LBUA4YKq" <<
|
10
|
+
"Dl8UICQRLkQFbBSLiUFpH2BJ7KbTi2F7NHDx4w8cCRI6mQdWa+b/6+t/voAhdtsp2dN/PNfN/8" <<
|
11
|
+
"vvl+38xb+gYRfzMhlJ3s08Q+Q6TskwZCutj3FaL+u78E2wvsQxugP29/ndcbtXyH6D/rbwsIaf" <<
|
12
|
+
"UIeVKpVAj+NbdCOcL651g5zMr3WbnqOjyPbzwSfUP2nKs24+HztifieStTIk/0H52EMszBPBfZ" <<
|
13
|
+
"d0/MD4KBmIWQCMcZ8j637B1hdrSzcgzLoYbf/ALqJ55jOVDC+dDuaFrrucJoH2btFTHOlL+X1w" <<
|
14
|
+
"nWya/+kCFHf0C9mV5vCfsewnNch5CN08afX54Vz3vO4TosKif6vW21/yHaowkYr6dg68315RDs" <<
|
15
|
+
"Ltn2RxMg14/4cNzO9h7Zx7+f6Pty5xetV3wYF+Yf8XB9sBzyLvv7h7/9QNhb4fZe8uN9sM586e" <<
|
16
|
+
"MzgJ/G83Emno8ZnvQW1vOA74wPdY5zTugza9l5R8xfqYwQ1A/LeBHMH595WfM+XNC83O7cS7S7" <<
|
17
|
+
"NYT5pHxADvm1/fozvyhwGvK9Gv6t/XWn/zHX62d4vgtxHBhFfXEe0w+5XgPnkv6WTx1/mx9b+2" <<
|
18
|
+
"Wrf5DXQ6yHW/ydfJ3v4D5jz7cb8+txuvyzuL5eHXFiBvXUfgn7YLkTN+RzU582C9eFzbsc41OE" <<
|
19
|
+
"88eXYV+p+FB1f99PtK+z2h8k2jdZ7ei3ozZOEmdu11qjPV50r+K2v2u130y0v2e1z6o4yeNcj4" <<
|
20
|
+
"yj32OJ6zvsAZ7SL/uRT+iPUI6x9eOq0rzeF2W2nsN5kCvmc6QR4yl/HggWs/tTp3+A/edE/9dU" <<
|
21
|
+
"PJ5mde7e47w/+tkMk+M91uc9y1/oVdQvj7zYgfb4IEeLOH+A+gY4f5AX+o6wfnzjhvzfM67HYh" <<
|
22
|
+
"jXkKOOXODIlZ5q/WcC7W9C/xzK5VLk5lmc2Yk4HUK/u4b2+MATdAvag/PTTXr8sjO+sCcAnLje" <<
|
23
|
+
"vIOyx5CjaXqZcnOGPTmN37iFX4ocA45+ksSF+5O0U9nRg+MStANxjteVxDoUibanSY7PAFL2GP" <<
|
24
|
+
"LUkOdygSvHAErY46M96CdFP01uXtuD+5nHc55j0c2On21J97O47Trw3rpLYJfhdwXpd0xC6meO" <<
|
25
|
+
"Y/vdCuU/Wm6uItchmrTjxFgIuSG9gHoibvQ7bX/ZsD+agLjG10Hox/q3IO584QMCiaopT631aw" <<
|
26
|
+
"L9LLnS04A0w7qTdD+SehfzjypJ+6aVfQH5G3jc13FVjIP8VWzIp80/L3FS+RIzrpvbcTI9jsV7" <<
|
27
|
+
"plAfXIcQ9mEIfFsORLZty9O0fWHLzQUEvkj9TfnxbPlpegr696+291dSf7meEI95PF8p1q8pIW" <<
|
28
|
+
"fr7Yl5AxJYcczsn6onjh8CX5ToTyjnxuFWvX8Ej6ypov+h+5b+0k+V/msy+MR3+MRHPnHiseKT" <<
|
29
|
+
"NZ6Nywq9fwoGT/JzUsXYT0n+y6v19uV6mHxyIcNfDDmLT3IZ/m7KcT5BvjbXW/BI5NhxMtuOBm" <<
|
30
|
+
"mHySMns+1QciaP5HV+IuzAPLMYpshxHkG/i7ePVlxc2uvEpUn56bMF4aLkTB7JZ+Oi5eYNe45W" <<
|
31
|
+
"XHw668SnoOwpLwgfLTe3IHy03LRhz+EEPl114tOi48izheCj5TjfPD8+hty8tucAnAOmII9X5z" <<
|
32
|
+
"ivNm+8Mr5orJMv0J+iO3A+6D+N4yyrnb9zngS+KCT6p+qN/UMIo6WAgMJ0uX2uo4PZeeRKlecx" <<
|
33
|
+
"Htkvz30D4F9f2+cU6Rc8vxR88o3237Lhv/Gec5h/nYbyBuBaDKucV4b1ONTaBxnnlQDtwnyN3w" <<
|
34
|
+
"MIfhl2zisXiZVHjWG+Q7c5+6Vb+2/Z8N+4DfDkflyTbwx5msUbJt80ZPO9xTeYF9ODaA/eb9E+" <<
|
35
|
+
"J+/clY4Pjy8y32yQeZvJN7uq4aHzPSWXdm6pluebcpxv8Hwk8Vc8c9Wx41p6/mzmzU0q/zR45l" <<
|
36
|
+
"q1vFnro+RMnvH0PY6wA/2j2Jgmx3hmYxKPTiN+KDtOZdtRUHYY/HIq2w4tZ/CLn8EvlhzjF8zb" <<
|
37
|
+
"4z3dFReXrjpxsc8zz4+LfZ5x7KmBS9o5JN7TBfxyC+6BRvB8HG+H+lhQm2eiX2Zf7fnkBfkmbu" <<
|
38
|
+
"ux7Ovvk7yK9+uDVfL+G51ol6/O/SsN3KMJOEcr+wbT7ZP9EueZsE4ewvnjM+1oF9zTNC+TduG9" <<
|
39
|
+
"DcYp6dfRNOKJeS3t1e8bhN2evO/YDfp6YLeMjxTPX9HNS2g3nKPNcagxjuxf9MAOPg7nKS0fqv" <<
|
40
|
+
"0n+MqJizzOvGbMt77Xs9Ytmizhew20f7XE+5H1voPnSQXj3lCet6qdV5Uf55BXcg6PXc3wY0PO" <<
|
41
|
+
"4rF8xv405TiPrZF4wv6KJtFO5JF4Hdp5E/04p+9FW408ScWjlmrxKEjlO8n/8v2OwrslPT5F02" <<
|
42
|
+
"V1X1OTBxu1v4wb/iL9JMGDSg+0H/Mwmc/J+2L53kmum7K7o05+7KiTH/2M+1aXH1UcRjwn4b6n" <<
|
43
|
+
"Ge97TVw7F4RrBm+2vCBv1sAvnTencF/CfVBzCn5ddeKXyqMdL8ijNfBL49Fo8r6FG3/fJ3hzac" <<
|
44
|
+
"b9uIe85Tl8uTTjftyW03yJccaUH8+Wn5Z+Jd/73nXwSfDEDbxHxvs9yafcDxqNfI+//1xp8qSX" <<
|
45
|
+
"zhdFD84zUk7dP2Nd5s+mfKr/4XxIEyWq4iXgw/fQWuN9oRzvHVZGx46P3n1T/x7BfB861HibfP" <<
|
46
|
+
"Tp4GA0cQ73KZzfmpfKdRt16ked+mGnfsCpP3DqA04d4uvdpfoce+TE8a92oP6S/5Lv4a+Q3X3t" <<
|
47
|
+
"fdEEnNPk7y2iid1Ovcepdzv1Lqfe6dTbnTr6UWv6+2d6Hp5vWIK/L2A4rb/94WX1nhT9cQfGgw" <<
|
48
|
+
"1Yrtpoy2X1k+fyRHv3wsb5z/Q7/3z9hrxdpHfv3naZ3zefsvPe5haHl1V9yqnfc+oPnfp9p45+" <<
|
49
|
+
"jnX+/qUd7yXajXzT9Ju/Lh3786X7TV+V9s3/U7/pfb5+y73FZFPXxq0yT5e/83lZv7Oh+DsCfK" <<
|
50
|
+
"2T+L2FvJ8IyLV/ePkvDyQvEw=="
|
51
|
+
|
52
|
+
raw = Zlib::Inflate.inflate(bpf_prog.unpack('m*').first)
|
53
|
+
dasm = Shellcode.decode(raw, EBPF.new(:latest, :little)).disassembler
|
54
|
+
dasm.backtrace_maxblocks_data = -1
|
55
|
+
|
56
|
+
dasm.callback_newinstr = lambda { |di|
|
57
|
+
if di.opcode.name == 'call'
|
58
|
+
case di.instruction.args.first.reduce
|
59
|
+
when 1; di.instruction.args[0] = ExpressionString.new(Expression[1], "bpf_map_lookup_elem")
|
60
|
+
when 2; di.instruction.args[0] = ExpressionString.new(Expression[1], "bpf_map_update_elem")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
di
|
64
|
+
}
|
65
|
+
# EmuDebugger needs an already disassembled binary
|
66
|
+
dasm.disassemble(0)
|
67
|
+
|
68
|
+
#Gui::DasmWindow.new.display(dasm)
|
69
|
+
|
70
|
+
# EmuDebugger has no memory except what is described in the binary
|
71
|
+
# We must manually add sections to the disassembler to 'map' the stack and working heap
|
72
|
+
stack = EncodedData.new("\x00" * 0x1000)
|
73
|
+
dasm.add_section(stack, 0x8000)
|
74
|
+
|
75
|
+
# ebpf works on network packets
|
76
|
+
eth = "\x11\x11\x11\x11\x11\x11\x22\x22\x22\x22\x22\x22\x08\x00"
|
77
|
+
ip = "\x45\x00\x00\x2c\x00\x00\x11\x11\x22\x11\x33\x33\x44\x44\x44\x44\x55\x55\x55\x55"
|
78
|
+
udp = "\x00\x00\x05\x39\x22\x22\x33\x33"
|
79
|
+
pld = "LUM{BvWQEdCrMfA}"
|
80
|
+
# forge the needed network headers
|
81
|
+
ip[2, 2] = [ip.length + udp.length + pld.length].pack('n')
|
82
|
+
udp[4, 2] = [udp.length + pld.length].pack('n')
|
83
|
+
pkt = EncodedData.new(eth + ip + udp + pld)
|
84
|
+
dasm.add_section(pkt, 0x9000)
|
85
|
+
|
86
|
+
# Initialize the emulator
|
87
|
+
dbg = Metasm::EmuDebugger.new(dasm)
|
88
|
+
# Set the initial state of the registers
|
89
|
+
dbg.set_reg_value(:r10, 0x8900)
|
90
|
+
# :packet is a special register used internally by some opcodes of the EBPF cpu (packet data store/load)
|
91
|
+
dbg.set_reg_value(:packet, 0x9000)
|
92
|
+
|
93
|
+
# This section emulates the kernel API for shared bpf maps
|
94
|
+
$bpf_map = { 0 => 0 }
|
95
|
+
dbg.callback_emulate_di = lambda { |di|
|
96
|
+
case di.opcode.name
|
97
|
+
when 'call'
|
98
|
+
case di.instruction.args.to_s
|
99
|
+
when /map_lookup/
|
100
|
+
key = dbg.resolve('dword ptr [r2]')
|
101
|
+
puts "bpf_map_lookup(#{dbg[:r1]}, #{key}) => #{$bpf_map[key].inspect}"
|
102
|
+
if $bpf_map[key]
|
103
|
+
dbg[:r0] = dbg[:r2]
|
104
|
+
dbg.memory_write_int(:r2, $bpf_map[key], 4)
|
105
|
+
else
|
106
|
+
dbg[:r0] = 0
|
107
|
+
end
|
108
|
+
when /map_update/
|
109
|
+
key = dbg.resolve('dword ptr [r2]')
|
110
|
+
val = dbg.resolve('dword ptr [r3]')
|
111
|
+
puts "bpf_map_update(#{dbg[:r1]}, #{key}, #{val})"
|
112
|
+
$bpf_map[key] = val
|
113
|
+
end
|
114
|
+
dbg.pc += di.bin_length
|
115
|
+
true
|
116
|
+
end
|
117
|
+
}
|
118
|
+
|
119
|
+
# Start the GUI
|
120
|
+
Gui::DbgWindow.new.display(dbg)
|
121
|
+
# some pretty settings for the initial view
|
122
|
+
dbg.gui.run_command('wd 6')
|
123
|
+
dbg.gui.run_command('wp 6')
|
124
|
+
dbg.gui.run_command('d :packet')
|
125
|
+
dbg.gui.parent.code.toggle_view(:graph)
|
126
|
+
|
127
|
+
Gui.main
|
data/samples/lindebug.rb
CHANGED
@@ -35,7 +35,7 @@ module Ansi
|
|
35
35
|
end
|
36
36
|
}.compact.join(';') << 'm'
|
37
37
|
end
|
38
|
-
def self.hline(len) "\e(0"<<'q'*len<<"\e(B" end
|
38
|
+
def self.hline(len) "\e(0" << 'q'*len << "\e(B" end
|
39
39
|
|
40
40
|
TIOCGWINSZ = 0x5413
|
41
41
|
TCGETS = 0x5401
|
@@ -124,10 +124,10 @@ class LinDebug
|
|
124
124
|
defretval
|
125
125
|
end
|
126
126
|
|
127
|
-
attr_accessor :dataptr, :codeptr, :
|
128
|
-
def initialize(
|
129
|
-
@
|
130
|
-
@
|
127
|
+
attr_accessor :dataptr, :codeptr, :dbg, :promptlog, :command
|
128
|
+
def initialize(dbg)
|
129
|
+
@dbg = dbg
|
130
|
+
@dbg.set_log_proc { |l| add_log l }
|
131
131
|
@datafmt = 'db'
|
132
132
|
|
133
133
|
@prompthistlen = 20
|
@@ -148,7 +148,7 @@ class LinDebug
|
|
148
148
|
end
|
149
149
|
|
150
150
|
def init_rs
|
151
|
-
@codeptr = @dataptr = @
|
151
|
+
@codeptr = @dataptr = @dbg.pc # avoid initial faults
|
152
152
|
end
|
153
153
|
|
154
154
|
def main_loop
|
@@ -211,14 +211,14 @@ class LinDebug
|
|
211
211
|
|
212
212
|
def _updateregs
|
213
213
|
pvrsz = 0
|
214
|
-
words = @
|
214
|
+
words = @dbg.register_list.map { |r|
|
215
215
|
rs = r.to_s.rjust(pvrsz)
|
216
216
|
pvrsz = rs.length
|
217
|
-
rv = @
|
218
|
-
["#{rs}=%0#{@
|
217
|
+
rv = @dbg[r]
|
218
|
+
["#{rs}=%0#{@dbg.register_size[r]/4}X " % rv,
|
219
219
|
(@oldregs[r] != rv)]
|
220
|
-
} + @
|
221
|
-
fv = @
|
220
|
+
} + @dbg.flag_list.map { |fl|
|
221
|
+
fv = @dbg.get_flag(fl)
|
222
222
|
[fv ? fl.to_s.upcase : fl.to_s.downcase,
|
223
223
|
(@oldregs[fl] != fv)]
|
224
224
|
}
|
@@ -253,24 +253,24 @@ class LinDebug
|
|
253
253
|
def _updatecode
|
254
254
|
if @codeptr
|
255
255
|
addr = @codeptr
|
256
|
-
elsif @oldregs[@
|
257
|
-
addr = @oldregs[@
|
256
|
+
elsif @oldregs[@dbg.register_pc] and @oldregs[@dbg.register_pc] < @dbg.pc and @oldregs[@dbg.register_pc] + 8 >= @dbg.pc
|
257
|
+
addr = @oldregs[@dbg.register_pc]
|
258
258
|
else
|
259
|
-
addr = @
|
259
|
+
addr = @dbg.pc
|
260
260
|
end
|
261
261
|
@codeptr = addr
|
262
262
|
|
263
|
-
addrsz = @
|
263
|
+
addrsz = @dbg.register_size[@dbg.register_pc]
|
264
264
|
addrfmt = "%0#{addrsz/4}X"
|
265
|
-
if not @
|
265
|
+
if not @dbg.addr2module(addr) and @dbg.shortname !~ /remote/
|
266
266
|
base = addr & ((1 << addrsz) - 0x1000)
|
267
267
|
@noelfsig ||= {} # cache elfmagic notfound
|
268
268
|
if not @noelfsig[base] and base < ((1 << addrsz) - 0x1_0000)
|
269
269
|
self.statusline = " scanning for elf header at #{addrfmt % base}"
|
270
270
|
128.times {
|
271
271
|
@statusline = " scanning for elf header at #{addrfmt % base}"
|
272
|
-
if not @noelfsig[base] and @
|
273
|
-
@
|
272
|
+
if not @noelfsig[base] and @dbg[base, Metasm::ELF::MAGIC.length] == Metasm::ELF::MAGIC
|
273
|
+
@dbg.loadsyms(base, base.to_s(16))
|
274
274
|
break
|
275
275
|
else
|
276
276
|
@noelfsig[base] = true # XXX an elf may be mmaped here later..
|
@@ -284,35 +284,35 @@ class LinDebug
|
|
284
284
|
|
285
285
|
text = ''
|
286
286
|
text << Color[:border]
|
287
|
-
title = @
|
287
|
+
title = @dbg.addrname(addr)
|
288
288
|
pre = [@console_width-100, 6].max
|
289
289
|
post = @console_width - (pre + title.length + 2)
|
290
290
|
text << Ansi.hline(pre) << ' ' << title << ' ' << Ansi.hline(post) << Color[:normal] << "\n"
|
291
291
|
|
292
292
|
seg = ''
|
293
|
-
seg = ('%04X' % @
|
293
|
+
seg = ('%04X' % @dbg['cs']) << ':' if @dbg.cpu.shortname =~ /ia32|x64/
|
294
294
|
|
295
295
|
cnt = @win_code_height
|
296
296
|
while (cnt -= 1) > 0
|
297
|
-
if @
|
298
|
-
text << (' ' << @
|
297
|
+
if @dbg.symbols[addr]
|
298
|
+
text << (' ' << @dbg.symbols[addr] << ?:) << Ansi::ClearLineAfter << "\n"
|
299
299
|
break if (cnt -= 1) <= 0
|
300
300
|
end
|
301
|
-
text << Color[:hilight] if addr == @
|
301
|
+
text << Color[:hilight] if addr == @dbg.pc
|
302
302
|
text << seg
|
303
|
-
if @
|
304
|
-
text << (addrfmt % (addr - 16*@
|
303
|
+
if @dbg.shortname =~ /remote/ and @dbg.realmode
|
304
|
+
text << (addrfmt % (addr - 16*@dbg['cs']))
|
305
305
|
else
|
306
306
|
text << (addrfmt % addr)
|
307
307
|
end
|
308
|
-
di = @
|
309
|
-
di = nil if di and addr < @
|
308
|
+
di = @dbg.di_at(addr)
|
309
|
+
di = nil if di and addr < @dbg.pc and addr+di.bin_length > @dbg.pc
|
310
310
|
len = (di ? di.bin_length : 1)
|
311
311
|
text << ' '
|
312
|
-
text << @
|
312
|
+
text << @dbg.memory[addr, [len, 10].min].to_s.unpack('C*').map { |c| '%02X' % c }.join.ljust(22)
|
313
313
|
if di
|
314
314
|
text <<
|
315
|
-
if addr == @
|
315
|
+
if addr == @dbg.pc
|
316
316
|
"*#{di.instruction}".ljust([@console_width-(addrsz/4+seg.length+24), 0].max)
|
317
317
|
else
|
318
318
|
" #{di.instruction}" << Ansi::ClearLineAfter
|
@@ -320,7 +320,7 @@ class LinDebug
|
|
320
320
|
else
|
321
321
|
text << ' <unk>' << Ansi::ClearLineAfter
|
322
322
|
end
|
323
|
-
text << Color[:normal] if addr == @
|
323
|
+
text << Color[:normal] if addr == @dbg.pc
|
324
324
|
addr += len
|
325
325
|
text << "\n"
|
326
326
|
end
|
@@ -332,7 +332,7 @@ class LinDebug
|
|
332
332
|
end
|
333
333
|
|
334
334
|
def _updatedata
|
335
|
-
addrsz = @
|
335
|
+
addrsz = @dbg.register_size[@dbg.register_pc]
|
336
336
|
addrfmt = "%0#{addrsz/4}X"
|
337
337
|
|
338
338
|
@dataptr &= ((1 << addrsz) - 1)
|
@@ -340,17 +340,17 @@ class LinDebug
|
|
340
340
|
|
341
341
|
text = ''
|
342
342
|
text << Color[:border]
|
343
|
-
title = @
|
343
|
+
title = @dbg.addrname(addr)
|
344
344
|
pre = [@console_width-100, 6].max
|
345
345
|
post = [@console_width - (pre + title.length + 2), 0].max
|
346
346
|
text << Ansi.hline(pre) << ' ' << title << ' ' << Ansi.hline(post) << Color[:normal] << "\n"
|
347
347
|
|
348
348
|
seg = ''
|
349
|
-
seg = ('%04X' % @
|
349
|
+
seg = ('%04X' % @dbg['ds']) << ':' if @dbg.cpu.shortname =~ /^ia32/
|
350
350
|
|
351
351
|
cnt = @win_data_height
|
352
352
|
while (cnt -= 1) > 0
|
353
|
-
raw = @
|
353
|
+
raw = @dbg.memory[addr, 16].to_s
|
354
354
|
text << seg << (addrfmt % addr) << ' '
|
355
355
|
case @datafmt
|
356
356
|
when 'db'; text << raw[0,8].unpack('C*').map { |c| '%02x ' % c }.join << ' ' <<
|
@@ -449,20 +449,21 @@ class LinDebug
|
|
449
449
|
end
|
450
450
|
|
451
451
|
def preupdate
|
452
|
-
@
|
453
|
-
@
|
452
|
+
@dbg.register_list.each { |r| @oldregs[r] = @dbg[r] }
|
453
|
+
@dbg.flag_list.each { |fl| @oldregs[fl] = @dbg.get_flag(fl) }
|
454
454
|
end
|
455
455
|
|
456
456
|
def updatecodeptr
|
457
|
-
@codeptr ||= @
|
458
|
-
if @codeptr > @
|
459
|
-
@codeptr = @
|
460
|
-
elsif @codeptr != @
|
457
|
+
@codeptr ||= @dbg.pc
|
458
|
+
if @codeptr > @dbg.pc or @codeptr < @dbg.pc - 6*@win_code_height
|
459
|
+
@codeptr = @dbg.pc
|
460
|
+
elsif @codeptr != @dbg.pc
|
461
461
|
addr = @codeptr
|
462
462
|
addrs = []
|
463
|
-
while addr
|
463
|
+
while addr <= @dbg.pc
|
464
464
|
addrs << addr
|
465
|
-
|
465
|
+
addrs << addr if @dbg.symbols[addr]
|
466
|
+
o = ((di = @dbg.di_at(addr)) ? di.bin_length : 0)
|
466
467
|
addr += ((o == 0) ? 1 : o)
|
467
468
|
end
|
468
469
|
if addrs.length > @win_code_height-4
|
@@ -478,35 +479,35 @@ class LinDebug
|
|
478
479
|
def singlestep
|
479
480
|
self.statusline = ' target singlestepping...'
|
480
481
|
preupdate
|
481
|
-
@
|
482
|
+
@dbg.singlestep_wait
|
482
483
|
updatecodeptr
|
483
484
|
@statusline = nil
|
484
485
|
end
|
485
486
|
def stepover
|
486
487
|
self.statusline = ' target running...'
|
487
488
|
preupdate
|
488
|
-
@
|
489
|
+
@dbg.stepover_wait
|
489
490
|
updatecodeptr
|
490
491
|
@statusline = nil
|
491
492
|
end
|
492
493
|
def cont(*a)
|
493
494
|
self.statusline = ' target running...'
|
494
495
|
preupdate
|
495
|
-
@
|
496
|
+
@dbg.continue_wait(*a)
|
496
497
|
updatecodeptr
|
497
498
|
@statusline = nil
|
498
499
|
end
|
499
500
|
def stepout
|
500
501
|
self.statusline = ' target running...'
|
501
502
|
preupdate
|
502
|
-
@
|
503
|
+
@dbg.stepout_wait
|
503
504
|
updatecodeptr
|
504
505
|
@statusline = nil
|
505
506
|
end
|
506
507
|
def syscall
|
507
508
|
self.statusline = ' target running to next syscall...'
|
508
509
|
preupdate
|
509
|
-
@
|
510
|
+
@dbg.syscall_wait
|
510
511
|
updatecodeptr
|
511
512
|
@statusline = nil
|
512
513
|
end
|
@@ -552,9 +553,9 @@ class LinDebug
|
|
552
553
|
when :data
|
553
554
|
@dataptr -= 16
|
554
555
|
when :code
|
555
|
-
@codeptr ||= @
|
556
|
+
@codeptr ||= @dbg.pc
|
556
557
|
@codeptr -= (1..10).find { |off|
|
557
|
-
di = @
|
558
|
+
di = @dbg.di_at(@codeptr-off)
|
558
559
|
di.bin_length == off if di
|
559
560
|
} || 10
|
560
561
|
end
|
@@ -573,8 +574,8 @@ class LinDebug
|
|
573
574
|
when :data
|
574
575
|
@dataptr += 16
|
575
576
|
when :code
|
576
|
-
@codeptr ||= @
|
577
|
-
di = @
|
577
|
+
@codeptr ||= @dbg.pc
|
578
|
+
di = @dbg.di_at(@codeptr)
|
578
579
|
@codeptr += (di ? (di.bin_length || 1) : 1)
|
579
580
|
end
|
580
581
|
when :left; @promptpos -= 1 if @promptpos > 0
|
@@ -588,10 +589,10 @@ class LinDebug
|
|
588
589
|
when :prompt; @log_off += @win_prpt_height-3
|
589
590
|
when :data; @dataptr -= 16*(@win_data_height-1)
|
590
591
|
when :code
|
591
|
-
@codeptr ||= @
|
592
|
+
@codeptr ||= @dbg.pc
|
592
593
|
(@win_code_height-1).times {
|
593
594
|
@codeptr -= (1..10).find { |off|
|
594
|
-
di = @
|
595
|
+
di = @dbg.di_at(@codeptr-off)
|
595
596
|
di.bin_length == off if di
|
596
597
|
} || 10
|
597
598
|
}
|
@@ -601,8 +602,8 @@ class LinDebug
|
|
601
602
|
when :prompt; @log_off -= @win_prpt_height-3
|
602
603
|
when :data; @dataptr += 16*(@win_data_height-1)
|
603
604
|
when :code
|
604
|
-
@codeptr ||= @
|
605
|
-
(@win_code_height-1).times { @codeptr += ((o = @
|
605
|
+
@codeptr ||= @dbg.pc
|
606
|
+
(@win_code_height-1).times { @codeptr += ((o = @dbg.di_at(@codeptr)) ? [o.bin_length, 1].max : 1) }
|
606
607
|
end
|
607
608
|
when ?\t
|
608
609
|
if not @promptbuf[0, @promptpos].include? ' '
|
@@ -631,67 +632,67 @@ class LinDebug
|
|
631
632
|
|
632
633
|
def load_commands
|
633
634
|
@command['kill'] = lambda { |str|
|
634
|
-
@
|
635
|
+
@dbg.kill
|
635
636
|
@running = false
|
636
637
|
log 'killed'
|
637
638
|
}
|
638
639
|
@command['quit'] = @command['detach'] = @command['exit'] = lambda { |str|
|
639
|
-
@
|
640
|
+
@dbg.detach
|
640
641
|
@running = false
|
641
642
|
}
|
642
643
|
@command['closeui'] = lambda { |str|
|
643
644
|
@running = false
|
644
645
|
}
|
645
646
|
@command['bpx'] = lambda { |str|
|
646
|
-
@
|
647
|
+
@dbg.bpx @dbg.resolve(str)
|
647
648
|
}
|
648
649
|
@command['bphw'] = @command['hwbp'] = lambda { |str|
|
649
650
|
type, str = str.split(/\s+/, 2)
|
650
|
-
@
|
651
|
+
@dbg.hwbp @dbg.resolve(str.to_s), type
|
651
652
|
}
|
652
|
-
@command['bt'] = lambda { |str| @
|
653
|
-
@command['d'] = lambda { |str| @dataptr = @
|
654
|
-
@command['db'] = lambda { |str| @datafmt = 'db' ; @dataptr = @
|
655
|
-
@command['dw'] = lambda { |str| @datafmt = 'dw' ; @dataptr = @
|
656
|
-
@command['dd'] = lambda { |str| @datafmt = 'dd' ; @dataptr = @
|
653
|
+
@command['bt'] = lambda { |str| @dbg.stacktrace { |a,t| add_log "#{'%x' % a} #{t}" } }
|
654
|
+
@command['d'] = lambda { |str| @dataptr = @dbg.resolve(str) if str.length > 0 }
|
655
|
+
@command['db'] = lambda { |str| @datafmt = 'db' ; @dataptr = @dbg.resolve(str) if str.length > 0 }
|
656
|
+
@command['dw'] = lambda { |str| @datafmt = 'dw' ; @dataptr = @dbg.resolve(str) if str.length > 0 }
|
657
|
+
@command['dd'] = lambda { |str| @datafmt = 'dd' ; @dataptr = @dbg.resolve(str) if str.length > 0 }
|
657
658
|
@command['r'] = lambda { |str|
|
658
659
|
r, str = str.split(/\s+/, 2)
|
659
660
|
if r == 'fl'
|
660
|
-
@
|
661
|
-
elsif not @
|
661
|
+
@dbg.toggle_flag(str.to_sym)
|
662
|
+
elsif not @dbg[r]
|
662
663
|
log "bad reg #{r}"
|
663
664
|
elsif str and str.length > 0
|
664
|
-
@
|
665
|
+
@dbg[r] = @dbg.resolve(str)
|
665
666
|
else
|
666
|
-
log "#{r} = #{@
|
667
|
+
log "#{r} = #{@dbg[r]}"
|
667
668
|
end
|
668
669
|
}
|
669
670
|
@command['g'] = lambda { |str|
|
670
|
-
@
|
671
|
+
@dbg.go @dbg.resolve(str)
|
671
672
|
}
|
672
|
-
@command['u'] = lambda { |str| @codeptr = @
|
673
|
+
@command['u'] = lambda { |str| @codeptr = @dbg.resolve(str) }
|
673
674
|
@command['ruby'] = lambda { |str| instance_eval str }
|
674
675
|
@command['wd'] = lambda { |str|
|
675
676
|
@focus = :data
|
676
677
|
if str.length > 0
|
677
|
-
@win_data_height = @
|
678
|
+
@win_data_height = @dbg.resolve(str)
|
678
679
|
resize
|
679
680
|
end
|
680
681
|
}
|
681
682
|
@command['wc'] = lambda { |str|
|
682
683
|
@focus = :code
|
683
684
|
if str.length > 0
|
684
|
-
@win_code_height = @
|
685
|
+
@win_code_height = @dbg.resolve(str)
|
685
686
|
resize
|
686
687
|
end
|
687
688
|
}
|
688
689
|
@command['wp'] = lambda { |str| @focus = :prompt }
|
689
690
|
@command['?'] = lambda { |str|
|
690
|
-
val = @
|
691
|
+
val = @dbg.resolve(str)
|
691
692
|
log "#{val} 0x#{val.to_s(16)} #{[val].pack('L').inspect}"
|
692
693
|
}
|
693
694
|
@command['syscall'] = lambda { |str|
|
694
|
-
@
|
695
|
+
@dbg.syscall_wait(str)
|
695
696
|
}
|
696
697
|
end
|
697
698
|
end
|
@@ -709,10 +710,10 @@ if $0 == __FILE__
|
|
709
710
|
when /^(tcp:|udp:)?..+:/, /^ser:/
|
710
711
|
opts[:sc_cpu] = eval(opts[:sc_cpu]) if opts[:sc_cpu] =~ /[.(\s:]/
|
711
712
|
opts[:sc_cpu] = opts[:sc_cpu].new if opts[:sc_cpu].kind_of?(::Class)
|
712
|
-
|
713
|
+
dbg = Metasm::GdbRemoteDebugger.new(ARGV.first, opts[:sc_cpu])
|
713
714
|
else
|
714
|
-
|
715
|
+
dbg = Metasm::LinDebugger.new(ARGV.join(' '))
|
715
716
|
end
|
716
|
-
|
717
|
-
LinDebug.new(
|
717
|
+
dbg.load_map(opts[:filemap]) if opts[:filemap]
|
718
|
+
LinDebug.new(dbg).main_loop
|
718
719
|
end
|