2005-12-17 06:46:23 +00:00
#!/usr/bin/env ruby
2010-05-03 17:13:09 +00:00
#
# $Id$
# $Revision$
#
2005-10-01 21:25:42 +00:00
2009-01-30 06:27:10 +00:00
msfbase = __FILE__
while File.symlink?(msfbase)
msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
end
2006-07-31 15:36:08 +00:00
$:.unshift(File.join(File.dirname(msfbase), 'lib'))
2008-02-02 21:29:46 +00:00
$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB']
2005-10-01 21:25:42 +00:00
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" ],
2007-02-18 12:27:17 +00:00
"-m" => [ true, "Specifies an additional module search path" ],
2005-10-01 21:25:42 +00:00
"-a" => [ true, "The architecture to encode as" ],
2009-12-13 19:03:35 +00:00
"-p" => [ true, "The platform to encode for" ],
2010-08-19 19:07:41 +00:00
"-t" => [ true, "The format to display the encoded buffer with (c, dll, elf, exe, java, js_le, js_be, perl, raw, ruby, vba, vbs, loop-vbs, asp, war, macho)" ],
2005-10-01 21:25:42 +00:00
"-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" ],
2008-09-26 22:34:51 +00:00
"-o" => [ true, "The output file" ],
2009-11-01 04:11:43 +00:00
"-c" => [ true, "The number of times to encode the data" ],
2005-10-01 21:25:42 +00:00
"-n" => [ false, "Dump encoder information" ],
"-h" => [ false, "Help banner" ],
2009-11-01 04:11:43 +00:00
"-x" => [ true, "Specify an alternate win32 executable template" ],
2010-03-24 15:55:24 +00:00
"-k" => [ false, "Keep template working; run payload in new thread (use with -x)" ],
2005-10-01 21:25:42 +00:00
"-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})" : ""),
2009-11-01 04:11:43 +00:00
'Columns' =>
2005-10-01 21:25:42 +00:00
[
"Name",
"Rank",
"Description"
])
cnt = 0
$framework.encoders.each_module(
'Arch' => arch ? arch.split(',') : nil) { |name, mod|
2006-01-08 01:12:00 +00:00
tbl << [ name, mod.rank_to_s, mod.new.name ]
2005-10-01 21:25:42 +00:00
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
2005-10-01 21:32:11 +00:00
$stderr.puts("\n" + " Usage: #{$0} <options>\n" + $args.usage)
2005-10-01 21:25:42 +00:00
exit
end
2010-08-19 19:07:41 +00:00
def write_encoded(buf)
if (not $output)
$stdout.write(buf)
else
File.open($output, "wb") do |fd|
fd.write(buf)
end
end
end
2005-10-01 21:25:42 +00:00
# Defaults
cmd = "encode"
arch = nil
badchars = ''
space = nil
encoder = nil
2009-10-19 02:42:39 +00:00
fmt = nil
2005-10-01 21:25:42 +00:00
input = $stdin
2005-10-01 21:32:11 +00:00
options = ''
2006-03-16 16:33:32 +00:00
delim = '_|_'
2008-09-26 22:34:51 +00:00
output = nil
2009-03-11 04:10:42 +00:00
ecount = 1
2009-11-01 04:11:43 +00:00
altexe = nil
2010-03-24 15:55:24 +00:00
inject = false
2009-12-13 19:03:35 +00:00
plat = nil
2005-10-01 21:25:42 +00:00
# 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
2007-02-18 12:27:17 +00:00
when "-m"
$framework.modules.add_module_path(val)
2005-10-01 21:25:42 +00:00
when "-l"
cmd = "list"
when "-n"
cmd = "dump"
when "-a"
arch = val
2009-03-11 04:10:42 +00:00
when "-c"
ecount = val.to_i
2005-10-01 21:25:42 +00:00
when "-b"
badchars = Rex::Text.hex_to_raw(val)
2009-12-13 19:03:35 +00:00
when "-p"
plat = Msf::Module::PlatformList.transform(val)
2005-10-01 21:25:42 +00:00
when "-s"
space = val.to_i
when "-t"
2010-08-19 19:07:41 +00:00
if (val =~ /^(perl|ruby|rb|raw|c|js_le|js_be|java|dll|exe|exe-small|elf|vba|vbs|loop-vbs|asp|war|macho)$/)
2005-10-01 21:25:42 +00:00
fmt = val
else
$stderr.puts(OutError + "Invalid format: #{val}")
exit
end
2008-09-26 22:34:51 +00:00
when "-o"
2010-08-19 19:07:41 +00:00
$output = val
2005-10-01 21:25:42 +00:00
when "-e"
encoder = val
2009-11-01 04:11:43 +00:00
when "-x"
altexe = val
2010-03-24 15:55:24 +00:00
when "-k"
inject = true
2005-10-01 21:25:42 +00:00
when "-h"
usage
2005-10-01 21:32:11 +00:00
else
if (val =~ /=/)
2006-03-16 16:33:32 +00:00
options += ((options.length > 0) ? delim : "") + "#{val}"
2005-10-01 21:32:11 +00:00
end
2009-11-01 04:11:43 +00:00
end
2005-10-01 21:25:42 +00:00
}
2009-10-19 02:42:39 +00:00
2009-10-20 21:58:08 +00:00
if(not fmt and output)
2009-10-19 02:42:39 +00:00
pre,ext = output.split('.')
if(ext and not ext.empty?)
fmt = ext
end
end
2010-03-24 15:55:24 +00:00
if inject and not altexe
$stderr.puts "[*] Error: the injection option must use a custom EXE template via -x, otherwise the injected payload will immediately exit when the main process dies."
exit(1)
end
2009-01-02 21:25:25 +00:00
# Initialize the simplified framework instance.
$framework = Msf::Simple::Framework.create(
2010-09-18 06:47:59 +00:00
:module_types => [ Msf::MODULE_ENCODER, Msf::MODULE_NOP ],
'DisableDatabase' => true
2009-01-02 21:25:25 +00:00
)
2005-10-01 21:25:42 +00:00
# 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"
2006-09-26 16:03:53 +00:00
enc = encoder ? $framework.encoders.create(encoder) : nil
2005-10-01 21:25:42 +00:00
if (enc)
$stderr.puts(Msf::Serializer::ReadableText.dump_module(enc))
else
$stderr.puts(OutError + "Invalid encoder specified.")
end
when "encode"
2006-12-17 07:03:00 +00:00
buf = input.read
2009-11-01 04:11:43 +00:00
2005-10-01 21:25:42 +00:00
encoders.each { |enc|
2006-01-29 21:47:51 +00:00
next if not enc
2005-10-01 21:25:42 +00:00
begin
2005-10-01 21:32:11 +00:00
# Imports options
2006-03-16 16:33:32 +00:00
enc.datastore.import_options_from_s(options, delim)
2005-10-01 21:32:11 +00:00
2009-03-11 04:10:42 +00:00
skip = false
eout = buf.dup
raw = nil
2009-11-01 04:11:43 +00:00
2009-03-11 04:10:42 +00:00
1.upto(ecount) do |iteration|
2005-10-01 21:25:42 +00:00
2009-03-11 04:10:42 +00:00
# Encode it up
2009-12-13 19:03:35 +00:00
raw = enc.encode(eout, badchars, nil, plat)
2009-03-11 04:10:42 +00:00
# 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
2005-10-01 21:25:42 +00:00
2009-03-11 04:10:42 +00:00
# Print it out
$stderr.puts(OutStatus + "#{enc.refname} succeeded with size #{raw.length} (iteration=#{iteration})\n\n")
eout = raw
end
2009-11-01 04:11:43 +00:00
2009-03-11 04:10:42 +00:00
next if skip
2009-11-01 04:11:43 +00:00
2008-11-12 19:15:24 +00:00
case fmt
2010-08-19 19:07:41 +00:00
when 'dll'
dll = nil
dll = Msf::Util::EXE.to_win32pe_dll($framework, raw)
write_encoded(dll)
2008-11-12 19:15:24 +00:00
when 'exe'
2009-08-25 23:23:39 +00:00
exe = nil
if(not arch or (arch.index(ARCH_X86)))
2010-03-24 15:55:24 +00:00
exe = Msf::Util::EXE.to_win32pe($framework, raw, {:insert => inject, :template => altexe})
2009-08-25 23:23:39 +00:00
end
2009-11-01 04:11:43 +00:00
2009-08-25 23:23:39 +00:00
if(arch and (arch.index( ARCH_X86_64 ) or arch.index( ARCH_X64 )))
2010-03-24 15:55:24 +00:00
exe = Msf::Util::EXE.to_win64pe($framework, raw, {:insert => inject, :template => altexe})
2009-08-25 23:23:39 +00:00
end
2009-11-01 04:11:43 +00:00
2010-08-19 19:07:41 +00:00
write_encoded(exe)
2009-12-13 19:03:35 +00:00
when 'exe-small'
exe = nil
if(not arch or (arch.index(ARCH_X86)))
exe = Msf::Util::EXE.to_win32pe_old($framework, raw)
end
2009-12-28 22:41:43 +00:00
2010-08-19 19:07:41 +00:00
write_encoded(exe)
2009-05-11 15:23:13 +00:00
when 'elf'
2009-06-24 03:59:54 +00:00
elf = Msf::Util::EXE.to_linux_x86_elf($framework, raw)
2010-08-19 19:07:41 +00:00
write_encoded(elf)
2010-04-14 17:23:35 +00:00
when 'macho'
macho = Msf::Util::EXE.to_osx_x86_macho($framework, raw)
2010-08-19 19:07:41 +00:00
write_encoded(macho)
2008-11-12 19:15:24 +00:00
when 'vba'
2010-03-24 15:55:24 +00:00
exe = Msf::Util::EXE.to_win32pe($framework, raw, {:insert => inject, :template => altexe})
2009-06-24 03:59:54 +00:00
vba = Msf::Util::EXE.to_exe_vba(exe)
2010-08-19 19:07:41 +00:00
write_encoded(vba)
2009-10-19 02:42:39 +00:00
when 'vbs'
2010-03-24 15:55:24 +00:00
vbs = Msf::Util::EXE.to_win32pe_vbs($framework, raw, {:insert => inject, :persist => false, :template => altexe})
2010-08-19 19:07:41 +00:00
write_encoded(vbs)
2009-10-19 02:42:39 +00:00
when 'loop-vbs'
2010-03-24 15:55:24 +00:00
vbs = Msf::Util::EXE.to_win32pe_vbs($framework, raw, {:insert => inject, :persist => true, :template => altexe})
2010-08-19 19:07:41 +00:00
write_encoded(vbs)
2009-12-28 22:41:43 +00:00
when 'asp'
2010-03-24 15:55:24 +00:00
asp = Msf::Util::EXE.to_win32pe_asp($framework, raw, {:insert => inject, :persist => false, :template => altexe})
2010-08-19 19:07:41 +00:00
write_encoded(asp)
2010-02-18 03:29:14 +00:00
when 'war'
tmp_plat = plat.platforms
war = Msf::Util::EXE.to_jsp_war($framework, arch, tmp_plat, raw, {:persist => false, :template => altexe})
2010-08-19 19:07:41 +00:00
write_encoded(war)
2008-11-12 19:15:24 +00:00
else
2009-11-04 21:30:00 +00:00
fmt ||= "ruby"
2010-08-19 19:07:41 +00:00
write_encoded(Msf::Simple::Buffer.transform(raw, fmt))
2008-09-26 22:34:51 +00:00
end
2009-11-01 04:11:43 +00:00
2005-10-01 21:25:42 +00:00
exit
2009-06-14 21:30:56 +00:00
rescue => e
2009-10-19 02:42:39 +00:00
$stderr.puts(OutError + "#{enc.refname} failed: #{e} #{e.backtrace}")
2005-10-01 21:25:42 +00:00
end
}
$stderr.puts(OutError + "No encoders succeeded.")
2008-11-12 19:15:24 +00:00
end