samples/metasm-shell.rb in metasm-1.0.2 vs samples/metasm-shell.rb in metasm-1.0.3

- old
+ new

@@ -16,75 +16,87 @@ # > nop ; nop # "\x90\x90" # > exit require 'metasm' +require 'readline' class String - @@cpu = Metasm::Ia32.new - class << self - def cpu() @@cpu end - def cpu=(c) - c = Metasm.const_get(c).new if c.kind_of? String - @@cpu=c - end - end + @@cpu = Metasm::Ia32.new + class << self + def cpu() @@cpu end + def cpu=(c) + c = Metasm.const_get(c).new if c.kind_of? String + @@cpu=c + end + end - # encodes the current string as a Shellcode, returns the resulting EncodedData - def encode_edata - Metasm::Shellcode.assemble(@@cpu, self).encode.encoded - end + # encodes the current string as a Shellcode, returns the resulting EncodedData + def encode_edata + Metasm::Shellcode.assemble(@@cpu, self).encode.encoded + end - # encodes the current string as a Shellcode, returns the resulting binary String - # outputs warnings on unresolved relocations - def encode - ed = encode_edata - if not ed.reloc.empty? - puts 'W: encoded string has unresolved relocations: ' + ed.reloc.map { |o, r| r.target.inspect }.join(', ') - end - ed.fill - ed.data - end + # encodes the current string as a Shellcode, returns the resulting binary String + # outputs warnings on unresolved relocations + def encode + ed = encode_edata + if not ed.reloc.empty? + puts 'W: encoded string has unresolved relocations: ' + ed.reloc.map { |o, r| r.target.inspect }.join(', ') + end + ed.fill + ed.data + end - # decodes the current string as a Shellcode, with specified base address - # returns the resulting Disassembler - def decode_blocks(base_addr=0, eip=base_addr) - sc = Metasm::Shellcode.decode(self, @@cpu) - sc.base_addr = base_addr - sc.disassemble(eip) - end + # decodes the current string as a Shellcode, with specified base address + # returns the resulting Disassembler + def decode_blocks(base_addr=0, eip=base_addr) + sc = Metasm::Shellcode.decode(self, @@cpu) + sc.base_addr = base_addr + sc.disassemble(eip) + end - # decodes the current string as a Shellcode, with specified base address - # returns the asm source equivallent - def decode(base_addr=0, eip=base_addr) - decode_blocks(base_addr, eip).to_s - end + # decodes the current string as a Shellcode, with specified base address + # returns the asm source equivallent + def decode(base_addr=0, eip=base_addr) + decode_blocks(base_addr, eip).to_s + end end # get in interactive assembler mode def asm - puts 'type "exit" or "quit" to quit', 'use ";" for newline', '' - while (print "asm> " ; $stdout.flush ; l = gets) - break if %w[quit exit].include? l.chomp - if l.chomp == 'help' - puts "Metasm assembly shell: type in opcodes to see their binary form", - "You can use ';' to type multi-line stuff", - "e.g. 'nop nop' will display \"\\x90\\x90\"" - next - end - - begin - data = l.gsub(';', "\n") - next if data.strip.empty? - data = data.encode - puts '"' + data.unpack('C*').map { |c| '\\x%02x' % c }.join + '"' - rescue Metasm::Exception => e - puts "Error: #{e.class} #{e.message}" - end - end + puts "[+] Metasm assembly shell" + puts "type help for usage..\n\n" - puts + Readline.completion_proc = lambda { |line| %w[help exit quit].find_all { |w| line.downcase == w[0, line.length] } } + Readline.completion_append_character = ' ' + + while line = Readline.readline('asm> ', true) + case line + when /^help(\W|$)/ + puts "", + "Type in opcodes to see their binary form", + "You can use ';' to type multi-line stuff", + "e.g. 'nop nop' will display \"\\x90\\x90\"", + "", + "exit/quit Quit the console", + "help Show this screen", + "" + when /^(quit|exit)(\W|$)/ + break + else + begin + data = line.gsub(';', "\n") + next if data.strip.empty? + e_data = data.encode + puts '"' + e_data.unpack('C*').map { |c| '\\x%02x' % c }.join + '"' + rescue Metasm::Exception => e + puts "Error: #{e.class} #{e.message}" + end + end + end + + puts end if __FILE__ == $0 - asm + asm end