2005-12-17 06:46:23 +00:00
#!/usr/bin/env ruby
2012-06-29 00:18:28 -05:00
# -*- coding: binary -*-
2010-05-03 17:13:09 +00:00
#
# $Id$
# $Revision$
#
2005-10-01 21:25:42 +00:00
2014-12-08 10:49:12 -06:00
$stderr . puts " [!] ************************************************************************ "
$stderr . puts " [!] * The utility msfencode is deprecated! * "
$stderr . puts " [!] * It will be removed on or about 2015-06-08 * "
$stderr . puts " [!] * Please use msfvenom instead * "
2014-12-09 13:04:35 -06:00
$stderr . puts " [!] * Details: https://github.com/rapid7/metasploit-framework/pull/4333 * "
2014-12-08 10:49:12 -06:00
$stderr . puts " [!] ************************************************************************ "
2009-01-30 06:27:10 +00:00
msfbase = __FILE__
while File . symlink? ( msfbase )
2013-09-30 13:47:53 -05:00
msfbase = File . expand_path ( File . readlink ( msfbase ) , File . dirname ( msfbase ) )
2009-01-30 06:27:10 +00:00
end
2012-02-04 00:32:37 -06:00
$: . unshift ( File . expand_path ( File . join ( File . dirname ( msfbase ) , 'lib' ) ) )
2012-04-15 23:35:38 -05:00
require 'msfenv'
2011-11-21 14:18:57 -06:00
2011-11-23 23:10:43 -06:00
2011-11-21 14:18:57 -06:00
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 = " [-] "
2010-09-21 00:13:30 +00:00
# Load supported formats
supported_formats = Msf :: Simple :: Buffer . transform_formats + Msf :: Util :: EXE . to_executable_fmt_formats
2005-10-01 21:25:42 +00:00
$args = Rex :: Parser :: Arguments . new (
2013-09-30 13:47:53 -05:00
" -h " = > [ false , " Help banner " ] ,
" -l " = > [ false , " List available encoders " ] ,
" -v " = > [ false , " Increase verbosity " ] ,
# input/output
" -i " = > [ true , " Encode the contents of the supplied file path " ] ,
" -m " = > [ true , " Specifies an additional module search path " ] ,
" -o " = > [ true , " The output file " ] ,
# architecture/platform
" -a " = > [ true , " The architecture to encode as " ] ,
" -p " = > [ true , " The platform to encode for " ] ,
# format options
" -t " = > [ true , " The output format: #{ supported_formats . join ( ',' ) } " ] ,
# encoder options
" -e " = > [ true , " The encoder to use " ] ,
" -n " = > [ false , " Dump encoder information " ] ,
" -b " = > [ true , " The list of characters to avoid: ' \\ x00 \\ xff' " ] ,
" -s " = > [ true , " The maximum size of the encoded data " ] ,
" -c " = > [ true , " The number of times to encode the data " ] ,
# EXE generation options
" -d " = > [ true , " Specify the directory in which to look for EXE templates " ] ,
" -x " = > [ true , " Specify an alternate executable template " ] ,
" -k " = > [ false , " Keep template working; run payload in new thread (use with -x) " ]
2010-09-21 00:13:30 +00:00
)
2005-10-01 21:25:42 +00:00
#
# Dump the list of encoders
#
def dump_encoders ( arch = nil )
2013-09-30 13:47:53 -05:00
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 " : " \n No compatible encoders found. \n \n "
2005-10-01 21:25:42 +00:00
end
#
# Returns the list of encoders to try
#
def get_encoders ( arch , encoder )
2013-09-30 13:47:53 -05:00
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
2005-10-01 21:25:42 +00:00
end
#
# Nuff said.
#
def usage
2013-09-30 13:47:53 -05:00
$stderr . puts ( " \n " + " Usage: #{ $0 } <options> \n " + $args . usage )
exit
2005-10-01 21:25:42 +00:00
end
2010-08-19 19:07:41 +00:00
def write_encoded ( buf )
2013-09-30 13:47:53 -05:00
if ( not $output )
$stdout . write ( buf )
else
File . open ( $output , " wb " ) do | fd |
fd . write ( buf )
end
end
2010-08-19 19:07:41 +00:00
end
2005-10-01 21:25:42 +00:00
# Defaults
2010-09-21 02:38:09 +00:00
verbose = 0
2005-10-01 21:25:42 +00:00
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
2010-09-21 00:13:30 +00:00
plat = nil
2009-11-01 04:11:43 +00:00
altexe = nil
2010-03-24 15:55:24 +00:00
inject = false
2010-09-21 00:13:30 +00:00
exedir = nil # use default
2005-10-01 21:25:42 +00:00
2014-03-04 15:00:48 -06:00
# Parse the argument and rock it
2005-10-01 21:25:42 +00:00
$args . parse ( ARGV ) { | opt , idx , val |
2013-09-30 13:47:53 -05:00
case opt
when " -i "
begin
input = File . open ( val , 'rb' )
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 " -p "
plat = Msf :: Module :: PlatformList . transform ( val )
when " -s "
space = val . to_i
when " -t "
if supported_formats . include? ( val )
fmt = val
else
$stderr . puts ( OutError + " Invalid format: #{ val } " )
exit
end
when " -o "
$output = val
when " -e "
encoder = val
when " -d "
exedir = val
when " -x "
altexe = val
when " -k "
inject = true
when " -h "
usage
when " -v "
verbose += 1
else
if ( val =~ / = / )
options += ( ( options . length > 0 ) ? delim : " " ) + " #{ val } "
end
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 )
2013-09-30 13:47:53 -05:00
pre , ext = output . split ( '.' )
if ( ext and not ext . empty? )
fmt = ext
end
2009-10-19 02:42:39 +00:00
end
2010-03-24 15:55:24 +00:00
if inject and not altexe
2013-09-30 13:47:53 -05:00
$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 )
2010-03-24 15:55:24 +00:00
end
2010-09-21 00:13:30 +00:00
exeopts = {
2013-09-30 13:47:53 -05:00
:inject = > inject ,
:template = > altexe ,
:template_path = > exedir
2010-09-21 00:13:30 +00:00
}
2010-03-24 15:55:24 +00:00
2009-01-02 21:25:25 +00:00
# Initialize the simplified framework instance.
$framework = Msf :: Simple :: Framework . create (
2013-09-30 13:47:53 -05: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
2013-09-30 13:47:53 -05:00
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 "
input . binmode # ensure its in binary mode
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 , nil , plat )
# 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
output = Msf :: Util :: EXE . to_executable_fmt ( $framework , arch , plat , raw , fmt , exeopts )
if not output
fmt || = " ruby "
output = Msf :: Simple :: Buffer . transform ( raw , fmt )
end
if exeopts [ :fellback ]
$stderr . puts ( OutError + " Warning: Falling back to default template: #{ exeopts [ :fellback ] } " )
end
write_encoded ( output )
exit
#
# These exception codes are fatal, we shouldn't expect them to succeed on the next
# iteration, nor the next encoder.
#
rescue :: Errno :: ENOENT , :: Errno :: EINVAL
$stderr . puts ( OutError + " #{ enc . refname } failed: #{ $! } " )
break
rescue = > e
$stderr . puts ( OutError + " #{ enc . refname } failed: #{ e } " )
if verbose > 0
e . backtrace . each { | el |
$stderr . puts ( OutError + el . to_s )
}
end
end
}
$stderr . puts ( OutError + " No encoders succeeded. " )
2008-11-12 19:15:24 +00:00
end