metasm 1.0.3 → 1.0.4
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 +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
|