metasm 1.0.2 → 1.0.3
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
- data/.gitignore +2 -0
- data/Gemfile +1 -0
- data/doc/code_organisation.txt +1 -1
- data/metasm.gemspec +1 -1
- data/metasm.rb +2 -1
- data/metasm/cpu/arc/decode.rb +3 -3
- data/metasm/cpu/arm/decode.rb +2 -2
- data/metasm/cpu/ia32/compile_c.rb +18 -2
- data/metasm/cpu/ia32/decode.rb +9 -4
- data/metasm/cpu/ia32/decompile.rb +22 -8
- data/metasm/cpu/ia32/opcodes.rb +5 -5
- data/metasm/cpu/mcs51.rb +8 -0
- data/metasm/cpu/mcs51/decode.rb +99 -0
- data/metasm/cpu/mcs51/main.rb +76 -0
- data/metasm/cpu/mcs51/opcodes.rb +120 -0
- data/metasm/cpu/mips/decode.rb +5 -4
- data/metasm/cpu/st20.rb +9 -0
- data/metasm/cpu/st20/decode.rb +180 -0
- data/metasm/cpu/st20/decompile.rb +283 -0
- data/metasm/cpu/st20/main.rb +37 -0
- data/metasm/cpu/st20/opcodes.rb +140 -0
- data/metasm/cpu/x86_64/encode.rb +4 -2
- data/metasm/cpu/x86_64/opcodes.rb +4 -2
- data/metasm/decode.rb +16 -15
- data/metasm/decompile.rb +1 -1
- data/metasm/disassemble.rb +3 -1
- data/metasm/disassemble_api.rb +3 -1
- data/metasm/dynldr.rb +9 -3
- data/metasm/encode.rb +2 -2
- data/metasm/exe_format/coff.rb +3 -1
- data/metasm/exe_format/coff_decode.rb +5 -3
- data/metasm/exe_format/elf.rb +4 -0
- data/metasm/exe_format/elf_decode.rb +1 -2
- data/metasm/exe_format/elf_encode.rb +4 -1
- data/metasm/exe_format/macho.rb +20 -6
- data/metasm/exe_format/pe.rb +1 -1
- data/metasm/exe_format/serialstruct.rb +1 -1
- data/metasm/gui.rb +1 -1
- data/metasm/gui/dasm_hex.rb +2 -2
- data/metasm/gui/dasm_main.rb +8 -8
- data/metasm/gui/debug.rb +4 -4
- data/metasm/gui/gtk.rb +1 -1
- data/metasm/gui/qt.rb +2 -2
- data/metasm/gui/win32.rb +1 -1
- data/metasm/main.rb +11 -6
- data/metasm/os/windows.rb +26 -23
- data/misc/hexdump.rb +2 -2
- data/misc/objdiff.rb +4 -1
- data/misc/objscan.rb +1 -1
- data/samples/dasm-plugins/bindiff.rb +1 -1
- data/samples/dasm-plugins/scanxrefs.rb +2 -1
- data/samples/dynamic_ruby.rb +24 -25
- data/samples/elfencode.rb +15 -0
- data/samples/exeencode.rb +2 -2
- data/samples/metasm-shell.rb +67 -55
- data/tests/mcs51.rb +27 -0
- metadata +13 -2
@@ -365,8 +365,7 @@ class ELF
|
|
365
365
|
# marks a symbol as @encoded.export (from s.value, using segments or sections)
|
366
366
|
def decode_symbol_export(s)
|
367
367
|
if s.name and s.shndx != 'UNDEF' and %w[NOTYPE OBJECT FUNC].include?(s.type)
|
368
|
-
if @header.type == 'REL'
|
369
|
-
sec = @sections[s.shndx]
|
368
|
+
if @header.type == 'REL' and s.shndx.kind_of?(::Integer) and sec = @sections[s.shndx]
|
370
369
|
o = sec.offset + s.value
|
371
370
|
elsif not o = addr_to_off(s.value)
|
372
371
|
# allow to point to end of segment
|
@@ -11,7 +11,7 @@ module Metasm
|
|
11
11
|
class ELF
|
12
12
|
class Header
|
13
13
|
def set_default_values elf
|
14
|
-
@magic ||=
|
14
|
+
@magic ||= ELF::MAGIC
|
15
15
|
@e_class ||= elf.bitsize.to_s
|
16
16
|
@data ||= (elf.endianness == :big ? 'MSB' : 'LSB')
|
17
17
|
@version ||= 'CURRENT'
|
@@ -62,6 +62,7 @@ class ELF
|
|
62
62
|
return if name_p and sne.data[@name_p, @name.length+1] == @name+0.chr
|
63
63
|
return if @name_p = sne.data.index(@name+0.chr)
|
64
64
|
@name_p = sne.virtsize
|
65
|
+
@name.force_encoding('BINARY') if name.respond_to?(:force_encoding)
|
65
66
|
sne << @name << 0
|
66
67
|
end
|
67
68
|
end
|
@@ -92,6 +93,7 @@ class ELF
|
|
92
93
|
return if name_p and s[@name_p, @name.length+1] == @name+0.chr
|
93
94
|
return if @name_p = s.index(@name+0.chr)
|
94
95
|
@name_p = strtab.length
|
96
|
+
@name.force_encoding('BINARY') if name.respond_to?(:force_encoding)
|
95
97
|
strtab << @name << 0
|
96
98
|
end
|
97
99
|
end
|
@@ -519,6 +521,7 @@ class ELF
|
|
519
521
|
add_str = lambda { |n|
|
520
522
|
if n and n != '' and not ret = strtab.encoded.data.index(n + 0.chr)
|
521
523
|
ret = strtab.encoded.virtsize
|
524
|
+
n.force_encoding('BINARY') if n.respond_to?(:force_encoding)
|
522
525
|
strtab.encoded << n << 0
|
523
526
|
end
|
524
527
|
ret || 0
|
data/metasm/exe_format/macho.rb
CHANGED
@@ -43,6 +43,8 @@ class MachO < ExeFormat
|
|
43
43
|
9 => '8600', 10 => '8650', 11 => '8800', 12 => 'UVAXIII',
|
44
44
|
},
|
45
45
|
'ROMP' => { 0 => 'ALL', 1 => 'PC', 2 => 'APC', 3 => '135',
|
46
|
+
},
|
47
|
+
'NS32032' => { # same for NS*
|
46
48
|
0 => 'MMAX_ALL', 1 => 'MMAX_DPC', 2 => 'SQT',
|
47
49
|
3 => 'MMAX_APC_FPU', 4 => 'MMAX_APC_FPA', 5 => 'MMAX_XPC',
|
48
50
|
},
|
@@ -138,7 +140,11 @@ class MachO < ExeFormat
|
|
138
140
|
SEC_TYPE = {
|
139
141
|
0 => 'REGULAR', 1 => 'ZEROFILL', 2 => 'CSTRING_LITERALS', 3 => '4BYTE_LITERALS',
|
140
142
|
4 => '8BYTE_LITERALS', 5 => 'LITERAL_POINTERS', 6 => 'NON_LAZY_SYMBOL_POINTERS',
|
141
|
-
7 => 'LAZY_SYMBOL_POINTERS', 8 => 'SYMBOL_STUBS', 9 => 'MOD_INIT_FUNC_POINTERS'
|
143
|
+
7 => 'LAZY_SYMBOL_POINTERS', 8 => 'SYMBOL_STUBS', 9 => 'MOD_INIT_FUNC_POINTERS',
|
144
|
+
10 => 'MOD_TERM_FUNC_POINTERS', 11 => 'COALESCED', 12 => 'GB_ZEROFILL', 13 => 'INTERPOSING',
|
145
|
+
14 => '16BYTE_LITERALS', 15 => 'DTRACE_DOF', 16 => 'LAZY_DYLIB_SYMBOL_POINTERS',
|
146
|
+
17 => 'THREAD_LOCAL_REGULAR', 18 => 'THREAD_LOCAL_ZEROFILL', 19 => 'THREAD_LOCAL_VARIABLES',
|
147
|
+
20 => 'THREAD_LOCAL_VARIABLE_POINTERS', 21 => 'THREAD_LOCAL_INIT_FUNCTION_POINTERS'
|
142
148
|
}
|
143
149
|
|
144
150
|
class SerialStruct < Metasm::SerialStruct
|
@@ -628,22 +634,26 @@ class MachO < ExeFormat
|
|
628
634
|
when 'NON_LAZY_SYMBOL_POINTERS', 'LAZY_SYMBOL_POINTERS'
|
629
635
|
edata = seg.encoded
|
630
636
|
off = sec.offset - seg.fileoff
|
631
|
-
(sec.size /
|
637
|
+
(sec.size / sizeof_xword).times { |i|
|
632
638
|
sidx = indsymtab[sec.res1+i]
|
639
|
+
if not sidx
|
640
|
+
puts "W: osx: invalid symbol pointer index #{i} ?" if $VERBOSE
|
641
|
+
next
|
642
|
+
end
|
633
643
|
case IND_SYM_IDX[sidx]
|
634
644
|
when 'INDIRECT_SYMBOL_LOCAL' # base reloc: add delta from prefered image base
|
635
645
|
edata.ptr = off
|
636
|
-
addr =
|
646
|
+
addr = decode_xword(edata)
|
637
647
|
if s = segment_at(addr)
|
638
648
|
label = label_at(s.encoded, s.encoded.ptr, "xref_#{Expression[addr]}")
|
639
|
-
seg.encoded.reloc[off] = Metasm::Relocation.new(Expression[label],
|
649
|
+
seg.encoded.reloc[off] = Metasm::Relocation.new(Expression[label], "u#@size".to_sym, @endianness)
|
640
650
|
end
|
641
651
|
when 'INDIRECT_SYMBOL_ABS' # nothing
|
642
652
|
else
|
643
653
|
sym = @symbols[sidx]
|
644
|
-
seg.encoded.reloc[off] = Metasm::Relocation.new(Expression[sym.name],
|
654
|
+
seg.encoded.reloc[off] = Metasm::Relocation.new(Expression[sym.name],"u#@size".to_sym, @endianness)
|
645
655
|
end
|
646
|
-
off +=
|
656
|
+
off += sizeof_xword
|
647
657
|
}
|
648
658
|
when 'SYMBOL_STUBS'
|
649
659
|
# TODO next unless arch == 386 and sec.attrs & SELF_MODIFYING_CODE and sec.res2 == 5
|
@@ -653,6 +663,10 @@ class MachO < ExeFormat
|
|
653
663
|
off = sec.offset - seg.fileoff + 1
|
654
664
|
(sec.size / 5).times { |i|
|
655
665
|
sidx = indsymtab[sec.res1+i]
|
666
|
+
if not sidx
|
667
|
+
puts "W: osx: invalid symbol stub index #{i} ?" if $VERBOSE
|
668
|
+
next
|
669
|
+
end
|
656
670
|
case IND_SYM_IDX[sidx]
|
657
671
|
when 'INDIRECT_SYMBOL_LOCAL' # base reloc: add delta from prefered image base
|
658
672
|
edata.ptr = off
|
data/metasm/exe_format/pe.rb
CHANGED
@@ -330,7 +330,7 @@ EOS
|
|
330
330
|
# compute Mandiant "importhash"
|
331
331
|
def imphash
|
332
332
|
lst = []
|
333
|
-
@imports.each { |id|
|
333
|
+
@imports.to_a.each { |id|
|
334
334
|
ln = id.libname.downcase.sub(/.(dll|sys|ocx)$/, '')
|
335
335
|
id.imports.each { |i|
|
336
336
|
if not i.name and ordtable = WindowsExports::IMPORT_HASH[ln]
|
@@ -56,7 +56,7 @@ class << self
|
|
56
56
|
|
57
57
|
# a fixed-size memory chunk
|
58
58
|
def mem(name, len, defval='')
|
59
|
-
new_field(name, lambda { |exe, me| exe.curencoded.read(len) }, lambda { |exe, me, val| val[0, len].ljust(len, 0.chr) }, lambda { |exe, me| len }, defval)
|
59
|
+
new_field(name, lambda { |exe, me| exe.curencoded.read(len) }, lambda { |exe, me, val| d = val[0, len].ljust(len, 0.chr) ; d.force_encoding('BINARY') if d.respond_to?(:force_encoding) ; d }, lambda { |exe, me| len }, defval)
|
60
60
|
end
|
61
61
|
# a fixed-size string, 0-padded
|
62
62
|
def str(name, len, defval='')
|
data/metasm/gui.rb
CHANGED
data/metasm/gui/dasm_hex.rb
CHANGED
data/metasm/gui/dasm_main.rb
CHANGED
@@ -946,11 +946,11 @@ class DasmWindow < Window
|
|
946
946
|
exe
|
947
947
|
end
|
948
948
|
|
949
|
-
def promptopen(caption='
|
949
|
+
def promptopen(caption='choose target binary', &b)
|
950
950
|
openfile(caption) { |exename| loadfile(exename) ; b.call(self) if b }
|
951
951
|
end
|
952
952
|
|
953
|
-
def promptdebug(caption='
|
953
|
+
def promptdebug(caption='choose target', &b)
|
954
954
|
l = nil
|
955
955
|
i = inputbox(caption) { |name|
|
956
956
|
i = nil ; l.destroy if l and not l.destroyed?
|
@@ -996,7 +996,7 @@ class DasmWindow < Window
|
|
996
996
|
@dasm_widget.dasm.save_file @savefile
|
997
997
|
return
|
998
998
|
end
|
999
|
-
|
999
|
+
savefile('choose save file') { |file|
|
1000
1000
|
@savefile = file
|
1001
1001
|
@dasm_widget.dasm.save_file(file)
|
1002
1002
|
}
|
@@ -1039,13 +1039,13 @@ class DasmWindow < Window
|
|
1039
1039
|
|
1040
1040
|
importmenu = new_menu
|
1041
1041
|
addsubmenu(importmenu, 'Load _map') {
|
1042
|
-
openfile('
|
1042
|
+
openfile('choose map file') { |file|
|
1043
1043
|
@dasm_widget.dasm.load_map(File.read(file)) if @dasm_widget
|
1044
1044
|
@dasm_widget.gui_update if @dasm_widget
|
1045
1045
|
} if @dasm_widget
|
1046
1046
|
}
|
1047
1047
|
addsubmenu(importmenu, 'Load _C') {
|
1048
|
-
openfile('
|
1048
|
+
openfile('choose C file') { |file|
|
1049
1049
|
@dasm_widget.dasm.parse_c(File.read(file)) if @dasm_widget
|
1050
1050
|
} if @dasm_widget
|
1051
1051
|
}
|
@@ -1053,21 +1053,21 @@ class DasmWindow < Window
|
|
1053
1053
|
|
1054
1054
|
exportmenu = new_menu
|
1055
1055
|
addsubmenu(exportmenu, 'Save _map') {
|
1056
|
-
savefile('
|
1056
|
+
savefile('choose map file') { |file|
|
1057
1057
|
File.open(file, 'w') { |fd|
|
1058
1058
|
fd.puts @dasm_widget.dasm.save_map
|
1059
1059
|
} if @dasm_widget
|
1060
1060
|
} if @dasm_widget
|
1061
1061
|
}
|
1062
1062
|
addsubmenu(exportmenu, 'Save _asm') {
|
1063
|
-
savefile('
|
1063
|
+
savefile('choose asm file') { |file|
|
1064
1064
|
File.open(file, 'w') { |fd|
|
1065
1065
|
fd.puts @dasm_widget.dasm
|
1066
1066
|
} if @dasm_widget
|
1067
1067
|
} if @dasm_widget
|
1068
1068
|
}
|
1069
1069
|
addsubmenu(exportmenu, 'Save _C') {
|
1070
|
-
savefile('
|
1070
|
+
savefile('choose C file') { |file|
|
1071
1071
|
File.open(file, 'w') { |fd|
|
1072
1072
|
fd.puts @dasm_widget.dasm.c_parser
|
1073
1073
|
} if @dasm_widget
|
data/metasm/gui/debug.rb
CHANGED
@@ -154,7 +154,7 @@ class DbgWidget < ContainerVBoxWidget
|
|
154
154
|
@children.each { |c| c.gui_update }
|
155
155
|
end
|
156
156
|
|
157
|
-
def prompt_attach(caption='
|
157
|
+
def prompt_attach(caption='choose target')
|
158
158
|
l = nil
|
159
159
|
i = inputbox(caption) { |name|
|
160
160
|
i = nil ; l.destroy if l and not l.destroyed?
|
@@ -184,7 +184,7 @@ class DbgWidget < ContainerVBoxWidget
|
|
184
184
|
} if not list_pr.empty?
|
185
185
|
end
|
186
186
|
|
187
|
-
def prompt_createprocess(caption='
|
187
|
+
def prompt_createprocess(caption='choose path')
|
188
188
|
openfile(caption) { |path|
|
189
189
|
path = '"' + path + '"' if @dbg.shortname == 'windbg' and path =~ /\s/
|
190
190
|
inputbox('target args?', :text => path) { |pa|
|
@@ -410,8 +410,8 @@ class DbgRegWidget < DrawableWidget
|
|
410
410
|
case v = key
|
411
411
|
when ?\x20; v = nil
|
412
412
|
when ?0..?9; v -= ?0
|
413
|
-
when ?a..?f; v -= ?a-10
|
414
|
-
when ?A..?F; v -= ?A-10
|
413
|
+
when ?a..?f; v -= ?a - 10
|
414
|
+
when ?A..?F; v -= ?A - 10
|
415
415
|
else return false
|
416
416
|
end
|
417
417
|
end
|
data/metasm/gui/gtk.rb
CHANGED
@@ -45,7 +45,7 @@ module Msgbox
|
|
45
45
|
InputBox.new(toplevel, *a) { |*ya| protect { yield(*ya) } }
|
46
46
|
end
|
47
47
|
|
48
|
-
# asks to
|
48
|
+
# asks to choose a file to open, yields filename
|
49
49
|
# args: title, :path => path
|
50
50
|
def openfile(*a)
|
51
51
|
OpenFile.new(toplevel, *a) { |*ya| protect { yield(*ya) } }
|
data/metasm/gui/qt.rb
CHANGED
@@ -51,7 +51,7 @@ module Msgbox
|
|
51
51
|
|
52
52
|
@@dialogfilefolder = nil
|
53
53
|
|
54
|
-
# asks to
|
54
|
+
# asks to choose a file to open, yields filename
|
55
55
|
# args: title, :path => path
|
56
56
|
def openfile(title, opts={})
|
57
57
|
f = Qt::FileDialog.get_open_file_name(nil, title, @@dialogfilefolder)
|
@@ -180,7 +180,7 @@ Standby OpenUrl LaunchMail LaunchMedia Launch0 Launch1 Launch2 Launch3 Launch4 L
|
|
180
180
|
LaunchC LaunchD LaunchE LaunchF MediaLast unknown Call Context1 Context2 Context3 Context4 Flip Hangup No Select Yes
|
181
181
|
Execute Printer Play Sleep Zoom Cancel
|
182
182
|
].inject({}) { |h, cst|
|
183
|
-
v = Qt.const_get("Key_#{cst}").to_i # AONETUHANOTEUHATNOHEU Qt::Enum !=
|
183
|
+
v = Qt.const_get("Key_#{cst}").to_i # AONETUHANOTEUHATNOHEU Qt::Enum != Integer
|
184
184
|
key = cst.downcase.to_sym
|
185
185
|
key = { :pageup => :pgup, :pagedown => :pgdown, :escape => :esc, :return => :enter }.fetch(key, key)
|
186
186
|
h.update v => key
|
data/metasm/gui/win32.rb
CHANGED
@@ -1401,7 +1401,7 @@ module Msgbox
|
|
1401
1401
|
InputBox.new(toplevel, *a) { |*ya| protect { yield(*ya) } }
|
1402
1402
|
end
|
1403
1403
|
|
1404
|
-
# asks to
|
1404
|
+
# asks to choose a file to open, yields filename
|
1405
1405
|
# args: title, :path => path
|
1406
1406
|
def openfile(*a)
|
1407
1407
|
OpenFile.new(toplevel, *a) { |*ya| protect { yield(*ya) } }
|
data/metasm/main.rb
CHANGED
@@ -307,7 +307,7 @@ class ExeFormat
|
|
307
307
|
def new_label(base = '')
|
308
308
|
base = base.dup.tr('^a-zA-Z0-9_', '_')
|
309
309
|
# use %x instead of to_s(16) for negative values
|
310
|
-
base = (base << '_uuid' << ('%08x' % base.object_id)).freeze if base.empty? or @unique_labels_cache[base]
|
310
|
+
base = (base << '_uuid' << ('%08x' % (base.object_id & 0xffff_ffff_ffff_ffff))).freeze if base.empty? or @unique_labels_cache[base]
|
311
311
|
@unique_labels_cache[base] = true
|
312
312
|
base
|
313
313
|
end
|
@@ -892,7 +892,7 @@ class Expression < ExpressionType
|
|
892
892
|
if targ and vars[targ]
|
893
893
|
return false if exp != vars[targ]
|
894
894
|
elsif targ and vars.has_key? targ
|
895
|
-
|
895
|
+
vars[targ] = exp
|
896
896
|
elsif targ.kind_of? ExpressionType
|
897
897
|
return false if not exp.kind_of? ExpressionType or not exp.match_rec(targ, vars)
|
898
898
|
else
|
@@ -1002,8 +1002,11 @@ class EncodedData
|
|
1002
1002
|
attr_reader :ptr # custom writer
|
1003
1003
|
def ptr=(p) @ptr = @export[p] || p end
|
1004
1004
|
|
1005
|
+
INITIAL_DATA = ''
|
1006
|
+
INITIAL_DATA.force_encoding('BINARY') if INITIAL_DATA.respond_to?(:force_encoding)
|
1007
|
+
|
1005
1008
|
# opts' keys in :reloc, :export, :virtsize, defaults to empty/empty/data.length
|
1006
|
-
def initialize(data=
|
1009
|
+
def initialize(data=INITIAL_DATA.dup, opts={})
|
1007
1010
|
if data.respond_to?(:force_encoding) and data.encoding.name != 'ASCII-8BIT' and data.length > 0
|
1008
1011
|
puts "Forcing edata.data.encoding = BINARY at", caller if $DEBUG
|
1009
1012
|
data = data.dup.force_encoding('binary')
|
@@ -1128,11 +1131,11 @@ class EncodedData
|
|
1128
1131
|
((val + len - 1) / len).to_i * len
|
1129
1132
|
end
|
1130
1133
|
|
1131
|
-
# concatenation of another +EncodedData+ (or nil/
|
1134
|
+
# concatenation of another +EncodedData+ (or nil/Integer/anything supporting String#<<)
|
1132
1135
|
def <<(other)
|
1133
1136
|
case other
|
1134
1137
|
when nil
|
1135
|
-
when ::
|
1138
|
+
when ::Integer
|
1136
1139
|
fill
|
1137
1140
|
@data = @data.to_str if not @data.kind_of? String
|
1138
1141
|
@data << other
|
@@ -1151,17 +1154,19 @@ class EncodedData
|
|
1151
1154
|
other.inv_export.each { |k, v| @inv_export[@virtsize + k] = v }
|
1152
1155
|
end
|
1153
1156
|
if @data.empty?; @data = other.data.dup
|
1157
|
+
elsif other.empty?
|
1154
1158
|
elsif not @data.kind_of?(String); @data = @data.to_str << other.data
|
1155
1159
|
else @data << other.data
|
1156
1160
|
end
|
1157
1161
|
@virtsize += other.virtsize
|
1158
1162
|
else
|
1159
1163
|
fill
|
1160
|
-
if other.respond_to?(:force_encoding) and other.encoding.name != 'ASCII-8BIT'
|
1164
|
+
if other.respond_to?(:force_encoding) and other.encoding.name != 'ASCII-8BIT' and other.length > 0
|
1161
1165
|
puts "Forcing edata.data.encoding = BINARY at", caller if $DEBUG
|
1162
1166
|
other = other.dup.force_encoding('binary')
|
1163
1167
|
end
|
1164
1168
|
if @data.empty?; @data = other.dup
|
1169
|
+
elsif other.empty?
|
1165
1170
|
elsif not @data.kind_of?(String); @data = @data.to_str << other
|
1166
1171
|
else @data << other
|
1167
1172
|
end
|
data/metasm/os/windows.rb
CHANGED
@@ -1232,22 +1232,31 @@ class WinOS < OS
|
|
1232
1232
|
end
|
1233
1233
|
attr_writer :debugger
|
1234
1234
|
|
1235
|
-
#
|
1236
|
-
|
1237
|
-
|
1235
|
+
# return 32 for 32bit process, 64 for 64bit process
|
1236
|
+
# populates iswow64
|
1237
|
+
def cpusz
|
1238
|
+
@cpusz ||= (
|
1238
1239
|
byte = 0.chr*8
|
1239
|
-
if WinAPI.iswow64process(handle, byte)
|
1240
|
+
if WinAPI.respond_to?(:iswow64process) and WinAPI.iswow64process(handle, byte)
|
1241
|
+
# os supports iswow64process, so target may be 64bits
|
1240
1242
|
if byte != 0.chr*8
|
1241
|
-
|
1242
|
-
|
1243
|
-
64 # us = wow64, target is not
|
1243
|
+
@iswow64 = true
|
1244
|
+
32
|
1244
1245
|
else
|
1246
|
+
@iswow64 = false
|
1245
1247
|
WinAPI.host_cpu.size
|
1246
1248
|
end
|
1247
1249
|
else
|
1248
1250
|
WinAPI.host_cpu.size
|
1249
1251
|
end
|
1250
|
-
|
1252
|
+
)
|
1253
|
+
end
|
1254
|
+
attr_accessor :iswow64
|
1255
|
+
|
1256
|
+
# returns the memory address size of the target process
|
1257
|
+
# if the target is a wow64 process (32bit process under a 64bit os), return 64
|
1258
|
+
def addrsz
|
1259
|
+
@addrsz ||= ((cpusz == 32 and iswow64) ? 64 : cpusz)
|
1251
1260
|
end
|
1252
1261
|
|
1253
1262
|
def modules
|
@@ -1363,7 +1372,7 @@ class WinOS < OS
|
|
1363
1372
|
|
1364
1373
|
# increment the suspend count of the target thread - stop at >0
|
1365
1374
|
def suspend
|
1366
|
-
if WinAPI.host_cpu.size == 64 and process and process.
|
1375
|
+
if WinAPI.host_cpu.size == 64 and process and process.iswow64
|
1367
1376
|
WinAPI.wow64suspendthread(handle)
|
1368
1377
|
else
|
1369
1378
|
WinAPI.suspendthread(handle)
|
@@ -1400,26 +1409,20 @@ class WinOS < OS
|
|
1400
1409
|
class Context
|
1401
1410
|
def initialize(thread, kind=:all)
|
1402
1411
|
@handle = thread.handle
|
1403
|
-
tg = (thread.process ? thread.process.
|
1404
|
-
hcpu = WinAPI.host_cpu.shortname
|
1405
|
-
case hcpu
|
1406
|
-
when 'ia32', 'x64'
|
1407
|
-
else raise "unsupported architecture #{tg}"
|
1408
|
-
end
|
1409
|
-
|
1412
|
+
tg = (thread.process ? thread.process.cpusz : 32)
|
1410
1413
|
@getcontext = :getthreadcontext
|
1411
1414
|
@setcontext = :setthreadcontext
|
1412
|
-
|
1413
|
-
|
1415
|
+
if tg == 32
|
1416
|
+
# XXX check CS under wow64 ?
|
1414
1417
|
@context = WinAPI.alloc_c_struct('_CONTEXT_I386')
|
1415
|
-
@context.contextflags = WinAPI::CONTEXT_I386_ALL
|
1416
|
-
if
|
1418
|
+
@context.contextflags = WinAPI::CONTEXT_I386_ALL # XXX kind ?
|
1419
|
+
if WinAPI.host_cpu.shortname == 'x64' and thread.process and thread.process.iswow64
|
1417
1420
|
@getcontext = :wow64getthreadcontext
|
1418
1421
|
@setcontext = :wow64setthreadcontext
|
1419
1422
|
end
|
1420
|
-
|
1423
|
+
else
|
1421
1424
|
@context = WinAPI.alloc_c_struct('_CONTEXT_AMD64')
|
1422
|
-
@context.contextflags = WinAPI::CONTEXT_AMD64_ALL
|
1425
|
+
@context.contextflags = WinAPI::CONTEXT_AMD64_ALL # XXX kind ?
|
1423
1426
|
end
|
1424
1427
|
end
|
1425
1428
|
|
@@ -1805,7 +1808,7 @@ class WinDebugger < Debugger
|
|
1805
1808
|
return if not @os_process
|
1806
1809
|
case WinAPI.host_cpu.shortname
|
1807
1810
|
when 'ia32', 'x64'
|
1808
|
-
@cpu = Ia32.new(os_process.
|
1811
|
+
@cpu = Ia32.new(os_process.cpusz)
|
1809
1812
|
else
|
1810
1813
|
raise 'unsupported architecture'
|
1811
1814
|
end
|
data/misc/hexdump.rb
CHANGED
@@ -29,7 +29,7 @@ def hexdump(ctx={})
|
|
29
29
|
print s.unpack('C*').map { |b| '%02x' % b }.join(' ').ljust(3*16-1) + ' ' if fmt.include? 'c'
|
30
30
|
print s.unpack('v*').map { |b| '%04x' % b }.join(' ').ljust(5*8-1) + ' ' if fmt.include? 'w'
|
31
31
|
print s.unpack('L*').map { |b| '%08x' % b }.join(' ').ljust(9*4-1) + ' ' if fmt.include? 'd'
|
32
|
-
print s.tr("\0-\x1f\x7f-\xff", '.') if fmt.include? 'a'
|
32
|
+
print s.tr("\0-\x1f\x7f-\xff".force_encoding('BINARY'), '.') if fmt.include? 'a'
|
33
33
|
puts
|
34
34
|
elsif not ctx[:lastdup]
|
35
35
|
ctx[:lastdup] = true
|
@@ -50,7 +50,7 @@ if $0 == __FILE__
|
|
50
50
|
fmt << 'w' if ARGV.delete '-W'
|
51
51
|
fmt << 'd' if ARGV.delete '-D'
|
52
52
|
fmt << 'a' if ARGV.delete '-A'
|
53
|
-
fmt = ['c', 'd', 'a'] if ARGV.delete '-a'
|
53
|
+
fmt = ['c', 'd', 'a'] if ARGV.delete '-a' or fmt.empty?
|
54
54
|
infd = ARGV.empty? ? $stdin : File.open(ARGV.first, 'rb')
|
55
55
|
infd.hexdump(:fmt => fmt)
|
56
56
|
end
|