Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Re: first posted obfu, explanation

by chargrill (Parson)
on Jan 17, 2006 at 19:02 UTC ( [id://523809]=note: print w/replies, xml ) Need Help??


in reply to first time caller, long time listener

I just thought I'd post the steps I took to create this.

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 :)

Many thanks to the following monks, tidbits, and snippets: gmax and their post Structured obfuscation - the fifth level of obfuscation listed there in particular, and in Writing highly obfuscated code in Perl 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 :)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://523809]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (4)
As of 2024-03-28 15:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found