From 24750deab37a56cf1de4935f52f94350fe09fa3c Mon Sep 17 00:00:00 2001 From: jvoisin Date: Mon, 26 Aug 2024 22:37:49 +0200 Subject: [PATCH 1/2] Add modules/encoders/php/hex.rb This one increases the size of the payload by a bit more than a factor two, but should be able to generate a valid encoded payload in some pathological BADCHAR situations where modules/encoders/php/base64.rb can't. --- modules/encoders/php/hex.rb | 72 +++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 modules/encoders/php/hex.rb diff --git a/modules/encoders/php/hex.rb b/modules/encoders/php/hex.rb new file mode 100644 index 000000000000..229847f5ddef --- /dev/null +++ b/modules/encoders/php/hex.rb @@ -0,0 +1,72 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Encoder + Rank = GreatRanking + + def initialize + super( + 'Name' => 'PHP Hex Encoder', + 'Description' => %q{ + This encoder returns a hex string encapsulated in + eval(hex2bin()), increasing the size by a bit more than + a factor two. + }, + 'Author' => 'Julien Voisin', + 'License' => BSD_LICENSE, + 'Arch' => ARCH_PHP) + register_options( + [ + OptBool.new('Compress', [ true, 'Compress the payload with zlib', false ]) # Disabled by default as it relies on having php compiled with zlib, which might not be available on come exotic setups. + ], + self.class) + end + + def encode_block(state, buf) + # Have to have these for the decoder stub, so if they're not available, + # there's nothing we can do here. + %w[e v a l h e x 2 b i n ( ) ;].uniq.each do |c| + raise BadcharError if state.badchars.include?(c) + end + + if datastore['Compress'] + %w[g z u n c o m p r e s s].uniq.each do |c| + raise BadcharError if state.badchars.include?(c) + end + end + + # Modern versions of PHP choke on unquoted literal strings. + quote = "'" + if state.badchars.include?("'") + raise BadcharError.new, "The #{name} encoder failed to encode the decoder stub without bad characters." if state.badchars.include?('"') + + quote = '"' + end + + if datastore['Compress'] + buf = Zlib::Deflate.deflate(buf) + end + + hex = buf.unpack1('H*') + + state.badchars.each_byte do |byte| + # Last ditch effort, if any of the normal characters used by hex + # are badchars, try to replace them with something that will become + # the appropriate thing on the other side. + if hex.include?(byte.chr) + %w[c h r ( ) .].uniq.each do |c| + raise BadcharError if state.badchars.include?(c) + end + hex.gsub!(byte.chr, "#{quote}.chr(#{byte}).#{quote}") + end + end + + if datastore['Compress'] + return 'eval(gzuncompress(hex2bin(' + quote + hex + quote + ')));' + else + return 'eval(hex2bin(' + quote + hex + quote + '));' + end + end +end From a22db071f0550072e6b7205730d3bbb151f5d311 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Wed, 28 Aug 2024 10:46:48 -0400 Subject: [PATCH 2/2] Appease rubocop --- modules/encoders/php/hex.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/modules/encoders/php/hex.rb b/modules/encoders/php/hex.rb index 229847f5ddef..3c31fdff58c6 100644 --- a/modules/encoders/php/hex.rb +++ b/modules/encoders/php/hex.rb @@ -21,7 +21,8 @@ def initialize [ OptBool.new('Compress', [ true, 'Compress the payload with zlib', false ]) # Disabled by default as it relies on having php compiled with zlib, which might not be available on come exotic setups. ], - self.class) + self.class + ) end def encode_block(state, buf) @@ -55,12 +56,12 @@ def encode_block(state, buf) # Last ditch effort, if any of the normal characters used by hex # are badchars, try to replace them with something that will become # the appropriate thing on the other side. - if hex.include?(byte.chr) - %w[c h r ( ) .].uniq.each do |c| - raise BadcharError if state.badchars.include?(c) - end - hex.gsub!(byte.chr, "#{quote}.chr(#{byte}).#{quote}") + next unless hex.include?(byte.chr) + + %w[c h r ( ) .].uniq.each do |c| + raise BadcharError if state.badchars.include?(c) end + hex.gsub!(byte.chr, "#{quote}.chr(#{byte}).#{quote}") end if datastore['Compress']