如何正确deobfusacte Perl脚本?

我试图去混淆下面的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作为值03进行散列。 我通常使用Python进行编码,所以在Python中将其转换为字典{'A': 0, 'B': 1, 'C': 2, 'D': 3}

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

$;join哈希键$; multidimensional array仿真的下标分隔符 。 这个文档说默认是“\ 034”,和awk中的SUBSEP一样,但是当我这样做的时候:

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

我得到的价值28 ? 此外,我不清楚这是如何模拟多维arrays。 现在$p是Python中的[['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; } 

对于03范围内的$d提取一些子string,但在这一点上,我完全失去了。 最后几行连接一切并评估结果。

注意 :不要盲目地运行混淆的Perl,特别是如果有一个eval ,反引号, systemopen等调用它的地方,这可能不是太明显 * 。 用Deparse混淆它,仔细地用打印语句replaceeval是必须的,直到你理解到底是怎么回事。 运行在沙箱/非特权用户/在虚拟机中也应该考虑。

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


首先观察: 034是八进制。 它等于28(十进制)或0x1c(hex),所以没有什么可疑的。

$; 事情纯粹是混淆,特别是找不到理由。 $p将只是一个stringATCG (用$;replace,不pipe它是什么)。
所以在正则expression式[$p]匹配任何{'A', 'T', 'C', 'G', $;} 。 由于$; 从来没有出现在$d ,那里没用。 反过来, [$p]{4}匹配上述集合中任意四个字母的序列,就好像这个已经被使用了一样(忽略无用的$; ):

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

如果你必须自己写这个,删除空格之后,你只需要抓取每个长度为四的$d的子string(假设$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的按位左移。

所以这个有趣的结构允许你在ATCG的基数四系统中build立任何8位数值作为数字!

即它做了以下转换:

  AAAA AAAA -> 00000000 TAAT TAAT -> 01000001 -> capital A in ascii TAAC 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 ,而不是螺旋(并删除解码器中的跳过部分)。