Deciphering a very cryptic perl "one-liner"

R

Robert Miller

Hello All,

Below is 8-lines of pure perl gibberish (a "one-liner") that computes the
SHA1 hash of its stdin. It's not mine, it's the work of John Allen. Just
Google his name and SHA1 if you want to know more about author.

It seems to work fine. My question is *how* it works. Most of the script is
fairly easy to follow: beginning on line 2 there are some arrays defined and
some procedures declared. There's a big DO loop from line 4-8 that reads all
the data from STDIN and processes it. The resulting hash is printed on line
8.

What I can't make heads or tails of is line 1 (the shebang). It seems to be
invoking the perl interpreter with the -i flag (edit in place). This makes
no sense though because the script isn't operating on a named file nor is
the flag followed by an file extension to be used for a backup. The flag
appears to be followed by random characters instead. It suprises me that
line 1 doesn't cause a syntax error, but apparently it's valid perl code.

What gives??? Can anyone explain or parse the first line of this script?

Thanks to any and all, -RM.

=================

#!/usr/bin/perl -iD9T4C`>_-JXF8NMS^$#)4=L/2X?!:mad:GF9;MGKH8\;O-S*8L'6
@A=unpack"N*",unpack u,$^I;@K=splice@A,5,4;sub
M{($x=pop)-($m=1+~0)*int$x/$m};
sub
L{$n=pop;($x=pop)<<$n|2**$n-1&$x>>32-$n}@F=(sub{$b&($c^$d)^$d},$S=sub{$b^$c
^$d},sub{($b|$c)&$d|$b&$c},$S);do{$l+=$r=read
STDIN,$_,64;$r++,$_.="\x80"if$r<
64&&!$p++;@W=unpack N16,$_."\0"x7;$W[15]=$l*8
if$r<57;for(16..79){push@W,L$W[$_
-3]^$W[$_-8]^$W[$_-14]^$W[$_-16],1}($a,$b,$c,$d,$e)=@A;for(0..79){$t=M&{$F[$
_/
20]}+$e+$W[$_]+$K[$_/20]+L$a,5;$e=$d;$d=$c;$c=L$b,30;$b=$a;$a=$t}$v='a';@A=m
ap{
M$_+${$v++}}@A}while$r>56;printf'%.8x'x5 ."\n",@A

===================
 
B

Ben Morrow

Quoth "Robert Miller said:
Below is 8-lines of pure perl gibberish (a "one-liner") that computes the
SHA1 hash of its stdin. It's not mine, it's the work of John Allen. Just
Google his name and SHA1 if you want to know more about author.

It seems to work fine. My question is *how* it works.

What I can't make heads or tails of is line 1 (the shebang). It seems to be
invoking the perl interpreter with the -i flag (edit in place). This makes
no sense though ...
#!/usr/bin/perl -iD9T4C`>_-JXF8NMS^$#)4=L/2X?!:mad:GF9;MGKH8\;O-S*8L'6
@A=unpack"N*",unpack u,$^I;@K=splice@A,5,4;sub
M{($x=pop)-($m=1+~0)*int$x/$m};
sub
L{$n=pop;($x=pop)<<$n|2**$n-1&$x>>32-$n}@F=(sub{$b&($c^$d)^$d},$S=sub{$b^$c
^$d},sub{($b|$c)&$d|$b&$c},$S);do{$l+=$r=read
STDIN,$_,64;$r++,$_.="\x80"if$r<
64&&!$p++;@W=unpack N16,$_."\0"x7;$W[15]=$l*8
if$r<57;for(16..79){push@W,L$W[$_
-3]^$W[$_-8]^$W[$_-14]^$W[$_-16],1}($a,$b,$c,$d,$e)=@A;for(0..79){$t=M&{$F[$
_/

^^ linewrap
20]}+$e+$W[$_]+$K[$_/20]+L$a,5;$e=$d;$d=$c;$c=L$b,30;$b=$a;$a=$t}$v='a';@A=m
ap{

^^ linewrap
M$_+${$v++}}@A}while$r>56;printf'%.8x'x5 ."\n",@A

The tool for this job is B::Deparse, which for this script gives:

BEGIN { $^I = "D9T4C`>_-JXF8NMS^\$#)4=L/2X?!:\@GF9;MGKH8\\;O-S*8L'6"; }
@A = unpack('N*', unpack('u', $^I));
@K = splice(@A, 5, 4);
sub M {
($x = pop @_) - ($m = 4294967296) * int($x / $m);
}
sub L {
$n = pop @_;
($x = pop @_) << $n | 2 ** $n - 1 & $x >> 32 - $n;
}
@F = (sub {
$b & ($c ^ $d) ^ $d;
}
, $S = sub {
$b ^ $c ^ $d;
}
, sub {
($b | $c) & $d | $b & $c;
}
, $S);
do {
$l += $r = read(STDIN, $_, 64);
++$r, $_ .= "\200" if $r < 64 and not $p++;
@W = unpack('N16', $_ . "\000" x 7);
$W[15] = $l * 8 if $r < 57;
foreach $_ (16 .. 79) {
push @W, L($W[$_ - 3] ^ $W[$_ - 8] ^ $W[$_ - 14] ^ $W[$_ - 16], 1);
}
($a, $b, $c, $d, $e) = @A;
foreach $_ (0 .. 79) {
$t = M(&{$F[$_ / 20];} + $e + $W[$_] + $K[$_ / 20] + L($a, 5));
$e = $d;
$d = $c;
$c = L($b, 30);
$b = $a;
$a = $t;
}
$v = 'a';
@A = map({M $_ + ${$v++;};} @A)
} while $r > 56;
printf '%.8x' x 5 . "\n", @A;

So the -i switch has the effect of setting the $^I variable, which is
then used on the second line of the script. A slightly nasty piece of
obfustication, IMHO :).

Ben
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,739
Latest member
Clint8040

Latest Threads

Top