Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic

Re: (SPOILER) Read carefully...

by meta4 (Monk)
on Oct 09, 2002 at 21:41 UTC ( #204058=note: print w/replies, xml ) Need Help??

in reply to Read carefully...

First, let me congratulate Felonius on a very fine obfuscation.

However, The use of white space, while very commendable when writing "real" code, detracts a bit from the intended effect of the obfuscation. Here is your code with all the white space, a few semi-colons, and all the new lines removed. (It works exactly the same on my machine.)

#!/usr/bin/perl -w use strict; (sub{print map{$_->()}@_[3,1,2,0,4]})->(sub{no strict;q;read!;},sub{(s +ub{ map{$_->()}@_[2,1,0]})->(sub{'t '},sub{(sub{$_[0]->(),'s'})->(sub {'u' +})}, sub {'t','r'})},sub{(sub{map{$_->()," "}@_;})->(sub{lc ref sub{'', rev +erse 'J A P H !'}},sub{++($_="yot")},sub{(sub{@_[1,4,3,6,2,5,0]})->(split(' +', "thnva'e"))})},sub{(sub {map{$_->()}@_[1,0]})->(sub{(sub{$_[0]->(), q; +'t ; })->(sub{'n'})},sub{no strict;Do})},sub{$/})

I don't know if that really adds any mystery, but I think it makes it look more intimidating.


The main trick in this obfuscation comes from the idiom of calling a subroutine through a code reference like this $sub_ref->( 1, 2, 3 ). However, instead of defining a subroutine somewhere else and storing a reference to it in a scalar, you can define an anonymous code reference right where you are using it, like this ( sub{ print "@_" } ) -> ( 1, 2, 3 ). This has the exact same effect as print( 1, 2, 3 ). If you reformat the creation of the code reference the way Felonious does in the obfu it looks like this.

( sub { print "@_" } ) -> ( 1, 2, 3 );

Felonius takes this idea several steps further, starting with the idea of passing code-references/anonymous-subroutines as arguments to another anonymous subroutine. A simple example of this is:

( sub { print map { $_->() } @_; } ) -> ( sub{ 'Just ' }, sub{ 'another ' }, sub{ 'Perl ' }, sub{ 'hacker,' }, );

This code snippet creates a list of anonymous subroutines and passes it to another anonymous subroutine that just loops through the list calling each of the anonymous subroutines and collects all their output into another list. The resulting list is then printed.

The next devious step Feloius takes is to fiddle a bit with the order of the list of anonymous functions using Perl's slice syntax on the argument array before handing the list off to map. Applying this to the previous example yields something like this.

( sub { print map { $_->() } @_[1,0,3,2]; } ) -> ( sub{ 'another ' }, sub{ 'Just ' }, sub{ 'hacker,' }, sub{ 'Perl ' }, );

Then to top it all off, Felonious nests this entire construct inside itself. Here is another simplified example, which demonstrates this technique. <\p>

( sub { print map { $_->() } @_ } ) -> ( sub { ( sub { map { $_->() } @_ } ) -> ( sub { 'J' }, sub { 'A' } ) }, sub { ( sub { map { $_->() } @_ } ) -> ( sub { 'P' }, sub { 'H', '!' } ) } );

If you can figure that snippet out most of Felonious' obfuscation will become clear. Felonious nests it up to three levels deep in some places. Notice in the above snippet the nested constructs are wrapped in a sub{...} block (operator?, function?). This keeps the anonymous subroutine from being evaluated even though arguments are supplied. (Someone else probably has a better explanation for this.)

That explains most of the obfuscation. There are, however, two other tricks Felonius uses. First, Felonius uses Perl's string increment operator to turn "yot" into "you". This is what the line ++($_="yot") does. Then he gets the string "code" by calling ref on an anonymous subroutine, and lowercasing the result. This is what the following snippet does.

lc ref sub { '', reverse 'J A P H !' }

There are a few other tricks scattered around in the obfu, but if you understand the above tricks the rest of it should be relatively easy.

Replies are listed 'Best First'.
Re: Re: (SPOILER) Read carefully...
by BrowserUk (Pope) on Oct 09, 2002 at 22:06 UTC

    Personally I thought that felonius' use of whitespace was the crowning glory of a masterpiece to rival erudil.

    If it's spoilers you want, this should clarify things completely 8^)

    #!/usr/bin/perl -w use strict; sub a{ print map{ $_->() } @_[3,1,2,0,4]; } sub b{ no strict;q;read!; } sub c{ c1( \&c11, \&c12, \&c13 ) } sub c1{ map{ $_->() } @_[2,1,0] } sub c11{ 't ' } sub c12{ c121( \&c122 ) } sub c121{ $_[0]->(), 's' } sub c122{ 'u' } sub c13{ 't', 'r' } sub d{ d1( \&d11, \&d12, \&d13 ) } sub d1{ map{ $_->(), " " } @_; } sub d11{ lc ref sub { '', reverse 'J A P H !' } } sub d12{ ++($_="yot") } sub d13{ d131( split('',"thnva'e") ) } sub d131{ @_[1,4,3,6,2,5,0]; } sub e{ e1( \&e11, \&e12 ) } sub e1{ map{ $_->() } @_[1,0] } sub e11{ e111( \&e1111 ) } sub e111{ $_[0]->(), q;'t ; } sub e1111{ 'n' } sub e12{ no strict; Do } sub f{ $/ } a( \&b, \&c, \&d, \&e, \&f );

    Cor! Like yer ring! ... HALO dammit! ... 'Ave it yer way! Hal-lo, Mister la-de-da. ... Like yer ring!

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://204058]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (7)
As of 2018-05-25 17:14 GMT
Find Nodes?
    Voting Booth?