http://qs321.pair.com?node_id=66624

in reply to Icarus

would you care to explain this one to me? As obfuscation goes completely over my head yours looks like a nice and short example that i *might* be able to comprehend

Jorg

"Do or do not, there is no try" -- Yoda

Replies are listed 'Best First'.
Re: Re: Icarus
by c-era (Curate) on Mar 23, 2001 at 20:26 UTC
Here it is formated nicly:
```*\$ = sub{
\$a=q;}die;;
sub u{
\$_;
}
\$= && unpack u => u;
};
s[]{82G5S="!A;F]T:&5R(%!E<FP\@:&%C:V5R}six;
die &\$ => \$/;
Boiled down this can be represented by
```*\$=sub{
unpack "u", \$_;
};
\$_='82G5S="!A;F]T:&5R(%!E<FP@:&%C:V5R';
die &\$, \$/;
or even a one-liner:
```die unpack ("u", '82G5S="!A;F]T:&5R(%!E<FP@:&%C:V5R'), \$/;
With this, you should be able to figure out what was done to hide the code.
Re: Re: Icarus
by larryk (Friar) on Mar 23, 2001 at 20:42 UTC
have a look with some formatting...
I'm no expert but I'll have a go at explaining this one.

```*\$=sub{
\$a=q;}die;;
sub u(){\$_}
\$= && unpack u=>u
};
s[]{82G5S="!A;F]T:&5R(%!E<FP\@:&%C:V5R}six;
die &\$=>\$/

I don't understand the *\$ except that * is the typeglob prefix so *test="a" would mean \$test is "a" \$test[0] (from @test) is "a" and \$test{a} is defined but with no value. In this case the Perl processID special variable \$\$ may be being overwritten with a ref(?) to the sub (someone help me out here please).

The \$a line is just to put someone offtrack - the q implies a singlequoted string to follow and the sneaky bit here is that Perl allows a ; to be the delimiter hence the ;;. The offputting bit is that if you put the newline in the wrong place then you get *\$=sub{\$a=q;} followed by die which appears to make sense. Truth is this whole line can be removed and the output won't be affected.

sub u(){\$_} is the same as sub u { return \$_; }

\$= is a Perl special variable a.k.a. \$FORMAT_LINES_PER_PAGE (default 60) and is used here simply as a true value so the unpack will be evaluated.

the s[]{blahblahblah} is a substitution on \$_ which is presumably a uuencoded string equating to "Just another Perl hacker" which the unpack reveals (six is just a clever arrangement of unnecessary modifiers to the substitution).

the last line "die &\$=>\$/" just dies with the returned value from the sub defined earlier although (again help please) the =>\$/ (which is the special variable for the input record separator) supresses the "at blah.pl line X" which usually follows - don't know how though.

how did I do?

Yes, you caught the general ideas, but I'll explain the parts you had questions on. Your formating of the code is correct, and the \$a assignment is definatly there to throw you, which it didn't.

*\$=sub{}; is equivalent to &\$=sub{}. This is equivalent to sub \$ {}, except that you can't do that. The magic is in the typeglob, which recognizes that its getting an anonymous sub, and names it &\$. The value of \$\$ (the PID) is left unchanged. :-)

Next, you said: sub u(){\$_} is the same as sub u { return \$_; }, which it isn't. The parens() act as an empty prototype basically telling Perl that the letter u by itself is a valid function call. Otherwise you have to use &u or u(). This allows the u=>u in the next line. Also note that even though this sub is defined inside the scope of the other sub, it is still a package global subroutine - all subroutines are, regardless of where they are defined. Granted there is some magic involved with localized variables and closures, but this doesn't run into any of that.

```s[]{82G5S="!A;F]T:&5R(%!E<FP\@:&%C:V5R}six;
Is kind of cool in that it takes \$_, which is undefined, and replaces it with the payload, uuencoded. The six are just useless extensions, but distracting ones. Its also sort of a joke in that this was my sixth obfuscation posted here. Note that this will generate a warning about using an undefined variable, but will still pass strict.

And last but not least, die &\$=>\$/ calls the sub defined earlier, which basically does die unpack( u=>u), \$/ Now you asked about \$/, it's default value is "\n". If you die with a string ending in a newline, then the "at blah.pl line X" is supressed. That's also true with warn. The u=>u is equivalent to "u", u() where the first u tells unpack to uudecode the return from u(), which just returns \$_.

Good job of taking this obfu apart.

Thankyou.

I have just one other query. You seem to have used => as a comma replacement. I know this is alternate notation when defining a hash but will Perl always interpret this as a comma?

aah yes indeed i'm starting to get the picture now thanks larryk, ++ tomorrow 'cuz haven't got any votes left.
thanks again!

Jorg

"Do or do not, there is no try" -- Yoda