metasm 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|