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
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
2012-02-04 00:32:37 -06:00
$: . unshift ( File . expand_path ( File . join ( File . dirname ( msfbase ) , 'lib' ) ) )
2011-11-21 14:18:57 -06:00
require 'fastlib'
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 (
2010-09-21 00:13:30 +00:00
" -h " = > [ false , " Help banner " ] ,
" -l " = > [ false , " List available encoders " ] ,
2010-09-21 02:38:09 +00:00
" -v " = > [ false , " Increase verbosity " ] ,
2010-09-21 00:13:30 +00:00
# input/output
2005-10-01 21:25:42 +00:00
" -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 " ] ,
2010-09-21 00:13:30 +00:00
" -o " = > [ true , " The output file " ] ,
# architecture/platform
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-09-21 00:13:30 +00:00
# format options
" -t " = > [ true , " The output format: #{ supported_formats . join ( ',' ) } " ] ,
# encoder options
" -e " = > [ true , " The encoder to use " ] ,
" -n " = > [ false , " Dump encoder information " ] ,
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 " ] ,
2009-11-01 04:11:43 +00:00
" -c " = > [ true , " The number of times to encode the data " ] ,
2010-09-21 00:13:30 +00:00
# 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) " ]
)
2005-10-01 21:25:42 +00:00
#
# 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 " : " \n No 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
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
# Parse the argument and rock that shit.
$args . parse ( ARGV ) { | opt , idx , val |
case opt
when " -i "
begin
2010-12-14 09:07:19 +00:00
input = File . open ( val , 'rb' )
2005-10-01 21:25:42 +00:00
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-09-21 00:13:30 +00:00
if supported_formats . include? ( val )
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
2010-09-21 00:13:30 +00:00
when " -d "
exedir = 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
2010-09-21 00:13:30 +00:00
2005-10-01 21:25:42 +00:00
when " -h "
usage
2011-02-15 23:34:26 +00:00
2010-09-21 02:38:09 +00:00
when " -v "
verbose += 1
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
2010-09-21 00:13:30 +00:00
exeopts = {
:inject = > inject ,
:template = > altexe ,
:template_path = > exedir
}
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 (
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 "
2010-12-14 09:07:19 +00:00
input . binmode # ensure its in binary mode
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
2010-09-21 00:13:30 +00:00
output = Msf :: Util :: EXE . to_executable_fmt ( $framework , arch , plat , raw , fmt , exeopts )
2009-12-28 22:41:43 +00:00
2010-09-21 00:13:30 +00:00
if not output
2009-11-04 21:30:00 +00:00
fmt || = " ruby "
2010-09-21 00:13:30 +00:00
output = Msf :: Simple :: Buffer . transform ( raw , fmt )
2008-09-26 22:34:51 +00:00
end
2009-11-01 04:11:43 +00:00
2010-09-21 00:13:30 +00:00
if exeopts [ :fellback ]
$stderr . puts ( OutError + " Warning: Falling back to default template: #{ exeopts [ :fellback ] } " )
end
write_encoded ( output )
2005-10-01 21:25:42 +00:00
exit
2011-02-15 23:34:26 +00:00
#
# 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
2009-06-14 21:30:56 +00:00
rescue = > e
2010-09-21 02:38:09 +00:00
$stderr . puts ( OutError + " #{ enc . refname } failed: #{ e } " )
if verbose > 0
e . backtrace . each { | el |
$stderr . puts ( OutError + el . to_s )
}
end
2005-10-01 21:25:42 +00:00
end
}
$stderr . puts ( OutError + " No encoders succeeded. " )
2008-11-12 19:15:24 +00:00
end