写在前面的话
在检测网站安全性的过程中,最麻烦的一部分工作就是要确保我们能够找出网站中所有已存在的后门。绝大多数情况下,攻击者会在网站各种不同的地方注入恶意代码,并以此来增加再次感染该网站的成功率以及尽可能久地实现持续感染。
虽然我们之前已经给大家介绍过数百种后门以及相应的影响,但今天我们想跟大家更加深入地讨论一些关于恶意软件的分析技术,即如何解码复杂的高级恶意软件。
本文所分析的恶意软件感染样例早在几个月前就已经出现了,但是受这种恶意软件变种所感染的网站(例如WordPress和Joomla等CMS)数量却一直在增加。
恶意软件
成功感染目标网站之后,攻击者可能会进行注入后门和Web Shell、以及添加伪造的管理员用户等恶意操作。一般来说,攻击者都会采用一种或多种技术来隐藏自己的恶意代码,例如编码、加密和混淆等等。
请大家先看下面给出的代码段。其中,攻击者同时使用上面举例的三种技术。接下来,我们会一步一步地告诉大家如何对这段代码进行解码和分析。
原始的恶意软件代码段:
简化代码
在解码过程中,最重要的是要理解代码的逻辑结构。为此,我们使用了PHP Beautifier来将之前的代码段转换成了下图所示的格式:
虽然目前为止代码仍然是不可读的,但是我们现在至少已经了解了代码的编程逻辑架构。
攻击者一开始声明了一个名叫”$hc7e1d20″的变量,而这个变量是没有任何实际意义的。根据我们的经验来看,这个变量的值(406)可能是攻击者用来标识恶意软件变种版本的。
- <?php
- $hc7e1d20 = 406;
- $GLOBALS['be10eb436'] = Array();
- global $be10eb436;
- $be10eb436 = $GLOBALS;
除此之外,还有一些全局变量也对我们理解代码不会提供任何帮助,我们可以直接忽略它们。
这个恶意软件样本基本上使用的是字符/字符串修改技术,攻击者在变量中存放了很多十六进制字符,然后再将它们编译成不同的变量。
第一个样例如下:
- ${"\x47\x4c\x4fB\x41\x4c\x53"}['tbb6a']
- ="\x2d\x3d\x3e\x35\x4e\x73\x7d\x4f\x65\x77\x59\x41\x5f\x70\x6a
- \x69\x23\x3b\x51\x21\x57\x74\x4b\x46\xd\x5b\x2b\x20\x38\x76\x68\x2e\x3f
- \x44\x4d\x34\x67\x6f\x6b\x7c\x64\x7a\x31\x24\x5c\x4c\x40\x3c\x28\x5a\x79
- \x2a\x58\x78\x7e\x6c\x63\x43\x71\x49\x33\x47\x54\x36\x53\x75\x27\x5e\x29
- \x56\x66\x26\x32\x2c\x62\x30\x2f\x6e\xa\x50\x22\x25\x52\x5d\x45\x60\x42
- \x48\x39\x61\x37\x7b\x4a\x9\x55\x3a\x6d\x72";
这段代码可以直接通过下面的bash命令来进行转译:
- $ echo -e"\x47\x4c\x4fB\x41\x4c\x53"
- GLOBALS
- $ php -r 'echo"\x47\x4c\x4fB\x41\x4c\x53";'
- GLOBALS
这个值(${GLOBALS}[‘tbb6a’])似乎使用了某些特殊字符来防止被转译,但是恶意软件最终似乎并没有使用这个值。现在,我们就可以创建一个简单的PHP脚本,然后自动化地打印出所有的变量以及相应的值。
查找和替换
得到这些信息之后,我们就可以使用查找和替换功能了。
第一个变量如下:
- $be10eb436[$be10eb436['tbb6a'][55] .$be10eb436['tbb6a'][75]
- . $be10eb436['tbb6a'][8] .$be10eb436['tbb6a'][63]] =$be10eb436['tbb6a'][56] .$be10eb436['tbb6a'][30] . $be10eb436['tbb6a'][97];
- $be10eb436['tbb6a'][55] = ‘l’
- $be10eb436['tbb6a'][75] = ‘0’
- $be10eb436['tbb6a'][8] = ‘e’
- $be10eb436['tbb6a'][63]] = ‘6’
- $be10eb436['tbb6a'][56] = ‘c’
- $be10eb436['tbb6a'][30] = ‘h’
- $be10eb436['tbb6a'][97] = ‘r’
我们可以得到下面的转译结果:
- $be10eb436[‘l . ‘0’ . ‘e’ . ‘6’] = ‘c’ .‘h’ . ‘r’; ---- $be10eb436[‘l0e6’] = ‘chr’;
为了增加代码的可读性,我们将’be10eb436′替换成了’arr’(因为它被声明为了一个array()),然后我们继续对字符进行转译。
几分钟之后,我们得到了如下所示的代码:
现在一切已经更加明朗了,接下来我们还要对代码进行一些调整。其中,前几个变量可以直接替换成下列形式:
- $arr['l0e6'] = ‘chr’;
- $arr['ac6c24d1'] = ‘ord’;
- $arr['s8bb921e'] = ‘strlen’;
将代码种各个变量和值调整到相应位置之后,我们就得到了上述代码中的第一个函数:
- function l3f5($nd0f2d, $yaf8a49ab)
- {
- global$arr;
- $wb1a= "";
- for($a5be536 = 0; $a5be536 < strlen($nd0f2d);)
- {
- for($jd82720f = 0; $jd82720f < strlen($yaf8a49ab) && $a5be536 <$arr['s8bb921e']($nd0f2d); $jd82720f++,$a5be536++)
- {
- $wb1a.=chr(ord($nd0f2d[$a5be536]) ^ ord($yaf8a49ab[$jd82720f]));
- }
- }
- return$wb1a;
- }
恶意目的
替换了所有的函数以及变量之后,我们就可以得到如下所示的代码段了:
得到了完整并且可读的恶意代码之后,我们发现了几个有意思的地方:
1. 其中有一个名叫l3f5() 的函数,该函数负责通过按位异或计算来执行加密和解密操作。
2. 函数 q057860()采用了两层异或加密/解密计算。
a) 第一层计算中,密钥是一个预定义的常量: ($w158 = ‘2cef0f87-62fe-4bb9-a1de-4dc009e818ea’;)。
b) 第二层所使用的密钥来自于POST参数或HTTP coockie。
c) 这个函数主要用来对经过加密的序列化数据进行解码。其中,序列化数据是攻击者通过cookie或POST参数传递给恶意脚本的。
3. 解码数据可能包含:
a) 可执行的PHP代码。
b) 提供关于后门和PHP版本信息的命令。
总结
现在网上有很多不同类型的恶意软件,但并非所有的恶意软件都是直接通过脚本来执行恶意命令的。比如说在这个样本中,它可以通过$_POST或$_COOKIE请求来接收任意命令,而Web服务器默认是不会记录这种行为的。
为了防止网站被恶意软件所感染,我们强烈建议管理员采用类似文件完整性监测以及Web应用防火墙(WAF)等安全措施。除此之外,我们还建议管理员定期检查网站的日志记录以尽早地发现可疑行为。