metasm 1.0.4 → 1.0.6
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 +5 -5
- data/.gitignore +1 -0
- data/Gemfile +3 -3
- data/Rakefile +1 -1
- data/cortex.yaml +17 -0
- data/metasm/cpu/arm64/decode.rb +87 -11
- data/metasm/cpu/arm64/decompile.rb +142 -0
- data/metasm/cpu/arm64/opcodes.rb +53 -23
- data/metasm/cpu/arm64.rb +1 -0
- data/metasm/cpu/dwarf/debug.rb +39 -0
- data/metasm/cpu/dwarf/decode.rb +124 -0
- data/metasm/cpu/dwarf/decompile.rb +212 -0
- data/metasm/cpu/dwarf/encode.rb +49 -0
- data/metasm/cpu/dwarf/main.rb +37 -0
- data/metasm/cpu/dwarf/opcodes.rb +107 -0
- data/metasm/cpu/dwarf.rb +11 -0
- data/metasm/cpu/ia32/debug.rb +8 -0
- data/metasm/cpu/ia32/decode.rb +25 -1
- data/metasm/cpu/ia32/decompile.rb +205 -342
- data/metasm/cpu/mips/decode.rb +1 -1
- data/metasm/cpu/ppc/decode.rb +1 -1
- data/metasm/cpu/sh4/decode.rb +1 -1
- data/metasm/cpu/x86_64/decompile.rb +68 -0
- data/metasm/cpu/x86_64.rb +1 -0
- data/metasm/decode.rb +14 -0
- data/metasm/decompile.rb +51 -27
- data/metasm/disassemble.rb +24 -15
- data/metasm/dynldr.rb +23 -4
- data/metasm/encode.rb +11 -0
- data/metasm/exe_format/elf.rb +60 -2
- data/metasm/exe_format/elf_decode.rb +201 -6
- data/metasm/exe_format/shellcode.rb +39 -0
- data/metasm/gui/dasm_decomp.rb +1 -0
- data/metasm/os/emulator.rb +7 -0
- data/metasm/parse_c.rb +1 -1
- data/metasm.gemspec +1 -2
- data/metasm.rb +1 -1
- data/samples/disassemble-gui.rb +27 -11
- data/samples/disassemble.rb +9 -12
- data/samples/emudbg.rb +1 -1
- data/samples/factorize-headers-elfimports.rb +4 -1
- data/samples/lindebug.rb +16 -2
- data/tests/shellcode.rb +111 -0
- metadata +19 -102
- checksums.yaml.gz.sig +0 -3
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -0
data/metasm/exe_format/elf.rb
CHANGED
|
@@ -393,7 +393,8 @@ class ELF < ExeFormat
|
|
|
393
393
|
15 => 'PC8', 16 => 'DTPMOD64', 17 => 'DTPOFF64',
|
|
394
394
|
18 => 'TPOFF64', 19 => 'TLSGD', 20 => 'TLSLD',
|
|
395
395
|
21 => 'DTPOFF32', 22 => 'GOTTPOFF', 23 => 'TPOFF32' },
|
|
396
|
-
'OPENRISC' => { 0 => 'NONE',
|
|
396
|
+
'OPENRISC' => { 0 => 'NONE',
|
|
397
|
+
1 => '32', 2 => '16', 3 => '8',
|
|
397
398
|
4 => 'LO_16_IN_INSN', 5 => 'HI_16_IN_INSN', 6 => 'INSN_REL_26', 7 => 'GNU_VTENTRY',
|
|
398
399
|
8 => 'GNU_VTINHERIT', 9 => '32_PCREL', 10 => '16_PCREL', 11 => '8_PCREL',
|
|
399
400
|
12 => 'GOTPC_HI16', 13 => 'GOTPC_LO16', 14 => 'GOT15', 15 => 'PLT26',
|
|
@@ -402,6 +403,53 @@ class ELF < ExeFormat
|
|
|
402
403
|
24 => 'TLS_LDM_HI16', 25 => 'TLS_LDM_LO16', 26 => 'TLS_LDO_HI16', 27 => 'TLS_LDO_LO16',
|
|
403
404
|
28 => 'TLS_IE_HI16', 29 => 'TLS_IE_LO16', 30 => 'TLS_LE_HI16', 31 => 'TLS_LE_LO16',
|
|
404
405
|
32 => 'TLS_TPOFF', 33 => 'TLS_DTPOFF', 34 => 'TLS_DTPMOD' },
|
|
406
|
+
'AARCH64' => {
|
|
407
|
+
0x100 => 'NONE',
|
|
408
|
+
0x101 => 'ABS64', 0x102 => 'ABS32', 0x103 => 'ABS16',
|
|
409
|
+
0x104 => 'PREL64', 0x105 => 'PREL32', 0x106 => 'PREL16',
|
|
410
|
+
0x107 => 'MOVW_UABS_G0', 0x108 => 'MOVW_UABS_G0_NC',
|
|
411
|
+
0x109 => 'MOVW_UABS_G1', 0x10a => 'MOVW_UABS_G1_NC',
|
|
412
|
+
0x10b => 'MOVW_UABS_G2', 0x10c => 'MOVW_UABS_G2_NC',
|
|
413
|
+
0x10d => 'MOVW_UABS_G3', 0x10e => 'MOVW_SABS_G0',
|
|
414
|
+
0x10f => 'MOVW_SABS_G1', 0x110 => 'MOVW_SABS_G2',
|
|
415
|
+
0x111 => 'LD_PREL_LO19', 0x112 => 'ADR_PREL_LO21',
|
|
416
|
+
0x113 => 'ADR_PREL_PG_HI21', 0x115 => 'ADD_ABS_LO12_NC',
|
|
417
|
+
0x116 => 'LDST8_ABS_LO12_NC', 0x117 => 'TSTBR14', 0x118 => 'CONDBR19',
|
|
418
|
+
0x11a => 'JUMP26', 0x11b => 'CALL26',
|
|
419
|
+
0x11c => 'LDST16_ABS_LO12_NC', 0x11d => 'LDST32_ABS_LO12_NC',
|
|
420
|
+
0x11e => 'LDST64_ABS_LO12_NC', 0x12b => 'LDST128_ABS_LO12_NC',
|
|
421
|
+
0x137 => 'ADR_GOT_PAGE', 0x138 => 'LD64_GOT_LO12_NC',
|
|
422
|
+
0x20b => 'TLSLD_MOVW_DTPREL_G2',
|
|
423
|
+
0x20c => 'TLSLD_MOVW_DTPREL_G1', 0x20d => 'TLSLD_MOVW_DTPREL_G1_NC',
|
|
424
|
+
0x20e => 'TLSLD_MOVW_DTPREL_G0', 0x20f => 'TLSLD_MOVW_DTPREL_G0_NC',
|
|
425
|
+
0x210 => 'TLSLD_ADD_DTPREL_HI12',
|
|
426
|
+
0x211 => 'TLSLD_ADD_DTPREL_LO12', 0x212 => 'TLSLD_ADD_DTPREL_LO12_NC',
|
|
427
|
+
0x213 => 'TLSLD_LDST8_DTPREL_LO12', 0x214 => 'TLSLD_LDST8_DTPREL_LO12_NC',
|
|
428
|
+
0x215 => 'TLSLD_LDST16_DTPREL_LO12', 0x216 => 'TLSLD_LDST16_DTPREL_LO12_NC',
|
|
429
|
+
0x217 => 'TLSLD_LDST32_DTPREL_LO12', 0x218 => 'TLSLD_LDST32_DTPREL_LO12_NC',
|
|
430
|
+
0x219 => 'TLSLD_LDST64_DTPREL_LO12', 0x21a => 'TLSLD_LDST64_DTPREL_LO12_NC',
|
|
431
|
+
0x21b => 'TLSIE_MOVW_GOTTPREL_G1', 0x21c => 'TLSIE_MOVW_GOTTPREL_G0_NC',
|
|
432
|
+
0x21d => 'TLSIE_ADR_GOTTPREL_PAGE21', 0x21e => 'TLSIE_LD64_GOTTPREL_LO12_NC',
|
|
433
|
+
0x21f => 'TLSIE_LD_GOTTPREL_PREL19', 0x220 => 'TLSLE_MOVW_TPREL_G2',
|
|
434
|
+
0x221 => 'TLSLE_MOVW_TPREL_G1', 0x222 => 'TLSLE_MOVW_TPREL_G1_NC',
|
|
435
|
+
0x223 => 'TLSLE_MOVW_TPREL_G0', 0x224 => 'TLSLE_MOVW_TPREL_G0_NC',
|
|
436
|
+
0x225 => 'TLSLE_ADD_TPREL_HI12',
|
|
437
|
+
0x226 => 'TLSLE_ADD_TPREL_LO12', 0x227 => 'TLSLE_ADD_TPREL_LO12_NC',
|
|
438
|
+
0x228 => 'TLSLE_LDST8_TPREL_LO12', 0x229 => 'TLSLE_LDST8_TPREL_LO12_NC',
|
|
439
|
+
0x22a => 'TLSLE_LDST16_TPREL_LO12', 0x22b => 'TLSLE_LDST16_TPREL_LO12_NC',
|
|
440
|
+
0x22c => 'TLSLE_LDST32_TPREL_LO12', 0x22d => 'TLSLE_LDST32_TPREL_LO12_NC',
|
|
441
|
+
0x22e => 'TLSLE_LDST64_TPREL_LO12', 0x22f => 'TLSLE_LDST64_TPREL_LO12_NC',
|
|
442
|
+
0x232 => 'TLSDESC_ADR_PAGE', 0x233 => 'TLSDESC_LD64_LO12_NC',
|
|
443
|
+
0x234 => 'TLSDESC_ADD_LO12_NC',
|
|
444
|
+
0x235 => 'TLSDESC_OFF_G1', 0x236 => 'TLSDESC_OFF_G0_NC', # from musl from this line
|
|
445
|
+
0x237 => 'TLSDESC_LDR', 0x238 => 'TLSDESC_ADD',
|
|
446
|
+
0x239 => 'TLSDESC_CALL', 0x23a => 'TLSLE_LDST128_TPREL_LO12',
|
|
447
|
+
0x23b => 'TLSLE_LDST128_TPREL_LO12_NC', 0x23c => 'TLSLD_LDST128_DTPREL_LO12',
|
|
448
|
+
0x23d => 'TLSLD_LDST128_DTPREL_LO12_NC',
|
|
449
|
+
0x400 => 'COPY', 0x401 => 'GLOB_DAT',
|
|
450
|
+
0x402 => 'JUMP_SLOT', 0x403 => 'RELATIVE',
|
|
451
|
+
0x404 => 'TLS_DTPMOD64', 0x405 => 'TLS_DTPREL64',
|
|
452
|
+
0x406 => 'TLS_TPREL64', 0x407 => 'TLSDESC' },
|
|
405
453
|
}
|
|
406
454
|
|
|
407
455
|
DEFAULT_INTERP = '/lib/ld-linux.so.2'
|
|
@@ -566,6 +614,7 @@ class ELF < ExeFormat
|
|
|
566
614
|
|
|
567
615
|
class SerialStruct
|
|
568
616
|
new_int_field :leb
|
|
617
|
+
new_int_field :uleb
|
|
569
618
|
end
|
|
570
619
|
|
|
571
620
|
# libdwarf/dwarf.h
|
|
@@ -629,6 +678,15 @@ class ELF < ExeFormat
|
|
|
629
678
|
end
|
|
630
679
|
end
|
|
631
680
|
|
|
681
|
+
class CIE < SerialStruct
|
|
682
|
+
attr_accessor :offset, :id, :version, :augmentation_string, :eh_data, :code_align,
|
|
683
|
+
:data_align, :return_reg, :augmentation_data, :initial_instrs
|
|
684
|
+
end
|
|
685
|
+
|
|
686
|
+
class FDE < SerialStruct
|
|
687
|
+
attr_accessor :offset, :cie_offset, :pc_begin, :pc_range, :augmentation_data, :instrs
|
|
688
|
+
end
|
|
689
|
+
|
|
632
690
|
word :cu_len
|
|
633
691
|
half :version, 2
|
|
634
692
|
word :abbrev_off
|
|
@@ -653,7 +711,7 @@ class ELF < ExeFormat
|
|
|
653
711
|
}
|
|
654
712
|
end
|
|
655
713
|
|
|
656
|
-
attr_accessor :header, :segments, :sections, :tag, :symbols, :relocations, :endianness, :bitsize, :debug
|
|
714
|
+
attr_accessor :header, :segments, :sections, :tag, :symbols, :relocations, :endianness, :bitsize, :debug, :eh_frame
|
|
657
715
|
def initialize(cpu=nil)
|
|
658
716
|
@header = Header.new
|
|
659
717
|
@tag = {}
|
|
@@ -781,13 +781,41 @@ class ELF
|
|
|
781
781
|
target = reloc_target(reloc)
|
|
782
782
|
target = Expression[target, :+, addend] if addend and addend != 0
|
|
783
783
|
else
|
|
784
|
-
puts "W: Elf: unhandled
|
|
784
|
+
puts "W: Elf: unhandled OpenRISC reloc #{reloc.inspect}" if $VERBOSE
|
|
785
785
|
target = nil
|
|
786
786
|
end
|
|
787
787
|
|
|
788
788
|
Metasm::Relocation.new(Expression[target], :u32, @endianness) if target
|
|
789
789
|
end
|
|
790
790
|
|
|
791
|
+
def arch_decode_segments_reloc_aarch64(reloc)
|
|
792
|
+
if reloc.symbol.kind_of?(Symbol) and n = reloc.symbol.name and reloc.symbol.shndx == 'UNDEF' and @sections and
|
|
793
|
+
s = @sections.find { |s_| s_.name and s_.offset <= @encoded.ptr and s_.offset + s_.size > @encoded.ptr }
|
|
794
|
+
@encoded.add_export(new_label("#{s.name}_#{n}"), @encoded.ptr, true)
|
|
795
|
+
end
|
|
796
|
+
|
|
797
|
+
original_xword = decode_xword
|
|
798
|
+
|
|
799
|
+
# decode addend if needed
|
|
800
|
+
case reloc.type
|
|
801
|
+
when 'NONE' # no addend
|
|
802
|
+
else addend = reloc.addend || Expression.make_signed(original_xword, 64)
|
|
803
|
+
end
|
|
804
|
+
|
|
805
|
+
case reloc.type
|
|
806
|
+
when 'NONE'
|
|
807
|
+
# TODO actual base relocs
|
|
808
|
+
when 'JUMP_SLOT'
|
|
809
|
+
target = reloc_target(reloc)
|
|
810
|
+
target = Expression[target, :+, addend] if addend and addend != 0
|
|
811
|
+
else
|
|
812
|
+
puts "W: Elf: unhandled AARCH64 reloc #{reloc.inspect}" if $VERBOSE
|
|
813
|
+
target = nil
|
|
814
|
+
end
|
|
815
|
+
|
|
816
|
+
Metasm::Relocation.new(Expression[target], :u64, @endianness) if target
|
|
817
|
+
end
|
|
818
|
+
|
|
791
819
|
class DwarfDebug
|
|
792
820
|
# decode a DWARF2 'compilation unit'
|
|
793
821
|
def decode(elf, info, abbrev, str)
|
|
@@ -850,19 +878,169 @@ class ELF
|
|
|
850
878
|
}
|
|
851
879
|
end
|
|
852
880
|
end
|
|
881
|
+
|
|
882
|
+
def self.decode_eh_frame_entry(elf, eh_frame)
|
|
883
|
+
start_ptr = eh_frame.ptr
|
|
884
|
+
len = elf.decode_word(eh_frame)
|
|
885
|
+
return if len == 0
|
|
886
|
+
|
|
887
|
+
if len >= 0xffff_fff0
|
|
888
|
+
puts "W: ELF: unhandled 64-bit .eh_frame entry"
|
|
889
|
+
return
|
|
890
|
+
end
|
|
891
|
+
|
|
892
|
+
id = elf.decode_word(eh_frame)
|
|
893
|
+
if id == 0
|
|
894
|
+
eh_frame.ptr = start_ptr
|
|
895
|
+
CIE.decode(elf, eh_frame)
|
|
896
|
+
else
|
|
897
|
+
eh_frame.ptr = start_ptr
|
|
898
|
+
FDE.decode(elf, eh_frame)
|
|
899
|
+
end
|
|
900
|
+
end
|
|
901
|
+
|
|
902
|
+
class CIE
|
|
903
|
+
def decode(elf, eh_frame)
|
|
904
|
+
@offset = eh_frame.ptr
|
|
905
|
+
len = elf.decode_word(eh_frame)
|
|
906
|
+
return if len == 0
|
|
907
|
+
return if len >= 0xffff_fff0
|
|
908
|
+
start_ptr = eh_frame.ptr
|
|
909
|
+
|
|
910
|
+
@id = elf.decode_word(eh_frame)
|
|
911
|
+
if id != 0
|
|
912
|
+
raise 'Not a CIE' # FDE, decode_eh_frame_entry should have handled that
|
|
913
|
+
end
|
|
914
|
+
@version = elf.decode_byte(eh_frame)
|
|
915
|
+
@augmentation_string = elf.decode_strz(eh_frame)
|
|
916
|
+
if @augmentation_string.include?('eh')
|
|
917
|
+
@eh_data = elf.decode_xword(eh_frame)
|
|
918
|
+
end
|
|
919
|
+
|
|
920
|
+
@code_align = elf.decode_uleb(eh_frame)
|
|
921
|
+
@data_align = elf.decode_leb(eh_frame)
|
|
922
|
+
@return_reg = elf.decode_byte(eh_frame)
|
|
923
|
+
|
|
924
|
+
if @augmentation_string[0, 1] == 'z'
|
|
925
|
+
a_len = elf.decode_uleb(eh_frame)
|
|
926
|
+
@augmentation_data = eh_frame.read(a_len)
|
|
927
|
+
# 'L' => read_byte LSDA pointer encoding
|
|
928
|
+
# 'R' => read_byte FDE address encoding
|
|
929
|
+
# 'P' => read_encoded_value? personality routine
|
|
930
|
+
end
|
|
931
|
+
|
|
932
|
+
if eh_frame.ptr <= start_ptr + len
|
|
933
|
+
# DWARF opcodes
|
|
934
|
+
@initial_instrs = []
|
|
935
|
+
while eh_frame.ptr < start_ptr+len
|
|
936
|
+
@initial_instrs << DwarfDebug.decode_dw_cfa_op(elf, eh_frame)
|
|
937
|
+
end
|
|
938
|
+
@initial_instrs.pop while @initial_instrs.last == [:nop]
|
|
939
|
+
end
|
|
940
|
+
|
|
941
|
+
eh_frame.ptr = start_ptr + len
|
|
942
|
+
end
|
|
943
|
+
end
|
|
944
|
+
|
|
945
|
+
class FDE
|
|
946
|
+
def decode(elf, eh_frame)
|
|
947
|
+
@offset = eh_frame.ptr
|
|
948
|
+
len = elf.decode_word(eh_frame)
|
|
949
|
+
return if len == 0
|
|
950
|
+
return if len >= 0xffff_fff0
|
|
951
|
+
start_ptr = eh_frame.ptr
|
|
952
|
+
|
|
953
|
+
id = elf.decode_word(eh_frame)
|
|
954
|
+
if id == 0
|
|
955
|
+
raise 'Not an FDE' # CIE
|
|
956
|
+
end
|
|
957
|
+
# in .eh_frame, this is a backward offset from current FDE to CIE, in .debug_frame, may be a direct offset from section start to CIE
|
|
958
|
+
@cie_offset = start_ptr - id
|
|
959
|
+
cie = elf.eh_frame.find { |c| c.offset == @cie_offset }
|
|
960
|
+
|
|
961
|
+
@pc_begin = Expression.make_signed(elf.decode_word(eh_frame), 32)
|
|
962
|
+
@pc_range = elf.decode_word(eh_frame)
|
|
963
|
+
|
|
964
|
+
if cie and cie.augmentation_data
|
|
965
|
+
a_len = elf.decode_uleb(eh_frame)
|
|
966
|
+
@augmentation_data = eh_frame.read(a_len)
|
|
967
|
+
end
|
|
968
|
+
|
|
969
|
+
if eh_frame.ptr <= start_ptr + len
|
|
970
|
+
# DWARF opcodes
|
|
971
|
+
@instrs = []
|
|
972
|
+
while eh_frame.ptr < start_ptr+len
|
|
973
|
+
@instrs << DwarfDebug.decode_dw_cfa_op(elf, eh_frame)
|
|
974
|
+
end
|
|
975
|
+
@instrs.pop while @instrs.last == [:nop]
|
|
976
|
+
end
|
|
977
|
+
|
|
978
|
+
|
|
979
|
+
eh_frame.ptr = start_ptr + len
|
|
980
|
+
end
|
|
981
|
+
end
|
|
982
|
+
|
|
983
|
+
# TODO make a cpu
|
|
984
|
+
def self.decode_dw_cfa_op(elf, eh_frame)
|
|
985
|
+
block = lambda {
|
|
986
|
+
blen = elf.decode_leb(eh_frame)
|
|
987
|
+
eh_frame.read(blen)
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
byte = elf.decode_byte(eh_frame)
|
|
991
|
+
case byte & 0xc0
|
|
992
|
+
when 0x40; [:advance_loc, byte & 0x3f]
|
|
993
|
+
when 0x80; [:offset, byte & 0x3f, elf.decode_uleb(eh_frame)]
|
|
994
|
+
when 0xc0; [:restore, byte & 0x3f]
|
|
995
|
+
else
|
|
996
|
+
case byte
|
|
997
|
+
when 0x00; [:nop]
|
|
998
|
+
when 0x01; [:set_loc, elf.decode_word(eh_frame)]
|
|
999
|
+
when 0x02; [:advance_loc, elf.decode_byte(eh_frame)]
|
|
1000
|
+
when 0x03; [:advance_loc, elf.decode_half(eh_frame)]
|
|
1001
|
+
when 0x04; [:advance_loc, elf.decode_word(eh_frame)]
|
|
1002
|
+
when 0x05; [:offset_extended, elf.decode_uleb(eh_frame), elf.decode_uleb(eh_frame)]
|
|
1003
|
+
when 0x06; [:restore_extended, elf.decode_uleb(eh_frame)]
|
|
1004
|
+
when 0x07; [:undefined, elf.decode_uleb(eh_frame)]
|
|
1005
|
+
when 0x08; [:same_value, elf.decode_uleb(eh_frame)]
|
|
1006
|
+
when 0x09; [:register, elf.decode_uleb(eh_frame), elf.decode_uleb(eh_frame)]
|
|
1007
|
+
when 0x0a; [:remember_state]
|
|
1008
|
+
when 0x0b; [:restore_state]
|
|
1009
|
+
when 0x0c; [:def_cfa, elf.decode_uleb(eh_frame), elf.decode_uleb(eh_frame)]
|
|
1010
|
+
when 0x0d; [:def_cfa_register, elf.decode_uleb(eh_frame)]
|
|
1011
|
+
when 0x0e; [:def_cfa_offset, elf.decode_uleb(eh_frame)]
|
|
1012
|
+
when 0x0f; [:def_cfa_expression, block[]]
|
|
1013
|
+
when 0x10; [:expression, elf.decode_uleb(eh_frame), block[]]
|
|
1014
|
+
when 0x11; [:offset_extended_sf, elf.decode_uleb(eh_frame), elf.decode_leb(eh_frame)]
|
|
1015
|
+
when 0x12; [:def_cfa_sf, elf.decode_uleb(eh_frame), elf.decode_leb(eh_frame)]
|
|
1016
|
+
when 0x13; [:def_cfa_offset_sf, elf.decode_leb(eh_frame)]
|
|
1017
|
+
when 0x14; [:val_offset, elf.decode_uleb(eh_frame), elf.decode_uleb(eh_frame)]
|
|
1018
|
+
when 0x15; [:val_offset_sf, elf.decode_uleb(eh_frame), elf.decode_leb(eh_frame)]
|
|
1019
|
+
when 0x16; [:val_expression, elf.decode_uleb(eh_frame), block[]]
|
|
1020
|
+
when 0x1c; [:lo_user]
|
|
1021
|
+
when 0x3f; [:hi_user]
|
|
1022
|
+
else [byte]
|
|
1023
|
+
end
|
|
1024
|
+
end
|
|
1025
|
+
end
|
|
853
1026
|
end
|
|
854
1027
|
|
|
855
1028
|
# decode an ULEB128 (dwarf2): read bytes while high bit is set, littleendian
|
|
856
|
-
def decode_leb(ed = @encoded)
|
|
1029
|
+
def decode_leb(ed = @encoded); decode_uleb(ed, true); end
|
|
1030
|
+
|
|
1031
|
+
def decode_uleb(ed, signed=false)
|
|
857
1032
|
v = s = 0
|
|
858
|
-
|
|
1033
|
+
while s < 10*7
|
|
859
1034
|
b = ed.read(1).unpack('C').first.to_i
|
|
860
1035
|
v |= (b & 0x7f) << s
|
|
861
1036
|
s += 7
|
|
862
|
-
break
|
|
863
|
-
|
|
1037
|
+
break if (b&0x80) == 0
|
|
1038
|
+
end
|
|
1039
|
+
v = Expression.make_signed(v, s) if signed
|
|
1040
|
+
v
|
|
864
1041
|
end
|
|
865
1042
|
|
|
1043
|
+
|
|
866
1044
|
# decodes the debugging information if available
|
|
867
1045
|
# only a subset of DWARF2/3 is handled right now
|
|
868
1046
|
# most info taken from http://ratonland.org/?entry=39 & libdwarf/dwarf.h
|
|
@@ -887,6 +1065,23 @@ class ELF
|
|
|
887
1065
|
end
|
|
888
1066
|
end
|
|
889
1067
|
|
|
1068
|
+
def decode_eh_frame
|
|
1069
|
+
return if not @sections
|
|
1070
|
+
|
|
1071
|
+
eh_frame = @sections.find { |sec| sec.name == '.eh_frame' }
|
|
1072
|
+
return if not eh_frame
|
|
1073
|
+
|
|
1074
|
+
eh_frame = @encoded[eh_frame.offset, eh_frame.size]
|
|
1075
|
+
|
|
1076
|
+
@eh_frame = []
|
|
1077
|
+
|
|
1078
|
+
while eh_frame.ptr < eh_frame.length
|
|
1079
|
+
entry = DwarfDebug.decode_eh_frame_entry(self, eh_frame)
|
|
1080
|
+
break if not entry
|
|
1081
|
+
@eh_frame << entry
|
|
1082
|
+
end
|
|
1083
|
+
end
|
|
1084
|
+
|
|
890
1085
|
# decodes the ELF dynamic tags, interpret them, and decodes symbols and relocs
|
|
891
1086
|
def decode_segments_dynamic(decode_relocs=true)
|
|
892
1087
|
return if not dynamic = @segments.find { |s| s.type == 'DYNAMIC' }
|
|
@@ -1067,7 +1262,7 @@ EOC
|
|
|
1067
1262
|
d.function[Expression[fn]] = noret
|
|
1068
1263
|
}
|
|
1069
1264
|
d.function[:default] = @cpu.disassembler_default_func
|
|
1070
|
-
when 'openrisc'
|
|
1265
|
+
when 'openrisc', 'arm64'
|
|
1071
1266
|
old_cp = d.c_parser
|
|
1072
1267
|
d.c_parser = nil
|
|
1073
1268
|
d.parse_c <<EOC
|
|
@@ -114,5 +114,44 @@ class Shellcode < ExeFormat
|
|
|
114
114
|
}
|
|
115
115
|
c
|
|
116
116
|
end
|
|
117
|
+
|
|
118
|
+
# returns an assembly `db` directive for the given byte string
|
|
119
|
+
# example: define_data("ABCD".b) => 'db 0x41, 0x42, 0x43, 0x44'
|
|
120
|
+
# returns the empty string for empty input so callers can omit the directive
|
|
121
|
+
def self.define_data(bytes)
|
|
122
|
+
return '' if bytes.nil? || bytes.empty?
|
|
123
|
+
|
|
124
|
+
'db ' + bytes.each_byte.map { |b| '0x%02x' % b }.join(', ')
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# returns an assembly `db` directive for a NULL-terminated string
|
|
128
|
+
# printable ASCII runs are emitted as string literals; non-printable bytes
|
|
129
|
+
# break the run and are emitted as hex tokens; a trailing 0 is always appended
|
|
130
|
+
# example: define_cstring("ABCD".b) => 'db "ABCD", 0'
|
|
131
|
+
# example: define_cstring("AB\x05CD".b) => 'db "AB", 0x05, "CD", 0'
|
|
132
|
+
# example: define_cstring("".b) => 'db 0'
|
|
133
|
+
def self.define_cstring(str)
|
|
134
|
+
str = '' if str.nil?
|
|
135
|
+
|
|
136
|
+
parts = []
|
|
137
|
+
buf = String.new
|
|
138
|
+
flush = lambda {
|
|
139
|
+
unless buf.empty?
|
|
140
|
+
parts << '"' + buf.gsub(/[\\"]/) { |c| '\\' + c } + '"'
|
|
141
|
+
buf.clear
|
|
142
|
+
end
|
|
143
|
+
}
|
|
144
|
+
str.each_byte do |b|
|
|
145
|
+
if b >= 0x20 && b <= 0x7e
|
|
146
|
+
buf << b.chr
|
|
147
|
+
else
|
|
148
|
+
flush.call
|
|
149
|
+
parts << ('0x%02x' % b)
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
flush.call
|
|
153
|
+
parts << '0'
|
|
154
|
+
'db ' + parts.join(', ')
|
|
155
|
+
end
|
|
117
156
|
end
|
|
118
157
|
end
|
data/metasm/gui/dasm_decomp.rb
CHANGED
|
@@ -230,6 +230,7 @@ class CdecompListingWidget < DrawableWidget
|
|
|
230
230
|
# TODO _declspec
|
|
231
231
|
vt.args.to_a.each_with_index { |a, idx|
|
|
232
232
|
oa = curfunc.type.args.to_a[idx]
|
|
233
|
+
next if not oa
|
|
233
234
|
oa.misc ||= {}
|
|
234
235
|
a.misc ||= {}
|
|
235
236
|
uan = a.misc[:unalias_name] = oa.misc[:unalias_name] ||= oa.name
|
data/metasm/os/emulator.rb
CHANGED
|
@@ -31,6 +31,10 @@ class VirtualMemoryDasm < VirtualString
|
|
|
31
31
|
!@disassembler.get_section_at(addr)
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
def get_page(addr, len=@pagelength)
|
|
35
|
+
read_range(addr, len) if !page_invalid?(addr)
|
|
36
|
+
end
|
|
37
|
+
|
|
34
38
|
# overwrite a section of the file
|
|
35
39
|
def rewrite_at(addr, data)
|
|
36
40
|
if e = @disassembler.get_section_at(addr)
|
|
@@ -74,6 +78,7 @@ class EmuDebugger < Debugger
|
|
|
74
78
|
@breakpoint = {}
|
|
75
79
|
@breakpoint_memory = {}
|
|
76
80
|
@breakpoint_thread = {}
|
|
81
|
+
@cpu.initialize_emudbg(self) if @cpu.respond_to?(:initialize_emudbg)
|
|
77
82
|
end
|
|
78
83
|
|
|
79
84
|
def detach
|
|
@@ -160,9 +165,11 @@ class EmuDebugger < Debugger
|
|
|
160
165
|
}.each { |k, v|
|
|
161
166
|
case k
|
|
162
167
|
when Indirection
|
|
168
|
+
raise "cannot assign value #{v}" if not v.kind_of?(::Integer)
|
|
163
169
|
v = v & ((1 << (k.len*8)) - 1)
|
|
164
170
|
memory_write_int(k.pointer, v, k.len)
|
|
165
171
|
when Symbol
|
|
172
|
+
raise "cannot assign value #{v}" if not v.kind_of?(::Integer)
|
|
166
173
|
set_reg_value(k, v)
|
|
167
174
|
when /^dummy_metasm_/
|
|
168
175
|
else
|
data/metasm/parse_c.rb
CHANGED
|
@@ -3432,7 +3432,7 @@ EOH
|
|
|
3432
3432
|
oldc = nil
|
|
3433
3433
|
while c = dep_cycle[[t]]
|
|
3434
3434
|
break if oldc == c
|
|
3435
|
-
r <<
|
|
3435
|
+
r << "#{t.kind_of?(Struct) ? 'struct' : 'union'} #{t.name};" if not oldc
|
|
3436
3436
|
oldc = c
|
|
3437
3437
|
c.each { |s|
|
|
3438
3438
|
# XXX struct z { struct a* }; struct a { void (*foo)(struct z); };
|
data/metasm.gemspec
CHANGED
|
@@ -4,7 +4,7 @@ require 'metasm'
|
|
|
4
4
|
|
|
5
5
|
Gem::Specification.new do |s|
|
|
6
6
|
s.name = 'metasm'
|
|
7
|
-
s.version = '1.0.
|
|
7
|
+
s.version = '1.0.6'
|
|
8
8
|
s.summary =
|
|
9
9
|
"Metasm is a cross-architecture assembler, disassembler, linker, and debugger."
|
|
10
10
|
s.description = ""
|
|
@@ -16,7 +16,6 @@ Gem::Specification.new do |s|
|
|
|
16
16
|
s.homepage = 'http://metasm.cr0.org'
|
|
17
17
|
s.license = 'LGPL-2.1'
|
|
18
18
|
|
|
19
|
-
s.add_development_dependency "bundler", "~> 1.7"
|
|
20
19
|
s.add_development_dependency "rake"
|
|
21
20
|
s.add_development_dependency "test-unit"
|
|
22
21
|
end
|
data/metasm.rb
CHANGED
|
@@ -38,7 +38,7 @@ module Metasm
|
|
|
38
38
|
'X86_64' => 'cpu/x86_64', 'Sh4' => 'cpu/sh4', 'Dalvik' => 'cpu/dalvik', 'ARC' => 'cpu/arc',
|
|
39
39
|
'Python' => 'cpu/python', 'Z80' => 'cpu/z80', 'CY16' => 'cpu/cy16', 'BPF' => 'cpu/bpf', 'EBPF' => 'cpu/ebpf',
|
|
40
40
|
'MSP430' => 'cpu/msp430', 'ARM64' => 'cpu/arm64', 'ST20' => 'cpu/st20', 'MCS51' => 'cpu/mcs51',
|
|
41
|
-
'OpenRisc' => 'cpu/openrisc', 'WebAsm' => 'cpu/webasm',
|
|
41
|
+
'OpenRisc' => 'cpu/openrisc', 'WebAsm' => 'cpu/webasm', 'Dwarf' => 'cpu/dwarf',
|
|
42
42
|
'C' => 'compile_c',
|
|
43
43
|
'MZ' => 'exe_format/mz', 'PE' => 'exe_format/pe',
|
|
44
44
|
'ELF' => 'exe_format/elf', 'COFF' => 'exe_format/coff',
|
data/samples/disassemble-gui.rb
CHANGED
|
@@ -25,12 +25,13 @@
|
|
|
25
25
|
#
|
|
26
26
|
|
|
27
27
|
require 'metasm'
|
|
28
|
+
include Metasm
|
|
28
29
|
require 'optparse'
|
|
29
30
|
|
|
30
31
|
$VERBOSE = true
|
|
31
32
|
|
|
32
33
|
# parse arguments
|
|
33
|
-
opts = {
|
|
34
|
+
opts = {}
|
|
34
35
|
OptionParser.new { |opt|
|
|
35
36
|
opt.banner = 'Usage: disassemble-gtk.rb [options] <executable> [<entrypoints>]'
|
|
36
37
|
opt.on('--no-data-trace', 'do not backtrace memory read/write accesses') { opts[:nodatatrace] = true }
|
|
@@ -54,31 +55,42 @@ OptionParser.new { |opt|
|
|
|
54
55
|
opt.on('-A', '--disassemble-all-entrypoints') { opts[:dasm_all] = true }
|
|
55
56
|
}.parse!(ARGV)
|
|
56
57
|
|
|
58
|
+
opts[:sc_cpu] = eval(opts[:sc_cpu]) if opts[:sc_cpu] =~ /[.(\s:]/
|
|
59
|
+
opts[:sc_cpu] = Metasm.const_get(opts[:sc_cpu]) if opts[:sc_cpu].kind_of?(::String)
|
|
60
|
+
opts[:sc_cpu] = opts[:sc_cpu].new if opts[:sc_cpu].kind_of?(::Class)
|
|
61
|
+
opts[:exe_fmt] = eval(opts[:exe_fmt]) if opts[:exe_fmt] =~ /[.(\s:]/
|
|
62
|
+
|
|
57
63
|
case exename = ARGV.shift
|
|
58
64
|
when /^live:(.*)/
|
|
59
65
|
t = $1
|
|
60
66
|
t = t.to_i if $1 =~ /^[0-9]+$/
|
|
61
|
-
os =
|
|
67
|
+
os = OS.current
|
|
62
68
|
raise 'no such target' if not target = os.find_process(t) || os.create_process(t)
|
|
63
69
|
p target if $VERBOSE
|
|
64
|
-
w =
|
|
70
|
+
w = Gui::DbgWindow.new(target.debugger, "#{target.pid}:#{target.modules[0].path rescue nil} - metasm debugger")
|
|
65
71
|
dbg = w.dbg_widget.dbg
|
|
72
|
+
when /^emu:(.*)/
|
|
73
|
+
t = $1
|
|
74
|
+
exefmt = opts[:exe_fmt] || AutoExe.orshellcode { opts[:sc_cpu] || Ia32.new }
|
|
75
|
+
dbgexe = exefmt.decode_file(t)
|
|
76
|
+
dbgexe.cpu = opts[:sc_cpu] if opts[:sc_cpu]
|
|
77
|
+
dbg = EmuDebugger.new(dbgexe.disassembler)
|
|
78
|
+
w = Gui::DbgWindow.new(dbg, "emudbg")
|
|
66
79
|
when /^(tcp:|udp:)?..+:/
|
|
67
|
-
dbg =
|
|
68
|
-
w =
|
|
80
|
+
dbg = GdbRemoteDebugger.new(exename, opts[:sc_cpu] || Ia32.new)
|
|
81
|
+
w = Gui::DbgWindow.new(dbg, "remote - metasm debugger")
|
|
69
82
|
else
|
|
70
|
-
w =
|
|
83
|
+
w = Gui::DasmWindow.new("#{exename + ' - ' if exename}metasm disassembler")
|
|
71
84
|
if exename
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
exe = w.loadfile(exename, opts[:sc_cpu], opts[:exe_fmt])
|
|
85
|
+
exe = w.loadfile(exename, opts[:sc_cpu] || 'Ia32', opts[:exe_fmt])
|
|
86
|
+
exe.disassembler.cpu = exe.cpu = opts[:sc_cpu] if opts[:sc_cpu]
|
|
75
87
|
exe.disassembler.rebase(opts[:rebase]) if opts[:rebase]
|
|
76
88
|
if opts[:autoload]
|
|
77
89
|
basename = exename.sub(/\.\w\w?\w?$/, '')
|
|
78
90
|
opts[:map] ||= basename + '.map' if File.exist?(basename + '.map')
|
|
79
91
|
opts[:cheader] ||= basename + '.h' if File.exist?(basename + '.h')
|
|
80
92
|
(opts[:plugin] ||= []) << (basename + '.rb') if File.exist?(basename + '.rb')
|
|
81
|
-
opts[:session] ||= basename + '.metasm-session'
|
|
93
|
+
opts[:session] ||= basename + '.metasm-session' if File.exist?(basename + '.metasm-session')
|
|
82
94
|
end
|
|
83
95
|
end
|
|
84
96
|
end
|
|
@@ -104,6 +116,10 @@ elsif dbg
|
|
|
104
116
|
puts "Error with plugin #{p}: #{$!.class} #{$!}"
|
|
105
117
|
end
|
|
106
118
|
}
|
|
119
|
+
if exename[0, 4] == 'emu:' and ep.first
|
|
120
|
+
dbg.pc = ep.first
|
|
121
|
+
w.dbg_widget.code.focus_addr dbg.pc
|
|
122
|
+
end
|
|
107
123
|
end
|
|
108
124
|
|
|
109
125
|
if dasm
|
|
@@ -139,5 +155,5 @@ end
|
|
|
139
155
|
|
|
140
156
|
opts[:hookstr].to_a.each { |f| eval f }
|
|
141
157
|
|
|
142
|
-
|
|
158
|
+
Gui.main
|
|
143
159
|
|
data/samples/disassemble.rb
CHANGED
|
@@ -15,7 +15,7 @@ include Metasm
|
|
|
15
15
|
require 'optparse'
|
|
16
16
|
|
|
17
17
|
# parse arguments
|
|
18
|
-
opts = {
|
|
18
|
+
opts = {}
|
|
19
19
|
OptionParser.new { |opt|
|
|
20
20
|
opt.banner = 'Usage: disassemble.rb [options] <executable> [<entrypoints>]'
|
|
21
21
|
opt.on('--no-data', 'do not display data bytes') { opts[:nodata] = true }
|
|
@@ -44,28 +44,25 @@ exename = ARGV.shift
|
|
|
44
44
|
|
|
45
45
|
t0 = Time.now if opts[:benchmark]
|
|
46
46
|
|
|
47
|
+
opts[:sc_cpu] = eval(opts[:sc_cpu]) if opts[:sc_cpu] =~ /[.(\s:]/
|
|
48
|
+
opts[:sc_cpu] = Metasm.const_get(opts[:sc_cpu]) if opts[:sc_cpu].kind_of?(::String)
|
|
49
|
+
opts[:sc_cpu] = opts[:sc_cpu].new if opts[:sc_cpu].kind_of?(::Class)
|
|
50
|
+
|
|
47
51
|
# load the file
|
|
48
52
|
if exename =~ /^live:(.*)/
|
|
49
53
|
raise 'no such live target' if not target = OS.current.find_process($1)
|
|
50
54
|
p target if $VERBOSE
|
|
51
|
-
|
|
52
|
-
opts[:sc_cpu] = Metasm.const_get(opts[:sc_cpu]) if opts[:sc_cpu].kind_of(::String)
|
|
53
|
-
opts[:sc_cpu] = opts[:sc_cpu].new if opts[:sc_cpu].kind_of?(::Class)
|
|
54
|
-
exe = Shellcode.decode(target.memory, opts[:sc_cpu])
|
|
55
|
+
exe = Shellcode.decode(target.memory, opts[:sc_cpu] || Ia32.new)
|
|
55
56
|
else
|
|
56
|
-
opts[:sc_cpu] = eval(opts[:sc_cpu]) if opts[:sc_cpu] =~ /[.(\s:]/
|
|
57
57
|
opts[:exe_fmt] = eval(opts[:exe_fmt]) if opts[:exe_fmt] =~ /[.(\s:]/
|
|
58
58
|
if opts[:exe_fmt].kind_of?(::String)
|
|
59
59
|
exefmt = opts[:exe_fmt] = Metasm.const_get(opts[:exe_fmt])
|
|
60
60
|
else
|
|
61
|
-
exefmt = opts[:exe_fmt] || AutoExe.orshellcode {
|
|
62
|
-
opts[:sc_cpu] = Metasm.const_get(opts[:sc_cpu]) if opts[:sc_cpu].kind_of?(::String)
|
|
63
|
-
opts[:sc_cpu] = opts[:sc_cpu].new if opts[:sc_cpu].kind_of?(::Class)
|
|
64
|
-
opts[:sc_cpu]
|
|
65
|
-
}
|
|
61
|
+
exefmt = opts[:exe_fmt] || AutoExe.orshellcode { opts[:sc_cpu] || Ia32.new }
|
|
66
62
|
end
|
|
67
|
-
exefmt = exefmt.withcpu(opts[:sc_cpu]) if exefmt.kind_of?(::Class) and exefmt.name.to_s.split('::').last == 'Shellcode'
|
|
63
|
+
exefmt = exefmt.withcpu(opts[:sc_cpu] || Ia32.new) if exefmt.kind_of?(::Class) and exefmt.name.to_s.split('::').last == 'Shellcode'
|
|
68
64
|
exe = exefmt.decode_file(exename)
|
|
65
|
+
exe.cpu = opts[:sc_cpu] if opts[:sc_cpu]
|
|
69
66
|
exe.disassembler.rebase(opts[:rebase]) if opts[:rebase]
|
|
70
67
|
if opts[:autoload]
|
|
71
68
|
basename = exename.sub(/\.\w\w?\w?$/, '')
|
data/samples/emudbg.rb
CHANGED
|
@@ -84,7 +84,7 @@ pkt = EncodedData.new(eth + ip + udp + pld)
|
|
|
84
84
|
dasm.add_section(pkt, 0x9000)
|
|
85
85
|
|
|
86
86
|
# Initialize the emulator
|
|
87
|
-
dbg =
|
|
87
|
+
dbg = EmuDebugger.new(dasm)
|
|
88
88
|
# Set the initial state of the registers
|
|
89
89
|
dbg.set_reg_value(:r10, 0x8900)
|
|
90
90
|
# :packet is a special register used internally by some opcodes of the EBPF cpu (packet data store/load)
|
|
@@ -36,6 +36,9 @@ when ELF
|
|
|
36
36
|
funcnames = exe.symbols.map { |s| s.name if s.shndx == 'UNDEF' and s.type == 'FUNC' }
|
|
37
37
|
opts[:hdrs] << 'stdio.h' << 'stdlib.h' << 'unistd.h'
|
|
38
38
|
opts[:gcc] = true if not opts[:vs]
|
|
39
|
+
case exe.cpu.shortname
|
|
40
|
+
when 'x64'; opts[:path] << '/usr/include/x86_64-linux-gnu/'
|
|
41
|
+
end
|
|
39
42
|
else raise "unsupported #{exe.class}"
|
|
40
43
|
end
|
|
41
44
|
|
|
@@ -51,7 +54,7 @@ ARGV.each { |n|
|
|
|
51
54
|
|
|
52
55
|
src = opts[:hdrs].map { |h| "#include <#{h}>" }.join("\n")
|
|
53
56
|
|
|
54
|
-
parser =
|
|
57
|
+
parser = exe.cpu.new_cparser
|
|
55
58
|
parser.prepare_gcc if opts[:gcc]
|
|
56
59
|
parser.prepare_visualstudio if opts[:vs]
|
|
57
60
|
pp = parser.lexer
|
data/samples/lindebug.rb
CHANGED
|
@@ -357,6 +357,7 @@ class LinDebug
|
|
|
357
357
|
raw[8,8].to_s.unpack('C*').map { |c| '%02x ' % c }.join
|
|
358
358
|
when 'dw'; text << raw.unpack('S*').map { |c| '%04x ' % c }.join
|
|
359
359
|
when 'dd'; text << raw.unpack('L*').map { |c| '%08x ' % c }.join
|
|
360
|
+
when 'dq'; text << raw.unpack('Q*').map { |c| '%016x ' % c }.join
|
|
360
361
|
end
|
|
361
362
|
text << ' ' << raw.unpack('C*').map { |c| (0x20..0x7e).include?(c) ? c : 0x2e }.pack('C*')
|
|
362
363
|
text << Ansi::ClearLineAfter << "\n"
|
|
@@ -655,6 +656,7 @@ class LinDebug
|
|
|
655
656
|
@command['db'] = lambda { |str| @datafmt = 'db' ; @dataptr = @dbg.resolve(str) if str.length > 0 }
|
|
656
657
|
@command['dw'] = lambda { |str| @datafmt = 'dw' ; @dataptr = @dbg.resolve(str) if str.length > 0 }
|
|
657
658
|
@command['dd'] = lambda { |str| @datafmt = 'dd' ; @dataptr = @dbg.resolve(str) if str.length > 0 }
|
|
659
|
+
@command['dq'] = lambda { |str| @datafmt = 'dq' ; @dataptr = @dbg.resolve(str) if str.length > 0 }
|
|
658
660
|
@command['r'] = lambda { |str|
|
|
659
661
|
r, str = str.split(/\s+/, 2)
|
|
660
662
|
if r == 'fl'
|
|
@@ -700,17 +702,29 @@ end
|
|
|
700
702
|
|
|
701
703
|
if $0 == __FILE__
|
|
702
704
|
require 'optparse'
|
|
703
|
-
opts = {
|
|
705
|
+
opts = {}
|
|
704
706
|
OptionParser.new { |opt|
|
|
705
707
|
opt.on('-m map', '--map filemap') { |f| opts[:filemap] = f }
|
|
706
708
|
opt.on('--cpu cpu') { |c| opts[:sc_cpu] = c }
|
|
707
709
|
}.parse!(ARGV)
|
|
708
710
|
|
|
709
711
|
case ARGV.first
|
|
712
|
+
when /^emu:(.*)/
|
|
713
|
+
exepath = $1
|
|
714
|
+
opts[:sc_cpu] = eval(opts[:sc_cpu]) if opts[:sc_cpu] =~ /[.(\s:]/
|
|
715
|
+
opts[:sc_cpu] = Metasm.const_get(opts[:sc_cpu]) if opts[:sc_cpu].kind_of?(::String)
|
|
716
|
+
opts[:sc_cpu] = opts[:sc_cpu].new if opts[:sc_cpu].kind_of?(::Class)
|
|
717
|
+
exe = Metasm::AutoExe.orshellcode { opts[:sc_cpu] || Metasm::Ia32.new }.decode_file(exepath)
|
|
718
|
+
exe.cpu = opts[:sc_cpu] if opts[:sc_cpu]
|
|
719
|
+
dbg = Metasm::EmuDebugger.new(exe.disassembler)
|
|
720
|
+
if ARGV[1]
|
|
721
|
+
dbg.pc = Integer(ARGV[1])
|
|
722
|
+
end
|
|
710
723
|
when /^(tcp:|udp:)?..+:/, /^ser:/
|
|
711
724
|
opts[:sc_cpu] = eval(opts[:sc_cpu]) if opts[:sc_cpu] =~ /[.(\s:]/
|
|
725
|
+
opts[:sc_cpu] = Metasm.const_get(opts[:sc_cpu]) if opts[:sc_cpu].kind_of?(::String)
|
|
712
726
|
opts[:sc_cpu] = opts[:sc_cpu].new if opts[:sc_cpu].kind_of?(::Class)
|
|
713
|
-
dbg = Metasm::GdbRemoteDebugger.new(ARGV.first, opts[:sc_cpu])
|
|
727
|
+
dbg = Metasm::GdbRemoteDebugger.new(ARGV.first, opts[:sc_cpu] || Metasm::Ia32.new)
|
|
714
728
|
else
|
|
715
729
|
dbg = Metasm::LinDebugger.new(ARGV.join(' '))
|
|
716
730
|
end
|