解析/分解 - 逐步解开这个混淆的Perl脚本

7
作为标题所述 - 请问有人能解释一下下面的脚本是如何工作的吗?
这段代码会输出文本:"Perl guys are smart"。
''=~('(?{'.('])@@^{'^'-[).*[').'"'.('-[)@{:__({:)[{(-:)^}'^'}>[,[]*&[[[[>[[@[[*_').',$/})')

这个代码只会输出 "b"

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

perl -MO=Deparse 只显示以下内容:

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

但是我不知道为什么... ;(

如何推荐分解类似的脚本?从哪里开始?

因此,尝试了这个:

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

几个部分通过.连接在一起。按位异或^的结果可能会给出文本部分。这些是:

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

打印出 "Perl guys are smart" 和第一个 ^ 生成的 "print"。

但是,当我将其重写为:

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

我的Perl告诉我:

panic: top_env

奇怪,我第一次看到这样的错误消息...

这意味着不能用result替换'str1' ^ 'str2'(不知道为什么),那么为什么Perl会打印出panic消息?

我的Perl版本:

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

Ps: examples are generated here


3
但事实上,没有人应该编写这样的代码,因此无需理解它。 - Oliver Charlesworth
7
现在明白了,没有人应该受伤,因此没有理由学习急救。 ;) - cajwine
2
实际上,我觉得这很有趣,我也想理解它。 - Zagorax
5
@OliCharlesworth,我真的不明白为什么你不能把它仅仅视为“使用Perl完成奇怪操作”的简单演示。我非常确定没有人会在现实生活中使用它。但这并不意味着,至少,这样的代码能够生成字符串是有趣的。 - Zagorax
1
@Zagorax:首先,OP已经说明他/她没有学习过Perl;我们不是替代品。其次,作为一个SO问题,它的用处就像“你能解释一下IOCCC中的例子XYZ是如何工作的吗?”任何人都可以用任何语言编写一个可怕的复杂的混淆代码,但这并不使它有趣或有用。 - Oliver Charlesworth
显示剩余3条评论
2个回答

6

在线

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

当你对 ']' ^ '-' 进行评估时,结果将是字母 p^ 是一种按位字符串操作,因此在此之后,我们按字母顺序得到结果字符串。

检查我的脚本,它的工作方式类似于你的示例。我希望它能帮助你。

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;
}

3
理解这里发生的事情的诀窍是看正在被XOR和连接构建的字符串:
(?{print "Perl guys are smart",$/})

这是一个实验性的正则表达式特性,形式为(?{ code })。因此,您在终端上看到的打印结果就是其结果。
print "Perl guys are smart",$/

''=~...调用。 $/是Perl的输入记录分隔符,默认情况下是换行符。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接