rapid7/metasploit-framework

View on GitHub
modules/encoders/cmd/base64.rb

Summary

Maintainability
A
3 hrs
Test Coverage
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Encoder
  Rank = GoodRanking

  BASE64_BYTES = [
    'A'.ord...'Z'.ord,
    'a'.ord...'z'.ord,
    '0'.ord...'9'.ord
  ].map(&:to_a).flatten + '+/='.bytes

  def initialize
    super(
      'Name' => 'Base64 Command Encoder',
      'Description' => %q{
        This encoder uses base64 encoding to avoid bad characters.
      },
      'Author' => 'Spencer McIntyre',
      'Arch' => ARCH_CMD,
      'Platform' => %w[bsd bsdi linux osx solaris unix],
      'EncoderType' => Msf::Encoder::Type::CmdPosixBase64)

    register_advanced_options(
      [
        OptString.new('Base64Decoder', [ false, 'The binary to use for base64 decoding', '', %w[base64 base64-long base64-short openssl] ])
      ],
      self.class
    )
  end

  #
  # Encodes the payload
  #
  def encode_block(state, buf)
    return buf if (buf.bytes & state.badchars.bytes).empty?

    raise EncodingError if (state.badchars.bytes & BASE64_BYTES).any?
    raise EncodingError if state.badchars.include?('-')

    ifs_encode_spaces = state.badchars.include?(' ')
    raise EncodingError if ifs_encode_spaces && (state.badchars.bytes & '${}'.bytes).any?

    base64_buf = Base64.strict_encode64(buf)
    case datastore['Base64Decoder']
    when 'base64'
      raise EncodingError if (state.badchars.bytes & '(|)'.bytes).any?

      base64_decoder = '(base64 --decode || base64 -d)'
    when 'base64-long'
      base64_decoder = 'base64 --decode'
    when 'base64-short'
      base64_decoder = 'base64 -d'
    when 'openssl'
      base64_decoder = 'openssl enc -base64 -d'
    else
      # find a decoder at runtime if we can use the necessary characters
      if (state.badchars.bytes & '(|)>/&'.bytes).empty?
        base64_decoder = '((command -v base64 >/dev/null && (base64 --decode || base64 -d)) || (command -v openssl >/dev/null && openssl enc -base64 -d))'
      elsif (state.badchars.bytes & '(|)'.bytes).empty?
        base64_decoder = '(base64 --decode || base64 -d)'
      else
        base64_decoder = 'openssl enc -base64 -d'
      end
    end

    if (state.badchars.bytes & '|'.bytes).empty?
      buf = "echo #{base64_buf}|#{base64_decoder}|sh"
    elsif (state.badchars.bytes & '<()'.bytes).empty?
      buf = "sh < <(#{base64_decoder} < <(echo #{base64_buf}))"
    elsif (state.badchars.bytes & '<`\''.bytes).empty?
      buf = "sh<<<`#{base64_decoder}<<<'#{base64_buf}'`"
    else
      raise EncodingError
    end

    buf = buf.gsub(/ +/, '${IFS}') if ifs_encode_spaces
    buf
  end
end