2012-02-18 141 views
54

我试图反混淆以下Perl代码(source):如何正确解析Perl脚本?

#!/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.

运行代码低谷Deparseperltidyperl -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); 

使得散列与作为键ATCG和作为值0123。 我通常使用Python编码,因此这转换为Python中的字典{'A': 0, 'B': 1, 'C': 2, 'D': 3}

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

加入与$;subscript separator for multidimensional array emulation哈希的键。该文件说,默认是“\ 034”,在AWK一样SUBSEP,但是当我做:

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

我得到的价值28?此外,我不清楚这是如何模拟多维阵列。现在是$p在Python中是什么样的[['A'], ['T'], ['C'], ['G']]

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

只要$d比赛,在块而执行该代码。但由于我不完全了解什么结构$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; 
} 

对于从0范围$d3提取一些子,但在这一点上,我完全失去了。最后几行连接所有内容并评估结果。

+11

真棒问题。 – Rayfleck 2012-02-18 14:55:16

+16

你应该小心处理'eval'混淆字符串的代码。我在这里看到了一个迂回的问题,它以一个字符串的eval结尾的“rm -rf /”'结尾。 – TLP 2012-02-18 15:00:20

+2

提醒我[Acme :: EyeDrops](http://p3rl.org/Acme::EyeDrops)。 – 2012-02-19 15:13:57

回答

50

注意:不要盲目的跑混淆perl的,尤其是如果有一个eval,反引号,systemopen,等它打电话的地方,并可能不是太明显*。使用Deparse对其进行去混淆处理,并且仔细地用打印语句替换eval是必须的,直到您明白发生了什么为止。应该考虑在沙箱/非特权用户/在虚拟机中运行。

*s&&$_ⅇ评估$_为intance。


第一观察:034是八进制。它等于28(十进制)或0x1c(十六进制),所以没有什么可怕的。

$;事情纯属迷惑,特别是找不到理由。 $p将只是一个字符串A.T.C.G(而.取代$;,无论它是什么)。
所以在正则表达式[$p]匹配{'A', 'T', 'C', 'G', $;}中的任何一个。由于$;从来没有出现在$d,那里没用。 反过来[$p]{4}四个字母的顺序匹配上面的设置,仿佛这已经使用(忽略无用$;):

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

如果你不得不写这个自己,在去除空白后,你” d只需抓取长度为4的$d的每个连续子字符串(假设$d中没有其他字符)。

现在,这部分很有趣:

foreach $d (0 .. 3) { 
    $c += $a{ substr $1, $d, 1 } * 4**$d; 
} 
  • $1保持当前的四个字母的代码点。 substr $1, $d, 1返回该码点的每个连续字母。
  • %a映射A为00b(二进制),T到01B,C到10b和G为11b。

    A 00 
    T 01 
    C 10 
    G 11 
    
  • 通过4**$d乘以将相当于0,2,4和6

逐位左移位所以这个有趣的结构允许你在碱基构建任何8位值四个系统以ATCG作为数字!

即它执行以下操作的转换:

  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,而不是螺旋线(并删除解码器中的跳过部分)。

+8

现在想了解一个非常有趣的问题:如何编写将文本转化为DNA的代码? =) – TLP 2012-02-18 15:42:33

+12

提供给DNA脚本的文本(如此unobfuscated它看起来不正确的perl):) – Mat 2012-02-18 15:51:19

+5

+1非常好:)关于你的警告的一件事:'eval'部分也可以被混淆。我在主要注释中提到的代码使用了';; s ;; $ _; see'',这是'$ _'上的双重评估。 – TLP 2012-02-18 16:35:11