This is all pretty much a spoiler, so I'm tucking it all away into a readmore.
I started with the following code:
#!/usr/bin/perl -wire
# sets -w, which only tries to slightly obfuscate that i'm using -i (
+$^I) to
# hold "re". a later version of this, i added a comment below this li
+ne that
# read "# Just another Bird onawire", hoping that an observant deobfus
+cator
# would notice that that phrase contained most of "Just another Perl h
+acker,",
# had the right capitalization, and the correct number of characters,
+and lead
# the deobfuscator to believe that the comment might be used to genera
+te the
# phrase.
# set $/ to 'J' to create the capital J.
$/ = "J";
# set $\ (output record separator, saves from having to print it) to '
+,' for
# the end of the japh.
$\ = ",";
# some basic character -> ord -> math -> character machinations.
# this puts the string "kcahtona" into $r - those bits give "anoth" an
+d "hack"
# when reversed and substr'd out.
$r = join "",
map { $_ += 57; chr }
map { ord }
split //, "2*(/;65(";
# t holds a list of single character symbols in the symbol table.
@t = sort
map { if( m/^\w$/m ){
$_
}
}
keys %{ *:: } ;
# sub u returns a single space.
sub u { $" }
# sub s returns "re" . "htona" = "another" reversed.
sub s { $^I . substr $r, 3, 5 }
# sub j returns "l" . "re" . "P" = "Perl" reversed. i've learned that
+ the
# symbol table gets populated in a reliable manner (at least reliable
+enough
# for the purposes of this JAPH) to be able to count on the position i
+n a sorted
# list of single character symbol table entries.
sub j { $t[-5] . $^I . $t[-8] }
# sub P returns "re" . "kcah" = "hacker" reversed.
sub P { $^I . substr $r, 0, 4 }
# sub l returns "t" . "s" . "u" . "J" = "Just" reversed.
sub l { $t[-2] . $t[-3] . $t[-1]. $/ }
print map {
# this just adds a space (via sub u) after every word-retu
+rning
# subroutine unless it matches /ack/.
if( m/ack/ ){
$_
}
else {
$_ .= &u }
}
# calls the subroutines in order, reversing the letters in each
+word.
map { scalar reverse }
( l, &s, &j, &P);
At this point, I thought it was a little confusing, but only slightly obfuscated (if at all) when compacted, etc.
I replaced a few ","s with "=>"s, replaced "scalar" with "~~", changed m//m to m**m etc, and was left with this:
$/="J";$\=",";$r=join""=>map{$_+=57;chr}map{ord}split//=>"2*(/;65(";@t
+=sort
map{if(m*^\w$*m){$_}}keys%{*::};sub u{$"}sub s{$^I.substr$r,3,5}sub j{
+$t[-5].$^I
.$t[-8]}sub P{$^I.substr$r,0,4}sub l{$t[-2].$t[-3].$t[-1].$/}print map
+{if(m#ack#
){$_}else{$_.=&u}}map{~~reverse}(l,&s,&j,&P);
Starting to look promising, but I find it lacking a bit. I ran a quick tr/a-z0-9/b-za2-901/ and added
a way to get it eval'd and was left with this:
#!/usr/bin/perl -wire
$_=q|$/="J"; $\=","; $s=kpjo"",nbq{$_+=79;dis}nbq{pse}tqmju//,"4*(/;87
+(";@u=tpsu
nbq{jg(n*^\x$*n){$_}}lfzt%{*::};tvc v{$"}tvc t{$^I.tvctus$s,5,7}tvc k{
+$u[-7].$^I
.$u[-0]}tvc P{$^I.tvctus$s,2,6}tvc m{$u[-4].$u[-5].$u[-3].$/}qsjou nbq
+{jg(n#bdl#
){ $_ }fmtf{ $_ .=&v}}nbq{~~sfwfstf}(m,&t,&k,&P);|;
$_ =~ y[b-za2-901][a-z0-9];
eval
All well and good, except anyone can apply a mental tr/// and see that in the above code nbq=map,tvc=sub, etc.
The next step is to hide the tr/// string.
First I need some ord values with which to do some math.
sub r { 49 } # returns 49
sub a { r()-1 } # returns 48
sub b { a()-1 } # returns 47
sub c { b()+3 } # returns 50
sub d { 0 } # returns 0
... but I'd like to hide _that_ a bit, as well as throw anyone off the trail of my main tr/// (perhaps they'll try
to apply _this_ tr/// to the main block above?) - therefore:
$e=q=
fho'e{49}
fho'n{e()-1}
fho'o{n()-1}
fho'p{o()+3}
fho'q{0}
=;
$e=~y/a-z/n-za-m/;
eval $e;
So now I need a way to create the string "y/b-za2-901/a-z0-9/", and that's where the last section
comes from.
I'm essentially performing the following:
$A = ( scalar join '',
map { $a = $_ + 48;
$a = pack('c',$a); # converts ord to chr without usin
+g 'chr'
$a =~ s/(b|2)/$1-/; # appends a '-' if it's a 'b' or a
+ '2'
$a
}
( 50, 74, 49, 2, 9, 0, 1 )
);
$A now contains ( 'b-za2-901' )
$B = ( scalar join '',
map { $b = $_ + 49;
$b = pack('c',$b); # converts ord to chr without usin
+g 'chr'
$b =~ s/(a|0)/$1-/; # appends a '-' if it's an 'a' or
+a '0'
$b
}
( 48, 74, -1, 8 )
);
$B now contains 'a-z0-9'.
join '',
map { if( m/^\d+$/ ){
pack'c',$_ # if map encounters a number, convert it to chr
}
else{
$_ # otherwise, don't chr it.
}
}
( 121, 47, $A, 47, $B, 47 )
Now I've got "y/b-za2-901/a-z0-9/" and it gets eval'd and combined and obfuscated thusly:
eval join '', map{ if( m|^\d+$| ){
pack'c',$_
}
else{$_}
}
( 22 + c() + r(), b(),
( ~~ join '', map { $a = $_ + a();
$a = pack('c',$a);
$a =~ s{(b|2)}[$1-];
$a
}
( c(), 24 + c(), r(), 2, 9, d(), 1 )
), b(),
( ~~ join '', map { $b = $_ + r();
$b = pack('c',$b);
$b =~ s=(a|0)=$1-=;
$b
}
( a(), 24 + r(), -1,8 )
), b() );
And that's the point where I decided enough was enough, and stopped obfuscating :)
there are many gems including the ~~ for scalar substitution, and my inspiration for using $^I.
Hopefully, it's not bad form to post the explanation of my obfuscation to my post without giving anyone else the chance to do so :)