Perl is famous for its ability to create programs that are entirely illegible to everyone but the developer who wrote them. The Perl community even has obfuscation contests to see who can write the most unintelligible Perl code.
-- Andrew Clinick, Microsoft Scripting Program Manager in Perl of Wisdom
it's almost depressing to think that someone might actually believe this. Programmers, not languages, write obfuscated code; and Perl certainly didn't invent the concept.
-- brian d foy response on comp.lang.perl.misc 16 February 1999
I may have become partially famous for my obscure one-liners here on Usenet, but when I write production code for hire, it's compact but readable and well-documented ... let us please stop passing around the myth that Perl *is* write-only code, or *encourages* write-only code.
-- Randal L. Schwartz response on comp.lang.perl.misc 1st March 1999
Let me begin this meditation on recreational obfuscation by reaffirming brian_d_foy's and merlyn's responses above: Perl is indeed a fine language for writing compact yet readable and maintainable systems.
Though Obfuscation has no place in production code, writing deliberately obfuscated code as a recreational pastime forms a proud part of Perl's history and culture -- a fun way to explore TMTOWTDI and the rich expressiveness of the language.
Obfu participation, of course, is optional, and many Perl programmers have no interest in it. Indeed, the following Perl generalissimos have never fired an obfuscated monastic projectile in anger: vroom, merlyn, dws, dragonchild, davorg, Elian, brian_d_foy, TheDamian and TimToady (though, admittedly, Tim did flirt briefly with C obfus in the mid 1980s). In case you're interested, from the PM top 40, the most prolific obfuscator is number 23, davido, with 30 obfuscated notches in his belt.
This, the third part of the seemingly never-ending series on the lighter side of Perl culture, focuses on artistic (or recreational) obfuscation. Naturally, I won't waste time on obfuscation for job security or, horrors, for perverse and futile attempts to close open source.
History
Obfuscated code began long before Perl did. In 1972, for example, Messrs Woods and Lyon outraged the conservative IBM/Cobol world by implementing INTERCAL on an IBM 360. Not to mention the International Obfuscated C Code Contest of '84, contested over three years before Perl's glitzy launch on 18 December 1987.
Perhaps the earliest example of obfuscated Perl code were some JAPHs concocted by merlyn in the early 1990s. These early JAPHs, however, were only mildly obfuscated compared to those inspired by fierce competition in the TPJ-sponsored Obfuscated Perl Competitions, started in 1996, and run by Jon Orwant and Felix Gallo.
Another significant promoter of obfu is the Perl Monks web site, sporting a distinct Obfuscated Code section, containing around 500 compositions. Indeed, from over half a million nodes, the most popular PM node of all time is an obfuscated one, the famous camel code.
Finally, it should come as no surprise that the country hosting The Louvre is also home to many eminent Perl obfu artisans. In particular, the Paris Perl Mongueurs (sic) have a long tradition of artistic obfuscation, evident from one of the finest obfu pages on the web, $A++.
Constraints
The more constraints one imposes, the more one frees oneself of the chains that shackle the spirit... the arbitrariness of the constraint only serves to obtain precision of execution.
-- Igor Stravinsky, 1882-1971
Constraints are the heart of obfu. When viewed as an art form, obfu seems closest to poetry (which is constrained by rhyme and meter) and Oulipo (formal constraints in literature, a famous example being Georges Perec's 300 page novel "La Disparition", written without using the letter 'e').
Perl obfu constraints might be classified as follows:
- Hard for human reader to understand
- JAPH
- $A++
- Restricted character set
- Restricted Perl subset
- Ascii art
- Size
- Perform a specified function
- Multi-lingual
- Quine
- Palindromic
Further to the above list, obfu specialists are always on the lookout for an original and surprising new constraint.
Hard for Human Reader to Understand
An obfu should be made as difficult as possible to comprehend, not only by using cheap tricks -- such as y}}}c instead of length -- but by employing unnatural algorithms. For some general tips on how to make code harder to understand, see Learning from Obfuscation. A fine example of an unnatural algorithm is described by MJD here.
JAPH
An obfuscated JAPH is constrained to output the string "Just another Perl hacker," -- for more information on JAPHs, see The Lighter Side of Perl Culture (Part II): JAPH.
$A++
$A++ is a deformation of "A plus" which is itself the common way to shorten "A plus tard". It is for the French what "see you" is to "see you later" in English.
-- stefp
And for the Australians, what "see ya" is to "see ya later mate" (or "see ya later cobber").
💲🅰➕➕🙋
Like the JAPH, the $A++ is just an arbitrary canonical program. An $A++ does not emit anything, it simply increments the variable $A. Traditionally, it's a parting word to end an email with, so it should be short.
The first $A++ was composed by BooK on Friday Oct 15 1999:
Not bad for a first attempt! A bit more interesting than the first JAPH. ;-)$A = eval q.@{[.."0,"x$A.qq|0]}|
From the BooK archives, here are the earliest $A++s:
1999/10/15 BooK $A = eval q.@{[.."0,"x$A.qq|0]}| 1999/11/04 BooK $A =~ s/$A/$A+1/e 1999/11/04 Moun inc( $a, $a, $tchoum ); sub inc { map { s/^(.*)$/$1 ++1/e; } @_ } 2000/01/31 BooK for(map{2**$_}(0..31)){if(($A&$_)==0){$A|=$_;last}else{$A&=~$_}} 2000/02/18 BooK $A+=@{[$A]} 2000/02/21 Moun $A = ((@S=("($A==$S[1])?($S[1]+1):(($S[1]++,eval($S[0]))[1])",0)),eval($S[0 +]))[1] 2000/03/13 BooK $A =~ s/(-)?(\d+(?:\.\d*)?)/$1.($2+($1?-1:1))/e 2000/03/13 BooK $A =~ s/(-)?(\d+(?:\.\d*)?)/"$1 1+"x$2.'1'/egoisme 2000/03/17 BooK $A+=0<<1|2<<3>>4 2000/03/24 BooK $A=~s/(-)?(\d+(?:\.\d*)?)/# les filles c'est des cl +oches (Souchon) "$1 1+"x$2.'1'/sexisme 2000/03/30 BooK $A=@{[($A)x$A,$A]} 2000/03/30 BooK $A=~s/($A)/$1+1/e 2000/03/31 BooK A:goto(A)if$A!=$A+++1 2000/04/05 BooK $A=$A{$A}?&{$A{$A}}($A):&{$A{$A}=sub{1+shift}}($A) 2000/04/05 grinder $a = do{ while(1&$a) {$a>>=1}continue {++$b}($a|1)< +<$b }; 2000/04/06 grinder $a = do{$_=!$_;$_<<=1 while($a&$_<<1<=$a);($a&$_|1)+($a&$_&&$a&~$_|1||$a& +~$_)}; 2000/04/11 stefp ${ '`' | '!' } -= $#$ + ${""} - ${''} 2000/04/11 stefp $ {'`'| '!'}-=-- +$#$+ $ { ""}- --$ { ''} 2000/04/12 BooK *A=\($A+1) 2000/04/12 grinder use Cobol; PROCEDURE DIVISION ADD 1 TO A GIVING B MOVE B TO A 2000/04/12 grinder $A = do{$_=!$_;$_<<=1 while(${'@'|'!'&~'"'}>=${'@'|'!'&~'"'}&$_<<1);(${'@'|'!'&~'"'}&$_|1)+( +${'@' |'!'&~'"' }&$_&&${'@'|'!'&~'"'}&~$_|1||${'@'|'!'&~'"'}&~$_)}; 2000/04/13 stefp use AI; incrémente la variable scalaire a de 1 unité +# $a++ 2000/04/13 stefp ${"A\0comme quoi perl n'ignore pas partout les \0"} +++
On Apr 12 2000, grinder proposed that these $A++s be collected and put on an $A++ web page.
Update (2012): Re: your obfuscation magic! lists a couple of nice $A++ obfus
Restricted Character Set
In this $A++:
Nicholas Clark restrains himself to non-alphanumeric characters only. The converse, a speciality of mtve, is illustrated by another $A++:${~$/&~$;&$^}++
y ccccd x s vvchr oct oct ord uc ave x s vvucve le s vvuc ave x s vvchr oct oct oct ord uc bve x eval
For obfus restricting themselves to not using any punctuation at all, see:
- No more $$$ by mtve
- Yet Another Obfuscation Engine by mtve
- Yet Another**2 Obfuscation Engine by mtve
- Yet Another**3 Obfuscation Engine by mtve
- Fun With Reserved Keywords by blokhead
- exactly 390 bytes by anonymous
- Re: Re: exactly 390 bytes by ambrus
- Ode for getprotobyname by ambrus
- Indigo japh by ambrus
- ppencode by dankogai
Restricted Perl Subset
Damian Conway's Extreme Perl -- The Horror That Is SelfGOL is an, er, horrific example, constraining itself to not importing any modules, and not using a single if, unless, while, until, for, foreach, goto, next, last, redo, map, or grep.
Constraints sometimes happen accidentally. When writing a little Sierpinski triangle generator, for example, I noticed it seemed to be using an awful lot of s/// operations ... so I naturally tried to make it use only this operator. Then, I noticed a lot of 'g' and 'e' characters ... so I tried to use as many of these as possible. None of this was planned, it just sort of happened. Here is the final result (it takes a command line argument (1-9) indicating the triangle size).
#!/usr/bin/perl -l s--@{[(gE^Ge)=~/[^g^e]/g]}[g^e]x((!!+~~g^e^g^e)<<pop).!gE-ge, s-[^ge^ge]-s,,,,s,@{[(g^';').(e^'?')]},(G^'/').(E^'|')^Ge,ge, print,s,(?<=/[^g^e])[^g^e][^g^e],$&^(G^'/').(E^'|')^gE,ge-ge
Ascii Art
The constraint here is that your code must fit into a specified shape. Some obfus are further constrained in that only certain characters may fill certain parts of the shape.
If you employ this style of obfu, strive to extend the theme defined by the shape to the source code itself. Note in camel code for example, Erudil's choice of variable names: $camel, @dromedary, @camelhump, and so on. To further illustrate, when tuning Saturn, I changed O^N^E}(@X,1.6) to S|A|T|U}(@R,$N) to better align the code to the Saturnian theme.
Size
There are often practical limits on the size of an obfu. In the TPJ Obfuscated Perl Contests, for example, the original 1024 character size limit was reduced by the judges to 512 bytes for OPC 5 -- which was a nasty spoiler for those entrants, such as BooK (Perl/Postscript obfu) and TheDamian (SelfGOL), who had prepared 1024-byte entries months in advance! Other obfu types limited by size are JAPH, $A++ and Ascii Art.
Overcoming size limits can be a chronic nuisance, requiring considerable golfing skills in addition to obfuscation ones. And significant golfing often spoils the artistic merit of the obfu.
Perform a Specified Function
A common constraint is to perform a specified function, such as fly through a Mandelbrot, as in Mandelbrot flythrough, or play a game, as in Space Invaders. Apart from playing games, spectacular visual effects and mathematical algorithms are popular choices for obfus.
Multi-Lingual (Polyglot)
Some early PM examples of these are P(ython|erl) (suck|rule)s! and BooK's C is Perl response to Ovid's Perl is C provocation.
BooK's prize-winning OPC 5 Perl/Postscript obfu can be found here.
Lyon's fiercely competitive Jerome Quelin tried to "out-BooK" BooK in his YAPC::Europe 2003 talk by showcasing an octo-lingual (perl, c, c++, befunge, brainf**k, python, ook, html/javascript) program that computed the Fibonacci series.
Update: For a list of polyglot references started by ambrus see: List of polyglot obfus (Re: Christmas poem since 1988).
Palindromic
An $A++ penned by the mtve:
!$A+++!q!+++A$!
Humour
When composing an obfu, always be on the lookout for opportunities to add humour -- as Abigail did in the classic Things are not what they seem like..
Exploring the Medieval Castle
Programming in Perl5 is like exploring a large medieval castle, surrounded by a dark, mysterious forest, with something new and unexpected around each corner. There are dragons to be conquered, maidens to be rescued, and holy grails to be quested for. Lots of fun.
-- Abigail in December 2002 Perl 6 Summary
Exploratory obfuscation is perhaps more fun in Perl than most languages. Why? For starters, there ain't no Ansi Perl. And there are numerous experimental, obsolete (e.g. D'oh not D::oh), half-baked (e.g. typed declarations) and undocumented (e.g. Japhy explains where behaviour of --$| is documented) features begging to be exploited by the evil obfuscator. Moreover, Perl offers more freedom and fewer limitations than most languages -- consider, for example, composing a Python Ascii Art obfu, given its ludicrous indentation rules.
Two sample exploratory $A++ obfus from stefp are:
and%average::; print probably not my average $A++
sub _ : lvalue { $A }; ++_();
Perl 6 is expected to be less fun for the obfuscator. Most people consider this to be a feature, but not Abigail, who further opined: "Perl6 looks like a Louis-XVI castle and garden to me. Straight, symmetric, and bright. There are wigs to be powdered, minuets to be danced, all quite boring.".
Some Classic Obfus
There are many obfus I've never seen. Please let us know of any classic obfus I've overlooked.
- My 2 cents worth
- There can be only one!
- Things are not what they seem like.
- camel code
- How to (ab)use substr
- 3-D Stereogram, Self replicating source.
- spiraling quine
- Just another Bach Hacker
- Fun With Reserved Keywords
- hello world
- Mandelbrot flythrough
- The Power of Three
- Saturn
- Magic 8 Ball
- Game of life ran by unpack function
- The Horror That Is SelfGOL (update: Selfgol)
- Surprise C obfu
- BooK's TPJ OPC 5 Perl/Postscript obfu
- MJD's TPJ OPC 5 entry
Some Keen Perl Monk Obfuscators
Please let me know of any I have overlooked.
- Abigail
- ambrus
- benn
- blokhead
- BooK
- BronzeWing
- chargrill
- clintp
- cog
- davido
- domm
- Erudil
- gmax
- Grimy
- grinder
- japhy
- Jasper
- jbware
- joecamel
- Len
- liverpole
- mtve
- o0lit3
- stefp
- teamster_jr
- Toodles
- trizen
- kschwab
- drpaz
- ColonelPanic
References
- Learning from Obfuscation
- Principles of obfuscation?
- New Section: Obfu Art Gallery?
- Writing highly obfuscated code in Perl
- Deobfuscation for fun and profit
- Structured obfuscation
- Yet another structured obfuscation
- japhy's Obfuscation Review
- jynx obfu tips
- BooK's YAPC::Europe 2000 talk
- domm's YAPC::Europe 2002 talk
- Language::Befunge
- Oulipo
- Intercal Resources Page
- Brainf**k
- Unlambda
- The Quine Page
- List of polyglot obfus (Re: Christmas poem since 1988)
- The Polyglot List
- polyglot quines
- polygot quine in OCaml, Haskell and Scheme
- Japhy's Quine module
- Polyglot, a program in 8 languages
- A program in 4 languages by Jerome Quelin
- Hello World in four languages... at the same time
- Polyglot Japh
- The Best Ever
- TPJ OPC 0
- TPJ OPC 1
- TPJ OPC 3
- TPJ OPC 4
- TPJ OPC 5
- European domination at TPJ OPC 3
- cam.pm Obfuscated Programming Contests
- wikipedia Obfuscated_code
- wikipedia Obfuscated_Perl_contest
- c2.com ObfuscatedPerl entry
- Games, Diversions & Perl Culture
References Added Later
- Re^3: Module to extract text from HTML by marto (2024) - suggests a reverse code golf challenge (the most convoluted way to achieve the goal) ... I guess this is closer to obfu than golf.
- Rube Goldberg machine
- Re: perl one liner for csv file one field (useless use of cat and other awards References)
- The wise coder - an excellent poem by hippo
- Competition: deceptive code
Bad code references:
- The joys of bad code by BUU (2004)
- Need Bad Code by SleepyJay (2007)
- Re^3: Where to place POD by hv (2024)
- The Daily WTF (wikipedia)
- The Daily WTF
- Competition: deceptive code by sfink (2008)
- Things are not what they seem like. by Abigail (2000)
- can someone help me? by xiper (2004)
Obfuscation Generators
Though I find these of academic interest, they are of little interest to obfuscators because they detract from artistic merit and originality. Two examples of these are Yet Another Obfuscation Engine and Acme::EyeDrops.
Is Obfu related to Golf?
As pointed out by champion golfer Eugene van der Pijll, there is usually little overlap between obfu and golf (the subject of the next installment of this series), a different mindset being required by each.
Occasionally however, a golfer accidentally produces a highly obfuscated solution in the heat of battle. In TPR(0,5a) (won by Eugene), for example, Michael Thelen commented: "How absolutely confusing! Replacing parens with whitespace makes this probably the most obfuscated program I've ever written" on his way to producing this infix to RPN converter:
#!perl -lp y/()^I /^I_/d+s@^I|(?<=\w)\D@($/=" $&$/")=~s#_(\C*?)^I|(\S)([ */${":"x/\G[+-]/}]*)#$2 #;$+@eg;$_.=$/;y/ / /s+chop
Acknowledgements
I would like to thank BooK and stefp for their help in preparing this article.
Other Articles in This Series
- The Lighter Side of Perl Culture (Part I): Introduction
- The Lighter Side of Perl Culture (Part II): JAPH
- The Lighter Side of Perl Culture (Part IV): Golf
- The Lighter Side of Perl Culture (Part V): Poetry
- The Lighter Side of Perl Culture (Part VI): April Fools
Updated June 2014: Added Magic 8 Ball to list of "Some Classic Obfus". Thanks ambrus for mentioning this. Nov 2018: Added list of polyglot references started by ambrus: List of polyglot obfus (Re: Christmas poem since 1988). Dec 2020: Added more comprehensive list of obfus restricting themselves to not using any punctuation characters at all (thanks BooK). Nov 2023: Added $A++ emoji from Perl Secret Operator Emojis
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: The Lighter Side of Perl Culture (Part III)
by Jenda (Abbot) on Jan 24, 2005 at 13:35 UTC | |
by eyepopslikeamosquito (Archbishop) on Jan 25, 2005 at 09:16 UTC | |
Re: The Lighter Side of Perl Culture (Part III)
by Anonymous Monk on Jan 24, 2005 at 03:13 UTC | |
by eyepopslikeamosquito (Archbishop) on Jan 24, 2005 at 08:01 UTC | |
by Anonymous Monk on Jan 28, 2005 at 03:38 UTC | |
Re: The Lighter Side of Perl Culture (Part III)
by kutsu (Priest) on Jan 24, 2005 at 15:27 UTC |