Last active
November 12, 2019 14:51
-
-
Save webstrand/a1b926f576c9fbf4ed7f159aea211f1a to your computer and use it in GitHub Desktop.
A self-installing quine that can be piped to a perl binary over the network. Installs to /payload when running from STDIN, keeps STDIN open for interactivity.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
BEGIN{B:{$_=<<'STRAP'; chomp; exit (eval() // exit print STDERR $@)}} | |
#line 4 "STDIN" | |
my $payload = "/tmp/payload"; | |
last unless $0 eq "-"; | |
my $F; do { local $^F=9999; open($F, '>', $payload) or die "$payload: $!" }; | |
$payload //= "/proc/self/fd/" . fileno($F); | |
chmod(0744, $F) or die "$payload: $!"; | |
$/="\n__END__\n"; | |
print $F <<EVAL, scalar <STDIN> or die "$payload: $!"; | |
#!/usr/bin/perl | |
BEGIN{B:{\$_=<<'STRAP'; chomp; exit (eval() // exit print STDERR \$@)}} | |
$_\nSTRAP | |
EVAL | |
use Fcntl; use Errno ':POSIX'; | |
my $CHILD; pipe my $IN, my $OUT or die "pipe: $!"; | |
unless(open($CHILD, "|-") // die "fork: $!") { | |
open STDIN, '<&', $IN or die "dup: $!"; | |
exec 'perl', $payload, @ARGV; | |
} | |
close $IN; $OUT->autoflush(1); | |
my $flags = 0|(fcntl(STDIN, F_GETFL, 0) or die "fcntl GETFL: $!"); | |
fcntl(STDIN, F_SETFL, $flags | O_NONBLOCK) or die "fcntl SETFL: $!"; | |
while(read STDIN, my $data, 8192) { print $OUT $data } | |
fcntl(STDIN, F_SETFL, $flags) or die "fcntl SETFL: $!"; | |
vec(my $vec = '', fileno(STDIN), 1) = 1; | |
vec($vec, fileno($OUT), 1) = 1; | |
for(my $readable;;) { | |
unless(select($readable=$vec, undef, undef, undef)) { | |
redo if not $! || $! == EINTR; | |
die "select: $!"; | |
} | |
last if vec($readable, fileno($OUT), 1); | |
if(vec($readable, fileno(STDIN), 1)) { | |
if(sysread(STDIN, my $data, 8192)) { | |
print $OUT $data or die "write: $!"; | |
} | |
else { | |
last unless $!; | |
redo if $! == EAGAIN || $! == EWOULDBLOCK || $! == EINTR; | |
die "read: $!"; | |
} | |
} | |
} | |
close STDIN; | |
close $OUT or die "write: $!"; | |
close $CHILD; | |
exit $? >> 8; | |
STRAP | |
STDOUT->autoflush(1); | |
print "Name? "; my $name = <STDIN>; chomp $name; | |
print "Hello, $name!\n"; | |
print "Name? "; $name = <STDIN>; chomp $name; | |
print "Hello, $name!\n"; | |
# Required for interactivity | |
# ./sipe stdin_quine.pl /dev/stdin | ssh remote perl | |
__END__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Leave
$payload
undefined to install to an anonymous file.__END__
is unnecessary ifSTDIN
isn't read from in the script body.Data following
"\n__END__\n"
is treated as interactiveSTDIN
when the script is executing over a pipe. Otherwise it is ignored.