Path: blob/master/modules/encoders/cmd/perl.rb
19500 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Encoder6Rank = NormalRanking78def initialize9super(10'Name' => 'Perl Command Encoder',11'Description' => %q{12This encoder uses perl to avoid commonly restricted characters.13},14'Author' => 'hdm',15'Arch' => ARCH_CMD,16'Platform' => %w[linux unix],17'EncoderType' => Msf::Encoder::Type::CmdPosixPerl)18end1920#21# Encodes the payload22#23def encode_block(state, buf)24# Skip encoding for empty badchars25if state.badchars.empty?26return buf27end2829if state.badchars.include?('-')30raise EncodingError31else32buf = encode_block_perl(state, buf)33end3435return buf36end3738#39# Uses the perl command to hex encode the command string40#41def encode_block_perl(state, buf)42hex = buf.unpack('H*').join43cmd = 'perl -e '44qot = ',-:.=+!@#$%^&'4546# Convert spaces to IFS...47if state.badchars.include?(' ')48if state.badchars.match(/[${IFS}]/n)49raise EncodingError50end5152cmd.gsub!(/\s/, '${IFS}')53end5455# Can we use single quotes to enclose the command string?56if state.badchars.include?("'")57if state.badchars.match(/[()\\]/)58cmd << perl_e(state, qot, hex)59else60# Without quotes, we can use backslash to escape parens so the61# shell doesn't try to interpreter them.62cmd << "system\\(pack\\(#{perl_qq(state, qot, hex)}\\)\\)"63end64elsif state.badchars.match(/[()]/n)65# Quotes are ok, but we still need parens or spaces66if state.badchars.include?(' ')67cmd << perl_e(state, qot, hex)68else69cmd << "'system pack #{perl_qq(state, qot, hex)}'"70end71else72cmd << "'system(pack(#{perl_qq(state, qot, hex)}))'"73end7475return cmd76end7778def perl_e(state, qot, hex)79# We don't have parens, quotes, or backslashes so we have to use80# barewords on the commandline for the argument to the pack81# function. As a consequence, we can't use things that the shell82# would interpret, so $ and & become badchars.83qot.delete('$')84qot.delete('&')8586# Perl chains -e with newlines, but doesn't automatically add87# semicolons, so the following will result in the interpreter88# seeing a file like this:89# system90# pack91# qq^H*^,qq^whatever^92# Since system and pack require arguments (rather than assuming93# $_ when no args are given like many other perl functions),94# this works out to do what we need.95cmd = "system -e pack -e #{perl_qq(state, qot, hex)}"96if state.badchars.include?(' ')97# We already tested above to make sure that these chars are ok98# if space isn't.99cmd.gsub!(' ', '${IFS}')100end101102cmd103end104105def perl_qq(state, qot, hex)106# Find a quoting character to use107state.badchars.unpack('C*') { |c| qot.delete(c.chr) }108109# Throw an error if we ran out of quotes110raise EncodingError if qot.empty?111112sep = qot[0].chr113# Use an explicit length for the H specifier instead of just "H*"114# in case * is a badchar for the module, and for the case where this115# ends up unquoted so the shell doesn't try to expand a path.116"qq#{sep}H#{hex.length}#{sep},qq#{sep}#{hex}#{sep}"117end118end119120121