DEV Community

Tib
Tib

Posted on • Updated on

Japhs Autopsies (1)

This is the first post of a serie about Japhs

Japhs are crazy-cursed-science, people sometimes love them as much as they hate them 😃

Crazy Japh

Japhs could be a showcase of obfuscated, bad practices, non modern Perl code but it is also often a demonstration of Perl skills and a way to nicely highlight some features or simply demonstrate code agility.

Several Japhs were written by "Perl Grand Masters".

DO-NOT-DO

Often a Japh is more a matter of obfuscation than encryption.

This is the case of this Japh from Randal Schwartz, where a simple print"Just another Perl hacker," is surrounded by "garbage code".

$_='987;s/^(d+)/$1-1/e;$1?eval:print"Just another Perl hacker,"';eval;
Enter fullscreen mode Exit fullscreen mode

This Japh is actually full of nothing 😃

Once unfold, the code is actually very simple but there is some interesting bits here :

  • Some fun with /e modifier (= evaluate right hand side RHS)
  • A misleading (d+) capture (vicious typo : missing \ ! 😄) that leads to a $1 actually undefined
  • Some fun with eval (the Japh killer-feature 😃)
eval {
        my $v = "987"; # or my $v = 987; it is the same
        # Substitute number by himself minus one
        $v =~ s/^(d+)/$1-1/e; # /e enable right hand side as an expression
        # $v is (still) "987";
        # $1 is undefined 
        # because to work
        # capture (d+) should be (\d+)
        if(undef) {
                eval;
        } else {
                print"Just another Perl hacker,";
        }
}
Enter fullscreen mode Exit fullscreen mode

I really love this Japh !!

Jump-Jump

$_="krJhruaesrltre c a cnP,ohet";$_.=$1,print$2while s/(..)(.)//;
Enter fullscreen mode Exit fullscreen mode

The trick here is to loop over a string and take one char every 3 chars (but only one time per loop).

Having all keywords sticked together like this :

$_.=$1,print$2while
Enter fullscreen mode Exit fullscreen mode

is a way to exploit the greatness of the parser ! 😎

When I first saw this Japh, I was not sure to understand well s/(..)(.)//
because it seemed the string matched was substitued by nothing.

But is is actually kept by $_.=$1.

It is the same than this code :

my $str ="krJhruaesrltre c a cnP,ohet";

