2
    #!/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->();

その多くは余分な/純粋な難読化だと思います。「Just another Perl hacker」を $japh に割り当て、それを印刷しますが、その前に「」に割り当てるので、それがまだどのように機能するかわかりません。誰かがここで何が起こっているのか説明できますか? ありがとう!

4

1 に答える 1

13

難読化された Perl を理解するためのステップ 1: 実行します-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 {...}コードリファレンスをグロブに割り当てます。9は有効なサブルーチン名ではありませんが、->演算子で使用できるため、その coderef を呼び出し9->()ます。これは と同じでsub foo {...}foo()"foo"->()は同じものです。

charはASCII のようにa10 進数としてエンコードされるため、 の場合は 26 になります。97ord("a")-961z

$?最後の子エラーであり、ゼロである必要があります。$+は最後のキャプチャ グループの値です (ergo, $_)。空の~~%bハッシュを二重否定します。空のハッシュのスカラー化は0であるため、ビットごとの二重否定は再びゼロを生成します。

これ$/ = $+; $q =~ s[$qq][$/]gはちょっとした難読化です。そのまま、直接書くこと$+$_できます$q =~ s/$qq/$_/g

$qq = [$q, %b]; ... $$qq[0]不自由ですが、$\ = pack('h*', $q)十分です。

サブでは、空の文字列が出力され、最後から 2 番目の行まで空の文字列に設定される が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禁止されています。結果の文字列は

a45737470216e6f64786562702055627c602861636b65627a0

これはJAPHにデコードされます。

于 2013-06-29T16:10:04.220 に答える