首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >这种模糊的Perl是如何工作的?

这种模糊的Perl是如何工作的?
EN

Stack Overflow用户
提问于 2013-06-29 23:11:08
回答 1查看 1.5K关注 0票数 2
代码语言:javascript
复制
    #!/bin/perl
    use strict;
    use warnings;
    my($japh,$q,$qq,%b)= "Just another Perl hacker\n";
    $_=join'',(
    07625127776,
    0122456410,
    03441733416,
    01420121552,
    04373570104,
    07143446334);s#9#f#;#s;#f#9#s;;
    s}9}b};$q=$_;*9=
    sub {
        $japh = "";
        print $japh;
    }; map { /^((?i)(?#q#;
    print $japh;#()[^
    for (my $(b) = 1; $(b) < $(q); \$b++;) {
        \/g])+[\](^.^)\[
    }
    ]*$/x?do{$qq=((ord)-96).(~~%b-$?)
    ;$/#;
    =$+;$q=~s/$qq/${\/}/g;}:9->({});
    }qw(
    a b c d e f g h i j k l m n o p q r s t u v w x y z
    );$qq=[$q,%b];$\=pack q*h\**
    ,qq$$.$$qq[0];9->();

我认为其中很多都是额外的/纯粹的混淆。我知道我们把“又一个Perl hacker”赋值给$japh,然后把它打印出来,然后再赋值给"“,所以我不明白这是怎么回事。有人能解释一下这是怎么回事吗?谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-06-30 00:10:04

理解混淆的№的步骤1:通过-MO=Deparse运行它。然后,我们得到这个输出:(去掉了一个小的语法错误)

代码语言:javascript
复制
use warnings;
use strict;
my($japh, $q, $qq, %b) = "Just another Perl hacker\n";
$_ = join('', (1045737470, 21650696, 478656270, 205562730, 602861636, 965627100));
s/9/f/;
s/9/b/;
$q = $_;
*9 = sub {
    $japh = '';
    print $japh;
}
;
map {m{^((?i)(?#q#;
    print \$japh;#()[^
    for (my $(b) = 1; $(b) < $(q); \$b++;) {
        /g])+[\](^.^)\[
    }
    ]*$}x ? do {
    $qq = ord($_) - 96 . (~~%b - $?);
    $/ = $+;
    $q =~ s[$qq][$/]g
} : 9->({});} 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z';
$qq = [$q, %b];
$\ = pack('h*', '' . $$qq[0]);
9->();

还是不漂亮,但更好了。特别是,这个正则表达式看起来很有趣:

代码语言:javascript
复制
m{^((?i)(?#q#;
    print \$japh;#()[^
    for (my $(b) = 1; $(b) < $(q); \$b++;) {
        /g])+[\](^.^)\[
    }
    ]*$}x

(?# ... )是一个嵌入的注释,我们可以删除它。接下来是字符类

代码语言:javascript
复制
[^
    for (my $(b) = 1; $(b) < $(q); \$b++;) {
        /g]

代码语言:javascript
复制
[\](^.^)\[
        }
        ]

在这里,它们等同于[^bfgmoqry][\[\]()^.}\s],但是由于正则表达式将仅针对单个字符进行匹配,因此[...]*将匹配零个字符。

因此,正则表达式等同于

代码语言:javascript
复制
m/^([^bfgmoqry])$/

在这种特殊情况下(与"a" .. "z"匹配)。

*9 = sub {...}将coderef分配给glob。因为coderef不是一个有效的子程序名,但是仍然可以与->操作符一起使用,所以9->()将调用该9。这就像sub foo {...}一样,foo()"foo"->()是一回事。

字符a被编码为十进制的97作为ASCII码,所以ord("a")-961,对于z,应该是26。

$?是最后一个子错误,应该为零。$+是最后一个捕获组(ergo,$_)的值。~~%b对一个空的散列进行双重否定。空散列的标度化为0,因此双倍按位求反再次生成零。

$/ = $+; $q =~ s[$qq][$/]g只是有点混淆;因为$+$_,所以我们可以直接编写$q =~ s/$qq/$_/g

$qq = [$q, %b]; ... $$qq[0]很差劲,一个$\ = pack('h*', $q)就足够了。

9子代码中,将打印空字符串,然后是$\,它被设置为直到倒数第二行的空字符串。除去这种间接性,以及任何现在未使用的变量,以及简单的替换,我们得到:

代码语言:javascript
复制
use warnings;
use strict;
my $q = '1045737470216506f6478656270205562730602861636b65627100';
for ("a" .. "z") {
    m/^([^bfgmoqry])$/ or next;
    my $qq = ord($_) - 96;
    $q =~ s/${qq}0/$_/g;
}
print pack('h*', $q);

s/${qq}0/$_/g替换只能在0处匹配,并且我们知道pack的输出将是某个十六进制数。可能的匹配位置包括:

代码语言:javascript
复制
1045737470216506f6478656270205562730602861636b65627100
*^      *^   *^          *^*^     *^*^             *^^
 a       g    e           g b      c f              a

其中,由于正则表达式,b, f, g是被禁止的。生成的字符串为

代码语言:javascript
复制
a45737470216e6f64786562702055627c602861636b65627a0

解码成JAPH。

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17381616

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档