Obfuscation

It should be plain to anyone who has created a JAPH that obfuscation is an art: misdirection, character alignment, and even wordplay are common elements in good "obfu." This makes it easy to distinguish between the creations of masters such as abigail and merlyn and the blunderings of Perl initiates. Take this infamous JAPH by abigail:

$;                                   # A lone dollar?
=$";                                 # Pod?
$;                                   # The return of the lone dollar?
{Just=>another=>Perl=>Hacker=>}      # Bare block?
=$/;                                 # More pod?
print%;                              # No right operand for %?

This JAPH blew my mind when I was first getting into Perl. Mainly because I thought ; always, always, always ended a line. If we properly reorder it, things make a bit more sense:

$; = $";
$;{Just=>another=>Perl=>Hacker=>} = $/;
print %;

But there's still some magic happening. $; is the input record separator, or the character that's printed between elements of an array/hash, and $" is just a space by default. On the second line we see $; again, but it's immediately followed by a hash key. This makes no sense whatsoever.
The secret is that this $; has no relation to the previous $;. Because we're using it in a hash context, $; is telling the Perl interpreter that we're creating a new array, %;, and placing a key/value pair inside it. That value, by the way, is another special character, which is a newline by default. Since I'm somewhat "old school," I think it should be ',', but I guess $/ fits the theme better. All that's left to do is print out the hash, which has just one key/value pair (and yes, there's a missing semicolon at the end). Genius.

On the other end of the spectrum, here's a more amateur JAPH that I came across, titled "My first JAPH":

use 5.10.0;
$p=japh;push@a,w();$s=j4;sub n{"8fbac6c6e252"};unshift@a,
"b4d6c7ea52a7";$k=crypt($s,$p);$o="aeafa7cfdbd597";@h=
map{sprintf"%x",ord($_)}split//,$k;push@a,$o;$a[3]=pop@a;
$a[2]=n();sub w{"bcb3d8dec8dd"}$x.=$_ for@a;@b=($x=~m/..?/g);
push@z,@h until @z>@b;for(@b){push@japh,hex($_)-hex($z
[$n]);$n++;}say map{chr$_}@japh;


There are quite a few things wrong here. Glaringly obvious are the misplaced line breaks; ideally, they should format the code into a solid block or other aesthetically pleasing pattern, but this code is simply a jumbled mess. use 5.10.0 is also unnecessary; it merely allows the use of say on the last line, which is easily changed to print.
Let's pick this thing apart:

$p = japh;
push @a, w();
$s = j4;
sub n {
  "8fbac6c6e252";
}
unshift @a, "b4d6c7ea52a7";
$k = crypt($s, $p);
$o = "aeafa7cfdbd597";
@h = map{sprintf "%x", ord($_)} split //, $k;
push @a, $o;
$a[3] = pop @a;
$a[2] = n();
sub w{
  "bcb3d8dec8dd";
}
$x .= $_ for @a;
@b = ($x =~ m/..?/g); 
push @z, @h until @z > @b;
for (@b) {
  push @japh, hex($_) - hex($z[$n]);
  $n++;
}
print map{chr $_} @japh;

Don't get me wrong, the author's original code is certainly obfuscated, in that its essential machinations are difficult to discern. But expanding it out like this reveals that most of the obfuscation at work was devoid of cleverness or whimsy, as seen in the previous example. Note the definitions upon definitions; the subroutines that simply return a string; the push and immediate pop of @a. These are simple misdirections that betray a much simpler algorithm at work. Remember, folks: security through obscurity isn't security at all. After a bit of reverse engineering, I produced my own version of this JAPH:

@b=split/ /,'b4 d6 c7 ea 52 c7 bc b3 d8 de '  .
'c8 dd 8f ba c6 c6 e2 52 ce af a7 cf db d5 97';
@h=map{sprintf"%x",ord} split//,crypt(j4,japh);
print chr(hex(@b[$_])-hex(@h[$_%13]))for 0..24;

That's over 140 characters of bloat shaved off -- large enough for another JAPH! I'll spare you the gory details, but suffice to say there's a lot of unnecessary code here. I also took the liberty of arranging the code into the standard "block" form, and I took care to make sure the hex numbers lined up, despite the slight ugliness required in the first line.
Now we see how simple this JAPH really is: it simply creates two arrays of hexadecimal numbers, subtracts one from the other, and prints out the corresponding character. For example, 6a is subtracted from b4, producing 4a, which is 74 in DEC, which corresponds to the ASCII character 'J'. @h is generated using crypt? and sprintf?, and @b was probably generated through trial and error.

So in essence, this is simple code surrounded by trivial fluff, which makes it unsatisfying to pick apart. Anyone can tack on unused variable definitions and hide strings in subroutines; good obfu means exploiting loopholes, drawing pictures, leaving hidden messages. It means code that is not hard to read, but code that is hard to grok.

Leave a Reply

Theme: Esquire by Matthew Buchanan.