Deciphering a very cryptic perl "one-liner"

Discussion in 'Perl Misc' started by Robert Miller, Jun 4, 2004.

  1. 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

    ===================
    --
    Robert Miller
    San Jose, CA, USA
    rwm415/pacbell/net
    Robert Miller, Jun 4, 2004
    #1
    1. Advertising

  2. Robert Miller

    Ben Morrow Guest

    Quoth "Robert Miller" <>:
    >
    > 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?!: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

    --
    And if you wanna make sense / Whatcha looking at me for? (Fiona Apple)
    * *
    Ben Morrow, Jun 4, 2004
    #2
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. pekka niiranen
    Replies:
    5
    Views:
    505
    Paul McGuire
    Oct 20, 2004
  2. Xah Lee
    Replies:
    0
    Views:
    338
    Xah Lee
    Oct 20, 2005
  3. John Carter

    Very Silly One Liner....

    John Carter, Aug 22, 2006, in forum: Ruby
    Replies:
    1
    Views:
    89
    Martin DeMello
    Aug 22, 2006
  4. Mark
    Replies:
    8
    Views:
    87
    Tad McClellan
    Apr 29, 2004
  5. Larry
    Replies:
    1
    Views:
    94
    Martien Verbruggen
    Feb 3, 2005
Loading...

Share This Page