do { 
    $str .= $1; # Keep 2 char (..)
    print $2; # Print one char (.)
} while($str =~ s/(..)(.)//);
Enter fullscreen mode Exit fullscreen mode

What if we print the $str to see the content ?

krJhruaesrltre c a cnP,ohet
hruaesrltre c a cnP,ohetkr
aesrltre c a cnP,ohetkrhr
rltre c a cnP,ohetkrhrae
re c a cnP,ohetkrhraerl
c a cnP,ohetkrhraerlre
 cnP,ohetkrhraerlrec 
P,ohetkrhraerlrec  c
hetkrhraerlrec  cP,
krhraerlrec  cP,he
raerlrec  cP,hekr
rlrec  cP,hekrra
ec  cP,hekrrarl
 cP,hekrrarlec
,hekrrarlec c
krrarlec c,h
arlec c,hkr
ec c,hkrar
c,hkrarec
krarecc,
recc,kr
c,krre
rrec,
c,rr
rc,
rc
Enter fullscreen mode Exit fullscreen mode

And if you look closer, you can see the Just another Perl hacker, hidden like a sort of steganography:

kr[J]hruaesrltre c a cnP,ohet
hr[u]aesrltre c a cnP,ohetkr
ae[s]rltre c a cnP,ohetkrhr
rl[t]re c a cnP,ohetkrhrae
re[ ]c a cnP,ohetkrhraerl
c [a] cnP,ohetkrhraerlre
 c[n]P,ohetkrhraerlrec 
P,[o]hetkrhraerlrec  c
he[t]krhraerlrec  cP,
kr[h]raerlrec  cP,he
ra[e]rlrec  cP,hekr
rl[r]ec  cP,hekrra
ec[ ] cP,hekrrarl
 c[P],hekrrarlec
,h[e]krrarlec c
kr[r]arlec c,h
ar[l]ec c,hkr
ec[ ]c,hkrar
c,[h]krarec
kr[a]recc,
re[c]c,kr
c,[k]rre
rr[e]c,
c,[r]r
rc[,]
rc
Enter fullscreen mode Exit fullscreen mode

The "substitution per nothing" and the "only one time per loop" tricks are confusing for me.

In my mind, I would have prefered something like this :

my $str ="krJhruaesrltre c a cnP,ohet";

do {
        print $2; # Print one char
} while($str =~ s/(..)(.)(.*)/$3$1/);
Enter fullscreen mode Exit fullscreen mode

But one of the goal of a Japh is to confuse the reader, isn't it ?

And this goal is well achieved by this really nice Japh !

Eval-ception

This Japh from Raymond Chen is playing with eval and \ (protected quotes by antislash).

All the annoying \, " and x makes this line very blurry to the reader.

$_='x"Not ";"x\"another \";\'x\\"perl \\";x\\"hacker,\\"\'"';s/x/print/g;eval eval eval;
Enter fullscreen mode Exit fullscreen mode

It is actually relatively simple when we break down into steps to see what happens exactly :

use v5.10;

$str = 'x"Not ";"x\"another \";\'x\\"perl \\";x\\"hacker,\\"\'"';
$str =~ s/x/print/g;
# 'print"Not "; "print\"another \";\'print\\"perl \\";print\\"hacker,\\"\'"';
say eval $str;
# Not print"another ";'print"perl ";print"hacker,"'
say eval eval $str;
# Not another print"perl ";print"hacker,"
eval eval eval $str;
# Not another perl hacker,
Enter fullscreen mode Exit fullscreen mode

First eval will print Not and remove " around the rest of the line :

print"Not ";"print\"another \";'print\"perl \";print\"hacker,\"'"
            ^                                                   ^
Enter fullscreen mode Exit fullscreen mode

Second eval will print another and remove ' around the rest of the line :

Not print"another ";'print"perl ";print"hacker,"'
                    ^                           ^
Enter fullscreen mode Exit fullscreen mode

Third eval will print perl hacker, :

Not another print"perl ";print"hacker,"
Enter fullscreen mode Exit fullscreen mode

And finally this is Not another perl hacker ! 😃

The Char-taker

This is a Japh from gnebbia

use Modern::Perl;

say chr($_) foreach qw/ 
74  117 
115     116 
20          97 
110             111
116             104
101             114
20          80
101     114
108 20
72
97
99
107
101
114/;
Enter fullscreen mode Exit fullscreen mode

Simple and effective !

Not very hard to understand, but it uses some nice features from perl.

The qw actually drops some formatting for us and builds a clean array of string.

Then the indentation and spaces are ignored and chr will tranform ASCII codes into a Japh 😃

use Modern::Perl;

#              J   u   s   t      a  n   o   t   h   e   r      P  e   r   l      h  a  c  k   e   r
foreach my $d (74,117,115,116,20,97,110,111,116,104,101,114,20,80,101,114,108,20,72,97,99,107,101,114) {
        print chr($d);
}
Enter fullscreen mode Exit fullscreen mode

This Japh does not really confuse the reader, but force to dig a bit into language understanding, and that's very cool ! 😎

Split-Sort-Grep

Randal Schwartz, in addition of being Japh #0 is one of the master of the Japh competition.

He plays often a lot with split combined with some other operands, here it is grep and sort.

print grep(s/^\d+(.*)/$1 /, sort(split(/ /,"8hacker, 4Perl 1Just 2another")));
Enter fullscreen mode Exit fullscreen mode

I feel comfortable with this one, I see the Japh unordered but there is a sort not far and numbers will give the ordering 😁

It is a way to properly demonstrate some Perl killer features like easy string manipulation and regular expressions.

We can detail this one liner into an equivalent script :

my $str = "8hacker, 4Perl 1Just 2another";
my @s = split " ", $str;
@s = sort @s;
# 1Just 2another 4Perl 8hacker,
foreach my $v (@s) {
        $v =~ s/^\d(.*)/$1/;
        print $v . " ";
}
Enter fullscreen mode Exit fullscreen mode

$1 is what is matched between parenthesis.

sort will not convert to numeric but compare string, if you're not convinced, please check this example :

my $str = "09first 2third 1second"; 
print join " ", sort split(" ", $str);
Enter fullscreen mode Exit fullscreen mode

That produces :

09first 1second 2third
Enter fullscreen mode Exit fullscreen mode

Despite being relatively simple, this is a cool Japh, demonstrating some nice Perl features. 😃

Turtle Neck

OH! Turtleneck phrase jar! 😲

$_ = "wftedskaebjgdpjgidbsmnjgc";
 tr/a-z/oh, turtleneck Phrase Jar!/; print;
Enter fullscreen mode Exit fullscreen mode

This Japh is playing with transliteration operator, the regex range and the default variable $_ features.

The tr is an operator to translate (like the Unix tr command line).

a-z in the regex is actually implicitely transformed into abcdefghijklmnopqrstuvwxyz.

Then we only have to pick our Japh using the "key" wftedskaebjgdpjgidbsmnjgc ! 😎

Once unfold, the Japh looks like this :

my $str = "wftedskaebjgdpjgidbsmnjgc";
$str =~ tr/abcdefghijklmnopqrstuvwxyz/oh, turtleneck Phrase Jar!/;
print $str;
Enter fullscreen mode Exit fullscreen mode

Relatively simple, but a very cool Japh !

Conclusion

This is the end of my first post about Japhs !

Crazy Japh

I hope you enjoyed as much as me 😁

Check the next post of the serie

Top comments (5)

Collapse
 
matthewpersico profile image
Matthew O. Persico

Typo in Split-Sort-Grep section: Randal Schwatz.

Collapse
 
thibaultduponchelle profile image
Tib

Fixed thank you a lot 👍

Collapse
 
matthewpersico profile image
Matthew O. Persico

I prefer to make those kind of typo-torial comments in private but it wasn't obvious to me where to send them. My email is first dot last at the google mail address.

Thread Thread
 
matthewpersico profile image
Matthew O. Persico

Unless I'm just missing something about your profile?

Thread Thread
 
thibaultduponchelle profile image
Tib

Same email pattern for me 😃

No problem for "public" corrections, I always warmly welcome corrections and I often edit my posts to include some content from comments or even strike through some of my sentences 😝