#!/usr/bin/env ruby msfbase = __FILE__ while File.symlink?(msfbase) msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) end $:.unshift(File.join(File.dirname(msfbase), 'lib')) $:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] require 'rex' require 'msf/ui' require 'msf/base' OutStatus = "[*] " OutError = "[-] " $args = Rex::Parser::Arguments.new( "-i" => [ true, "Encode the contents of the supplied file path" ], "-m" => [ true, "Specifies an additional module search path" ], "-a" => [ true, "The architecture to encode as" ], "-t" => [ true, "The format to display the encoded buffer with (c, elf, exe, java, perl, raw, ruby, vba)" ], "-b" => [ true, "The list of characters to avoid: '\\x00\\xff'" ], "-s" => [ true, "The maximum size of the encoded data" ], "-e" => [ true, "The encoder to use" ], "-o" => [ true, "The output file" ], "-c" => [ true, "The number of times to encode the data" ], "-n" => [ false, "Dump encoder information" ], "-h" => [ false, "Help banner" ], "-l" => [ false, "List available encoders" ]) # # Dump the list of encoders # def dump_encoders(arch = nil) tbl = Rex::Ui::Text::Table.new( 'Indent' => 4, 'Header' => "Framework Encoders" + ((arch) ? " (architectures: #{arch})" : ""), 'Columns' => [ "Name", "Rank", "Description" ]) cnt = 0 $framework.encoders.each_module( 'Arch' => arch ? arch.split(',') : nil) { |name, mod| tbl << [ name, mod.rank_to_s, mod.new.name ] cnt += 1 } (cnt > 0) ? "\n" + tbl.to_s + "\n" : "\nNo compatible encoders found.\n\n" end # # Returns the list of encoders to try # def get_encoders(arch, encoder) encoders = [] if (encoder) encoders << $framework.encoders.create(encoder) else $framework.encoders.each_module_ranked( 'Arch' => arch ? arch.split(',') : nil) { |name, mod| encoders << mod.new } end encoders end # # Nuff said. # def usage $stderr.puts("\n" + " Usage: #{$0} \n" + $args.usage) exit end # Defaults cmd = "encode" arch = nil badchars = '' space = nil encoder = nil fmt = "c" input = $stdin options = '' delim = '_|_' output = nil ecount = 1 # Parse the argument and rock that shit. $args.parse(ARGV) { |opt, idx, val| case opt when "-i" begin input = File.new(val) rescue $stderr.puts(OutError + "Failed to open file #{val}: #{$!}") exit end when "-m" $framework.modules.add_module_path(val) when "-l" cmd = "list" when "-n" cmd = "dump" when "-a" arch = val when "-c" ecount = val.to_i when "-b" badchars = Rex::Text.hex_to_raw(val) when "-s" space = val.to_i when "-t" if (val =~ /^(perl|ruby|raw|c|js_le|js_be|java|exe|elf|vba)$/) fmt = val else $stderr.puts(OutError + "Invalid format: #{val}") exit end when "-o" output = val when "-e" encoder = val when "-h" usage else if (val =~ /=/) options += ((options.length > 0) ? delim : "") + "#{val}" end end } # Initialize the simplified framework instance. $framework = Msf::Simple::Framework.create( :module_types => [ Msf::MODULE_ENCODER ] ) # Get the list of encoders to try encoders = get_encoders(arch, encoder) # Process the actual command case cmd when "list" $stderr.puts(dump_encoders(arch)) when "dump" enc = encoder ? $framework.encoders.create(encoder) : nil if (enc) $stderr.puts(Msf::Serializer::ReadableText.dump_module(enc)) else $stderr.puts(OutError + "Invalid encoder specified.") end when "encode" buf = input.read encoders.each { |enc| next if not enc begin # Imports options enc.datastore.import_options_from_s(options, delim) skip = false eout = buf.dup raw = nil 1.upto(ecount) do |iteration| # Encode it up raw = enc.encode(eout, badchars) # Is it too big? if (space and space > 0 and raw.length > space) $stderr.puts(OutError + "#{enc.refname} created buffer that is too big (#{raw.length})") skip = true break end # Print it out $stderr.puts(OutStatus + "#{enc.refname} succeeded with size #{raw.length} (iteration=#{iteration})\n\n") eout = raw end next if skip case fmt when 'exe' exe = Msf::Util::EXE.to_win32pe($framework, raw) if(not output) $stdout.write(exe) else File.open(output, "wb") do |fd| fd.write(exe) end end when 'elf' elf = Rex::Text.to_linux_x86_elf(raw, "") if(not output) $stdout.write(elf) else File.open(output, "wb") do |fd| fd.write(elf) end end when 'vba' exe = Rex::Text.to_win32pe(raw, "") vba = Rex::Text.to_exe_vba(exe) if(not output) $stdout.write(vba) else File.open(output, "wb") do |fd| fd.write(vba) end end else if(not output) $stdout.print(Msf::Simple::Buffer.transform(raw, fmt)) else File.open(output, "wb") do |fd| fd.write(Msf::Simple::Buffer.transform(raw, fmt)) end end end exit rescue => e $stderr.puts(OutError + "#{enc.refname} failed: #{e}") end } $stderr.puts(OutError + "No encoders succeeded.") end