55

次の Perl コード ( source )の難読化を解除しようとしています:

#!/usr/bin/perl
(my$d=q[AA                GTCAGTTCCT
  CGCTATGTA                 ACACACACCA
    TTTGTGAGT                ATGTAACATA
      CTCGCTGGC              TATGTCAGAC
        AGATTGATC          GATCGATAGA
          ATGATAGATC     GAACGAGTGA
            TAGATAGAGT GATAGATAGA
              GAGAGA GATAGAACGA
                TC GATAGAGAGA
                 TAGATAGACA G
               ATCGAGAGAC AGATA
             GAACGACAGA TAGATAGAT
           TGAGTGATAG    ACTGAGAGAT
         AGATAGATTG        ATAGATAGAT
       AGATAGATAG           ACTGATAGAT
     AGAGTGATAG             ATAGAATGAG
   AGATAGACAG               ACAGACAGAT
  AGATAGACAG               AGAGACAGAT
  TGATAGATAG             ATAGATAGAT
  TGATAGATAG           AATGATAGAT
   AGATTGAGTG        ACAGATCGAT
     AGAACCTTTCT   CAGTAACAGT
       CTTTCTCGC TGGCTTGCTT
         TCTAA CAACCTTACT
           G ACTGCCTTTC
           TGAGATAGAT CGA
         TAGATAGATA GACAGAC
       AGATAGATAG  ATAGAATGAC
     AGACAGAGAG      ACAGAATGAT
   CGAGAGACAG          ATAGATAGAT
  AGAATGATAG             ACAGATAGAC
  AGATAGATAG               ACAGACAGAT
  AGACAGACTG                 ATAGATAGAT
   AGATAGATAG                 AATGACAGAT
     CGATTGAATG               ACAGATAGAT
       CGACAGATAG             ATAGACAGAT
         AGAGTGATAG          ATTGATCGAC
           TGATTGATAG      ACTGATTGAT
             AGACAGATAG  AGTGACAGAT
               CGACAGA TAGATAGATA
                 GATA GATAGATAG
                    ATAGACAGA G
                  AGATAGATAG ACA
                GTCGCAAGTTC GCTCACA
])=~s/\s+//g;%a=map{chr $_=>$i++}65,84,67,
71;$p=join$;,keys%a;while($d=~/([$p]{4})/g
){next if$j++%96>=16;$c=0;for$d(0..3){$c+=
$a{substr($1,$d,1)}*(4**$d)}$perl.=chr $c}
             eval $perl;

実行すると、出力されますJust another genome hacker.

コード トラフDeparseperltidy( perl -MO=Deparse jagh.pl | perltidy) を実行すると、コードは次のようになります。

( my $d =
"AA...GCTCACA\n" # snipped double helix part
) =~ s/\s+//g;
(%a) = map( { chr $_, $i++; } 65, 84, 67, 71 );
$p = join( $;, keys %a );
while ( $d =~ /([$p]{4})/g ) {
    next if $j++ % 96 >= 16;
    $c = 0;
    foreach $d ( 0 .. 3 ) {
        $c += $a{ substr $1, $d, 1 } * 4**$d;
    }
    $perl .= chr $c;
}

これが私が自分で解読できたものです。

( my $d =
"AA...GCTCACA\n" # snipped double helix part
) =~ s/\s+//g;

$d(二重らせん)内のすべての空白を削除します。

(%a) = map( { chr $_, $i++; } 65, 84, 67, 71 );

Aキー、TCおよびGを値012およびとしてハッシュを作成します3。私は通常 Python でコーディングするので、これは Python の辞書{'A': 0, 'B': 1, 'C': 2, 'D': 3}に変換されます。

$p = join( $;, keys %a );

多次元配列エミュレーションのために、ハッシュのキーを添え字セパレータと結合し$;ます。ドキュメントには、デフォルトはawkのSUBSEPと同じ「\ 034」であると書かれていますが、そうすると:

my @ascii = unpack("C*", $p);
print @ascii[1];

