Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Perl Misc (http://www.velocityreviews.com/forums/f67-perl-misc.html)
-   -   Deciphering a very cryptic perl "one-liner" (http://www.velocityreviews.com/forums/t886737-deciphering-a-very-cryptic-perl-one-liner.html)

Robert Miller 06-03-2004 11:42 PM

Deciphering a very cryptic perl "one-liner"
 
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?!:@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

===================
--
Robert Miller
San Jose, CA, USA
rwm415/pacbell/net




Ben Morrow 06-04-2004 12:09 AM

Re: Deciphering a very cryptic perl "one-liner"
 

Quoth "Robert Miller" <see.post.for.real.address@pacbell.net>:
>
> 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 ...

<snip>
>
> #!/usr/bin/perl -iD9T4C`>_-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=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

--
And if you wanna make sense / Whatcha looking at me for? (Fiona Apple)
* ben@morrow.me.uk *


All times are GMT. The time now is 10:32 PM.

Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57