解密模糊的perl脚本



我的服务器上有一些垃圾邮件问题,在发现并删除了一些Perl和PHP脚本后,我开始检查它们的真正功能,尽管我是一名资深PHP程序员,但我对Perl没有什么经验,有人能帮我处理一下这里的脚本吗:

http://pastebin.com/MKiN8ifp

(这是一长行代码,脚本名为list.pl)


脚本的开头是:

$??s:;s:s;;$?::s;(.*); ]="&%[=.*.,-))'-,-#-*.).<.'.+-<-~-#,~-.-,.+,~-{-,.<'`.{'`'<-<--):)++,+#,-.{).+,,~+{+,,<)..})<.{.)-,.+.,.)-#):)++,+#,-.{).+,,~+{+,,<)..})<*{.}'`'<-<--):)++,+#,-.{).+:,+,+,',~+*+~+~+{+<+,)..})<'`'<.{'`'<'<-}.<)'+'.:*}.*.'-|-<.+):)~*{)~)|)++,+#,-.{).+:,+,+,',~+*+~+~+{+<+,)..})

它继续使用宝贵的少数非标点符号字符,直到最后:

0-9;\_rs}&a-h;;s;(.*);$_;see;

s;(.*);$_;see;替换为print以获得此值。在有效载荷的前半部分用print再次替换s;(.*);$_;see;,得到这个,这就是解密代码。有效负载的后半部分是要解密的代码,但我不能再往下说了,因为正如你所看到的,解密代码正在envvar或cookie中寻找密钥(这样大概只有脚本的创建者才能控制或解码它),而我没有那个密钥。这实际上是相当巧妙的做法。

对于那些对细节感兴趣的人。。。第一部分,当去纠缠看起来像这样:

$?  ?  s/;s/s;;$?/ :
       s/(.*)/...lots of punctuation.../;

行开头的$?是包含子错误的预定义变量,毫无疑问,这只是混淆。它将是未定义的,因为此时不可能有子错误。

它后面的问号是三元算子的开始

CONDITION ? IF_TRUE : IF_FALSE

这也只是为了混淆。为true返回的表达式是一个替换正则表达式,其中/斜线分隔符已替换为冒号s:pattern:replacement:。上面,我放回了斜线。另一个表达式,也就是将要执行的表达式,也是一个替换正则表达式,尽管它非常长。分隔符为分号。

这种替换将$_(默认的输入和模式搜索空间)中的.*替换为大量的标点符号,这些标点符号代表了大部分代码。由于.*匹配任何字符串,即使是空字符串,它也会被简单地插入到$_中,并且在所有意图和目的上都与简单地将字符串分配给$_相同,这就是我所做的:

$_ = q;]="&%[=.*.,-))'-,-# .......;;

以下几行是音译和另一种替换。(我插入注释指出分隔符)

y; -"[%-.:<-@]-`{-}#~$\;{$()*.0-9;\_rs}&a-h;;
#^                       ^           ^          ^
#1                       2                      3

(1,2,3是分隔符,2和3之间的分号是转义符)

它的基本要点是,各种字符和范围-"(空格到双引号),以及看起来像字符类(有范围)[%-.:<-@]但不是的东西,被音译成更易读的字符,例如大括号、美元符号、括号、0-9等。

s;(.*);$_;see;

下一次换人是魔术发生的地方。它也是一个使用模糊分隔符的替换,但有三个修饰符:sees在这种情况下不起任何作用,因为它只允许通配符.与换行符匹配。然而,ee意味着对表达式求值两次。

为了了解我在评估什么,我进行了音译并打印了结果。我怀疑我在某个地方有一些字符被破坏了,因为有一些细微的错误,但这里是简短的(清理过的)版本:

s;(.*);73756220656e6372797074696f6e5f6 .....;;  # very long line of alphanumerics
s;(..);chr(hex($1));eg;
s;(.*);$_;see;
s;(.*);704b652318371910023c761a3618265 .....;;  # another long line
s;(..);chr(hex($1));eg; 
&e_echr($_);
s;(.*);$_;see;

长正则表达式再次成为数据容器,并将数据插入$_中以作为代码进行评估。

s/(..)/chr(hex($1))/eg;开始看起来相当清晰。它基本上是一次从$_读取两个字符,并将其从十六进制转换为相应的字符。

倒数第二行&e_echr($_);让我困惑了一段时间,但它是一个子程序,定义在这个评估代码的某个地方,因为霍布斯能够很好地解码。美元符号的前缀是反斜杠,这意味着它是对$_:的引用,即子程序可以更改全局变量。

经过多次评估后,$_通过该子程序运行,之后$_中包含的任何内容都将进行最后一次评估。大概这次是在执行代码。正如hobbs所说,需要一个密钥,该密钥取自运行脚本的机器的环境%ENV。我们没有。

询问B::Deparse模块使其可读性(稍微提高一点)。

最新更新