私は値を取得します28か?また、これが多次元配列をどのようにエミュレートするかは明確ではありません。Python$pのようなものになりましたか?[['A'], ['T'], ['C'], ['G']]

    while ( $d =~ /([$p]{4})/g ) {

$d一致する限り([$p]{4})、while ブロック内のコードを実行します。しかし、私は構造が完全に理解していないので$p、ここで何が起こっているのかを理解するのにも苦労しています.

next if $j++ % 96 >= 16;

$jモジュロ 96 が 16 以上の場合は続行$jします。while ループ (?) の各パスでインクリメントします。

$c = 0;
foreach $d ( 0 .. 3 ) {
    $c += $a{ substr $1, $d, 1 } * 4**$d;
}

$dからの範囲でいくつかの部分文字列03抽出しますが、この時点で私は完全に迷っています。最後の数行はすべてを連結し、結果を評価します。

4

1 に答える 1

51

注意: 難読化された perl をやみくもに実行しないでください。特に、その中にeval, バッククォート , system,openなどの呼び出しがあり、それがあまり明白ではない場合があります*。何が起こっているのかを理解するまでは、難読化を解除しDeparse、慎重に s を print ステートメントに置き換える必要があります。evalサンドボックス/非特権ユーザー/VM で実行することも考慮する必要があります。

*s&&$_ⅇインスタンスを評価$_します。


最初の観測:034は 8 進数です。これは 28 (10 進数) または 0x1c (16 進数) に等しいので、怪しいものはありません。

事は純粋に難読化であり、$;特にそれを使用する理由が見つかりません。$p単なる文字列になりますA.T.C.G(それが何であれ、に.置き換えられ$;ます)。
したがって、正規表現では の[$p]いずれかと一致します{'A', 'T', 'C', 'G', $;}$;には絶対に出てこないので$d、そこは駄目です。次に[$p]{4}、これが使用されたかのように、上記のセットの 4 文字の任意のシーケンスに一致します (無駄な を無視します$;)。

while ( $d =~ /([ATCG]{4})/g ) { ... }

これを自分で書かなければならない場合、空白を削除した後$d、長さ 4 の連続する各部分文字列を取得するだけです ( に他の文字がないと仮定します$d)。

今、この部分は楽しいです:

foreach $d ( 0 .. 3 ) {
    $c += $a{ substr $1, $d, 1 } * 4**$d;
}
  • $1現在の 4 文字のコードポイントを保持します。substr $1, $d, 1そのコードポイントから連続する各文字を返します。
  • %aA00b (バイナリ)、T01b、C10b、およびG11bにマップされます。

    A   00
    T   01
    C   10
    G   11
    
  • を掛けること4**$dは、0、2、4、および 6 のビットごとの左シフトと同等になります。

ATCGしたがって、この面白い構文を使用すると、 as digitsを使用して基数 4 システムで任意の 8 ビット値を構築できます。

つまり、次の変換を行います。

         A A A A
AAAA -> 00000000

         T A A T
TAAT -> 01000001 -> capital A in ascii

         T A A C
CAAT -> 01000010 -> capital B in ascii

CAATTCCTGGCTGTATTTCTTTCTGCCT -> BioGeek

この部分:

next if $j++ % 96 >= 16;

上記の変換を最初の 16 の「コードポイント」に対してのみ実行し、次の 80 をスキップしてから、次の 16 に対して変換し、次の 80 をスキップするなどです。本質的には、楕円の一部をスキップするだけです (ジャンク DNA 除去システム)。


これは、らせんを置き換えるために何かを生成するために使用できる醜いテキストからDNAへのコンバーターです(80スキップのものを処理しません):

use strict;
use warnings;
my $in = shift;

my %conv = ( 0 => 'A', 1 => 'T', 2 => 'C', 3 => 'G');

for (my $i=0; $i<length($in); $i++) {
    my $chr = substr($in, $i, 1);
    my $chv = ord($chr);
    my $encoded ="";
    $encoded .= $conv{($chv >> 0) & 0x3};
    $encoded .= $conv{($chv >> 2) & 0x3};
    $encoded .= $conv{($chv >> 4) & 0x3};
    $encoded .= $conv{($chv >> 6) & 0x3};
    print $encoded;
}
print "\n";
$ perl q.pl 'print "BioGeek\n";'
AAGTCAGTTCCTCGCTATGTAACACACACAATTCCTGGCTGTATTTCTTTCTGCCTAGTTCGCTCACAGCGA

らせん$dの代わりにそれを貼り付けます(デコーダーのスキップ部分を削除します)。

于 2012-02-18T15:13:02.243 に答える