#!/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黑客”分配给$ japh,我们打印它但是在我们这样做之前将它分配给“”我不知道它是如何工作的。有人能解释一下这里发生了什么吗?谢谢!
答案 0 :(得分:13)
步骤№1了解混淆的Perl:通过-MO=Deparse
运行它。然后,我们得到这个输出:(删除了一个小的语法错误)
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->();
仍然不漂亮,但更好。特别是,这个正则表达式看起来很有趣:
m{^((?i)(?#q#;
print \$japh;#()[^
for (my $(b) = 1; $(b) < $(q); \$b++;) {
/g])+[\](^.^)\[
}
]*$}x
(?# ... )
是嵌入式评论,我们可以删除。接下来是字符类
[^
for (my $(b) = 1; $(b) < $(q); \$b++;) {
/g]
和
[\](^.^)\[
}
]
此处,它们相当于[^bfgmoqry]
和[\[\]()^.}\s]
,但由于正则表达式只会与单个字符匹配,因此[...]*
将匹配零个字符。
因此,正则表达式等同于
m/^([^bfgmoqry])$/
在此特殊情况中(与"a" .. "z"
匹配)。
*9 = sub {...}
将一个coderef分配给一个glob。由于9
不是有效的子例程名称,但仍可与->
运算符一起使用,9->()
会调用该coderef。这跟sub foo {...}
一样,foo()
和"foo"->()
是一回事。
char [{1}}被编码为十进制a
为ASCII,因此97
为ord("a")-96
,而1
为26。
z
是最后一个子错误,应为零。 $?
是最后一个捕获组的值(ergo,$+
)。 $_
双重否定空哈希。空哈希的标量为~~%b
,因此双位否定将再次产生零。
0
只是有点混淆;由于$/ = $+; $q =~ s[$qq][$/]g
是$+
,我们可以直接写$_
。
$q =~ s/$qq/$_/g
是蹩脚的,$qq = [$q, %b]; ... $$qq[0]
就足够了。
在$\ = pack('h*', $q)
子句中,将打印空字符串,然后是9
,其设置为倒数第二行的空字符串。删除这个间接级别,以及任何现在未使用的变量,以及简单的替换,我们得到:
$\
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
的某个十六进制数。匹配的可能位置是:
pack
其中1045737470216506f6478656270205562730602861636b65627100
*^ *^ *^ *^*^ *^*^ *^^
a g e g b c f a
由于正则表达式而被禁止。结果字符串是
b, f, g
解码为JAPH。