[ SEA-GHOST MINI SHELL]
#!/usr/bin/perl
# Original author: Author: Don Libes, NIST (tcl/expect)
# Date written: December 5, 1991
# Date last editted: October 19, 1994
# Version: 2.11
#
# Ported to Perl Expect module by: Lee Eakin, <Lee@Eakin.org>
# Date first ported: January 28, 2001
#
require 5.004;
my ($pgm)=$0=~m|([^/]*)$|;
$DEBUG=0;
use strict;
use Expect;
use Getopt::Long;
use vars qw($opt_noproc $opt_catu $opt_tty $opt_noescape $opt_escape
$opt_silent $opt_proxy $opt_r);
$|=1;
my $prompt= $ENV{EXPECT_PROMPT} || '(?:%|#|\$)\s';
Getopt::Long::Configure('auto_abbrev','pass_through');
&GetOptions(qw(noproc catu tty=s noescape escape=s silent proxy=s r)) or &usage;
&usage unless @ARGV or $opt_noproc;
$opt_escape="\035" unless $opt_escape or $opt_noescape;
my @flags;
push @flags,'-tty',$opt_tty if $opt_tty;
push @flags,'-silent' if $opt_silent;
$Expect::Log_Stdout=0;
my $stdin=Expect->exp_init(\*STDIN);
my $stdout=Expect->exp_init(\*STDOUT);
my $pid;
my $user=shift;
my $usernum;
if ($opt_r) {
print "KRUN";
$usernum=3;
} else {
$usernum=$user=~/^-\d+/ ? 2 : 1
}
# User who originated kibitz session has $usernum == 1 on local machine.
# User who is responding to kibitz has $usernum == 2.
# User who originated kibitz session has $usernum == 3 on remote machine.
# user 1 invokes kibitz as "kibitz user[@host]"
# user 2 invokes kibitz as "kibitz -####" (some pid).
# user 3 invokes kibitz as "kibitz -r user".
my $sh;
my $rhost;
my $remsh;
if ($usernum == 1) {
unless ($opt_noproc) {
if (@ARGV) {
$sh=Expect->spawn("@ARGV") or die "$pgm: \"@ARGV\" spawn failed";
} else {
$sh=Expect->spawn($ENV{SHELL} || '/bin/sh')
or die "$pgm: shell spawn failed";
}
}
if ($user=~/([^@]+)@(.+)/) {
$user=$1;
$rhost=$2;
}
if ($rhost) {
print "connecting to $rhost\n" unless $opt_silent;
$opt_proxy||=$ENV{USER} || $ENV{LOGNAME} || `whoami` || `logname`;
my $rcmd="rlogin $rhost -l $opt_proxy -8";
$remsh=Expect->spawn($rcmd);
while (1) {
$remsh->expect(60, -re => 'word:\s*$',
-re => '\s+incorrect.*', -re => $prompt)
or die "$pgm: connection to $rhost timed out\n";
if ($remsh->exp_match_number == 1) {
print "password (for $opt_proxy) on $rhost: ";
$stdin->exp_stty('-echo');
my $pswd=<STDIN>;
$stdin->exp_stty('echo');
print "\n";
chomp $pswd;
print $remsh "$pswd\r";
} elsif ($remsh->exp_match_number == 2) {
die "$pgm: invalid password or account\n";
} elsif ($remsh->exp_match_number == 3) {
last;
}
}
print "starting $pgm on $rhost\n" unless $opt_silent;
print $remsh "$pgm @flags -r $user;kill -9 $$\r";
$remsh->expect(120, -re => "$pgm @flags -r $user.*KRUN",
-re => "$pgm @flags -r $user.*$pgm"."[^\r\n]*\r")
or die "$pgm: unable to run $pgm on $rhost: timed out\n";
if ($remsh->exp_match_number == 2) {
die "$pgm: unable to run $pgm on $rhost\n".
"try rlogin by hand followed by \"$pgm $user\"\n";
}
while (1) {
$remsh->expect(120, -re => ".*\n",'KABORT','KDATA');
print $remsh->exp_match if $remsh->exp_match_number == 1;
exit if $remsh->exp_match_number == 2;
last if $remsh->exp_match_number == 3;
}
}
} elsif ($usernum == 2) {
($pid)=$user=~/^-(\d+)/;
}
my $localio=(($usernum == 3) or not $rhost);
my $inf;
my $outf;
my $exin;
my $exout;
if ($localio) {
$pid||=$$;
if ($usernum == 2) {
$inf="/tmp/exp1.$pid";
$outf="/tmp/exp0.$pid";
} else {
$inf="/tmp/exp0.$pid";
$outf="/tmp/exp1.$pid";
}
} else {
$exin=$remsh;
$exout=$remsh;
}
if ($usernum == 2) {
die "$pgm: Huh? No one is asking you to $pgm.\n" unless -r $inf;
open OUT,">$outf" or die "$pgm: write pipe open failed: $!\n";
select((select(OUT),$|=1)[0]);
open IN,$inf or die "$pgm: read pipe open failed: $!\n";
select((select(IN),$|=1)[0]);
$stdin->exp_stty('-echo raw');
$exin=Expect->exp_init(\*IN);
$exout=Expect->exp_init(\*OUT);
if ($opt_escape) {
&vprint("Escape sequence is $opt_escape");
print "\r\n";
$stdin->set_seq($opt_escape,\&local_esc);
}
unlink $inf;
$exin->set_group($stdout);
$stdin->set_group($exout);
Expect::interconnect($exin,$stdin);
exit;
}
if ($localio) {
$SIG{'INT'}=$SIG{'QUIT'}=$SIG{'TERM'}=eval "sub {unlink '$inf','$outf';exit}";
my $fifocmd;
foreach (qw(/usr/bin /usr/sbin /usr/local/bin /usr/local/sbin /bin /sbin)) {
$fifocmd="$_/mkfifo %s",last if -x "$_/mkfifo";
}
unless ($fifocmd) {
foreach (qw(/usr/bin /usr/sbin /usr/local/bin /usr/local/sbin /bin /sbin
/usr/etc /etc)) {
$fifocmd="$_/mknod %s p",last if -x "$_/mknod";
}
}
die "$pgm: could not determine how to make a fifo - where is mknod?\n"
unless $fifocmd;
system(sprintf $fifocmd,$inf) == 0 or
die "$pgm: could not make fifo \"$inf\": $?\n";
system(sprintf $fifocmd,$outf) == 0 or
unlink($inf),
die "$pgm: could not make fifo \"$outf\": $?\n";
chmod 0666,$inf,$outf;
print "asking $user to type: $pgm -$pid\n" unless $opt_silent;
open WQ,"|/usr/bin/write $user $opt_tty" or
unlink($inf,$outf),
die "$pgm: write command failed: $!\n";
print WQ "Can we talk? Run: $pgm -$pid\n";
close WQ;
open IN,$inf or die "$pgm: read pipe open failed: $!\n";
select((select(IN),$|=1)[0]);
open OUT,">$outf" or die "$pgm: write pipe open failed: $!\n";
select((select(OUT),$|=1)[0]);
$stdin->exp_stty('-echo raw');
$exin=Expect->exp_init(\*IN);
$exout=Expect->exp_init(\*OUT);
unlink $inf;
}
if ($usernum==3) {
print "KDATA";
$exin->set_group($stdout);
$stdin->set_group($exout);
Expect::interconnect($exin,$stdin);
} else {
if ($opt_escape) {
&vprint("Escape sequence is $opt_escape");
print "\r\n";
$stdin->set_seq($opt_escape,\&local_esc);
}
if ($opt_noproc) {
$exin->set_group($stdout);
$stdin->set_group($exout);
Expect::interconnect($exin,$stdin);
} else {
$exin->set_group($sh);
$stdin->set_group($sh);
$sh->set_group($stdout,$exout);
Expect::interconnect($exin,$stdin,$sh);
}
$sh->hard_close;
}
unlink $inf,$outf;
exit;
sub local_esc {
print "\r\n$pgm:\r\n E) Exit program\r\n any other key to return to program\r\n";
my $ans=getc;
print "\r\n";
exit if $ans eq 'E';
print "returning to $pgm\r\n";
}
sub vprint {
my @keys=@_;
foreach (@keys) {
s/([\200-\277])/'M-'.chr(ord($1)^128)/eg;
s/([\000-\011\013-\037\177])/"^".chr(ord($1)^ord('@'))/eg;
}
print @keys;
}
sub usage {
print STDERR "Usage: $pgm [options] user [program ...]\n";
print STDERR " or: $pgm [options] user\@host [program ...]\n";
exit 1;
}
SEA-GHOST - SHELL CODING BY SEA-GHOST