in reply to Hubris or plain arrogance?
Okay, I'm not much of an obfu guy at all, but lemme give this a shot. Note: reading more gives away the tricks :)
#!/usr/bin/perl -w print <<JAPH; Do You Dare To Try To Crack The Code Of The Perl Masters of Obfuscation? JAPH use strict; BEGIN { $_ = q# ;}$~='Z126504E060240Q102408n106424u101404P039156e039156o1 17468v111444 I am 106424n115460p113452 now a master 060240 F042168d12750 Obfuscator! 8037148H041164c102408C11 You are not 6464P112448O109436g100400m060 so do not 240042168A115460r102408P1084 +32 even try 100400W098392U073292c033132 to figure 109436G115460n102408k +0 this out! 81324p033132v115460N102408E105420m117468h112448J111444h066 +264 033132117468u116464p118472S075300J041164j120480A114456f045180c035140 +j03313 2S035140A111444v106424T112448l107428A06 Just 2248A096384Z037148 Anot +her 06 0240F035140i083332 Perl 083332N070280H035140l062 Hacker 24804216 +8Q0 52208x045180R052208y045180V127508I037148k041164N115460J1 Are 17468 +11646 4K099396K118472E116464A12 you 4496076304068272W070280G073292b0 a 6 +8272 299355p452113E420105H16 camel 4041180045m4681170810 person 243210 +84 a001004W92 too?? 09830 92732n116054p115234F064002F046821d120875s52 +4968' ;print$~,$\;END{ #; y/0-9//cd; eval (join "", reverse map {chr(--$_)} unpack(q!A3x3!x89,$_)); }
Applying the y/0-9//cd; removes all characters in that long string that are not within the 0-9 range. It therefore deletes anything but numbers, including the whitespace, from the string. So, we may reduce everything down to this:
!/usr/bin/perl -w print <<JAPH; Do You Dare To Try To Crack The Code Of The Perl Masters of Obfuscation? JAPH use strict; BEGIN { $_ = q# 12650406024010240810642410140403915603915611746811144410642411546011 +3452 06024004216812750803714804116410240811646411244810943610040006024004 +216 81154601024081084321004000983920732920331321094361154601024080813240 +3313 21154601024081054201174681124481114440662640331321174681164641184720 +7530 00411641204801144560451800351400331320351401114441064241124481074280 +6224 80963840371480602400351400833320833320702800351400622480421680522080 +4518 00522080451801275080371480411641154601174681164640993961184721164641 +2449 60763040682720702800732920682722993554521134201051640411800454681170 +8102 4321084001004920983092732116054115234064002046821120875524968 #; s/\s//gs; # Remove the whitespace still eval (join "", reverse map {chr(--$_)} unpack(q!A3x3!x89,$_)); }
Okay now, so the magic all lies within that eval line. Let's start with the unpack() call:
unpack(q!A3x3!x89,$_); # here is the equivalent: # The use of 'x3' confuses me, but I know that this creates # a list of 89 elements, each 3 characters long (numbers) unpack("A3x3" x 89, $_);
Okay, so now we can make everything look quite simple. Basically, the long string now contains 3-digit ascii codes. So, we split on each 3-digit number, subtract one from it to obtain the de-obfu'd number, and then reverse the list, join it together to make one string and eval it.:
#!/usr/bin/perl -w print <<JAPH; Do You Dare To Try To Crack The Code Of The Perl Masters of Obfuscation? JAPH use strict; BEGIN { $_ = q# 12606010210610103903911711110611511306004212703704110211611210910006 +004211 51021081000980730331091151020810331151021051171121110660331171161180 +750411 20114045035033035111106112107062096037060035083083070035062042052045 +052045 127037041115117116099118116124076068070073068 #; s/\s//gs; eval (join "", reverse map {chr(--$_)} m/\d{3}/g ); }
Put simply, after we are all done, here is what is being executed:
#!/usr/bin/perl -w print <<JAPH; Do You Dare To Try To Crack The Code Of The Perl Masters of Obfuscation? JAPH use strict; BEGIN { # eval (join "", reverse map {chr(--$_)} m/\d{3}/g ); # That above line makes us execute the following: CHECK { substr($~,3,3) = "ERR"; # Select STDERR as file handle $_ = join " ", qw(Just Another Perl Hacker); # obvious # Close STDERR, STDOUT is automatically selected close ($~); # Print the string and die - # no error because STDERR is closed print && die; } }
Just to clarify that CHECK {} block:
# Note that he could have simply closed STDERR here, # rather than select it, then close it. Spiffy use though! CHECK { select STDERR; $_ = join " ", qw(Just Another Perl Hacker); close STDERR; select STDOUT; print && die; }
And now, the obvious reason as to why we never see the print placed right at the beginning of the script: the real code that makes this work is located within a BEGIN {} and a CHECK{} block. We die() within the CHECK {} block (STDERR is closed, so we see no error), so the beginning of the script is only compiled and never run. Not bad at all :)
Update: Thanks to TimToady and diotalevi, I understand the use of 'x3' in the unpack() template. It simply moves the pointer 3 characters ahead in the string :)
Update: Per sugegstion by gmax, I added readmore tags to conceal the secrets :)
If the above content is missing any vital points or you feel that any of the information is misleading, incorrect or irrelevant, please feel free to downvote the post. At the same time, please reply to this node or /msg me to inform me as to what is wrong with the post, so that I may update the node to the best of my ability.
|
|---|