7

As the title - please can anyone explain how the next scripts works

this prints the text: "Perl guys are smart"

''=~('(?{'.('])@@^{'^'-[).*[').'"'.('-[)@{:__({:)[{(-:)^}'^'}>[,[]*&[[[[>[[@[[*_').',$/})')

this prints only "b"

use strict;
use warnings;
''=~('(?{'.('_/).+{'^'/]@@_[').'"'.('=^'^'_|').',$/})')

the perl -MO=Deparse shows only this:

use warnings;
use strict 'refs';
'' =~ m[(?{print "b",$/})];

but havent any idea why... ;(

What is the recommended way decomposing like scripts? How to start?

so, tried this:

'' =~
(
        '(?{'
        .
        (
                '])@@^{' ^ '-[).*['
        )
        .
        '"'
        .
        (
                 '-[)@{:__({:)[{(-:)^}' ^ '}>[,[]*&[[[[>[[@[[*_'
        )
        .
        ',$/})'
)

several parts are concatenated by .. And the result of the bitwise ^ probably gives the text parts. The:

perl -e "print '-[)@{:__({:)[{(-:)^}' ^ '}>[,[]*&[[[[>[[@[[*_'"

prints "Perl guys are smart" and the first ^ generating "print".

But when, i rewrite it to:

'' =~
(
    '(?{'
    .
    (
        'print'
    )
    .
    '"'
    .
    (
         'Perl guys are smart'
    )
    .
    ',$/})'
)

My perl told me:

panic: top_env

Strange, first time i saw like error message...

Thats mean: it isn't allowed replace the 'str1' ^ 'str2' with the result, (don't understand why) and why the perl prints the panic message?

my perl:

This is perl 5, version 12, subversion 4 (v5.12.4) built for darwin-multi-2level

Ps: examples are generated here

cajwine
  • 3,100
  • 1
  • 20
  • 41
  • "Learn Perl" is the obvious answer. – Oliver Charlesworth Jun 16 '12 at 10:51
  • 3
    But really, no-one should be writing code like this, so there is no reason to have to understand it. – Oliver Charlesworth Jun 16 '12 at 10:52
  • 7
    Now understand. No one should be injured, so here is no reason learning first aid. ;) – cajwine Jun 16 '12 at 10:59
  • 2
    Actually, I find it interesting and I would like to understand it, too. – Zagorax Jun 16 '12 at 10:59
  • 1
    @cajwine: If anyone writes code like this (other than as a joke), then they're an idiot. If you find yourself in (for example) a work environment where code like this is tolerated, then you should leave. But either way, I would still recommend "learn Perl" as the first step! – Oliver Charlesworth Jun 16 '12 at 11:02
  • For some time it seemed to me that *all* Perl code looked like this... – thkala Jun 16 '12 at 11:03
  • 5
    @OliCharlesworth, I really don't understand why you can't accept it only as a simple demonstration of "strange things done with perl". I'm quite sure none is using it in real life. This doesn't mean that it is, at least, interesting that such code can generate string. – Zagorax Jun 16 '12 at 11:08
  • 1
    @Zagorax: Because firstly, the OP has stated that he/she hasn't learnt Perl; we're not a substitute for that. Second, as a SO question, it's about as useful as "can you explain how example XYZ from the [IOCCC](http://www.ioccc.org/) works?". Anyone can write a horrible convoluted obfuscated piece of code in any language, that doesn't make it interesting or useful. – Oliver Charlesworth Jun 16 '12 at 11:10

2 Answers2

6

In the line

.('_/).+{' ^ '/]@@_[

when you evaluate ']' ^ '-', the result will be the letter p. ^ is a bitwise string operation, so after that we follow letter by letter to get result string.

Check my script, it works like your example. I hope it will help you.

use v5.14;

# actually we obfuscated print and your word + "
# it looks like that (print).'"'.(yor_word")
my $print  = 'print';
my $string = 'special for stackoverflow by fxzuz"';

my $left  = get_obfuscated($print);
my $right = get_obfuscated($string);

# prepare result regexp
my $result = "'' =~ ('(?{'.($left).'\"'.($right).',\$/})');";

say 'result obfuscated ' .  $result;
eval $result;

sub get_obfuscated {

    my $string = shift;
    my @letters = split //, $string;

    # all symbols like :,&? etc (exclude ' and \)
    # we use them for obfuscation
    my @array = (32..38, 40..47, 58..64, 91, 93..95, 123..126);

    my $left_str = '';
    my $right_str = '';

    # obfuscated letter by letter
    for my $letter (@letters) {

        my @result;
        # get right xor letters
        for my $symbol (@array) {

            # prepare xor results
           my $result = ord $letter ^ $symbol;
           push @result, { left => $result, right => $symbol } if $result ~~ @array;
        }

        my $rand_elem = $result[rand $#result];
        $left_str  .= chr $rand_elem->{left};
        $right_str .= chr $rand_elem->{right};
    }

    my $obfuscated = "'$left_str' ^ '$right_str'";
    say "$string => $obfuscated";

    return $obfuscated;
}
daxim
  • 39,270
  • 4
  • 65
  • 132
Pavel Vlasov
  • 3,455
  • 21
  • 21
3

The trick to understanding what's going on here is to look at the string being constructed by the XORs and concatenations:

(?{print "Perl guys are smart",$/})

This is an experimental regular expression feature of the form (?{ code }). So what you see printed to the terminal is the result of

print "Perl guys are smart",$/

being invoked by ''=~.... $/ is Perl's input record separator, which by default is a newline.

flesk
  • 7,439
  • 4
  • 24
  • 33