这是一篇前段时间写的文章,现在归整到这个博客中,那个时候刚学网络安全不久。当时遇到这个木马也是极其偶然,就当做兴趣进行分析,搞了差不多有一天半的时间,期间收获颇多,果然实践中才是出真知啊。
木马来源
有天早去上课的时候收到学妹的消息说她的服务器被人上传了木马,我当时心里一愣,因为前一天还在和她讨论关于在她网站上存在的安全性问题,结果第二天就被人黑了,不禁感叹现在黑客的效率是真的高啊。
为了证明我这不是马后炮,贴出以下聊天记录:
前一天:
后一天:
她用的是WordPress这个博客系统,wordpress本身的安全性还可以,使用也很方便。但是各种第三方插件的安全性就不敢保证了。她正是因为装了有安全漏洞的第三方插件,所以就被黑客利用了,估计还是大规模攻击的受害者。通过腾讯云的路径提示找到了恶意脚本文件(木马,webshell等在本文中是同一个意思)。再通过查看访问流量看到入侵者的IP地址,查明后发现来源是俄罗斯。俄罗斯黑客在我印象中都是挺厉害的,就打算分析一下源码,下面就把这个过程分享出来。
初始信息分析
脚本名:404.php(伪装成404文件,起隐藏作用。)
1、在php环境下浏览器打开
显示如下:
恶意脚本的登录界面,需要输入密码进入,尝试多次弱口令登录没有通过。
2、用Notepad++打开查看源码
显示如下:
发现是一个经过编码加密后的内容,从这里看不到源码,所以只能先进行破解。
开始破解
第一步
观察变量,把中间一大串密文字符忽略(这里用X代替),整体框架显示如下:
这里解码较为容易,第一行是一串无规则的字符,存放到一个变量中。再从这个变量中取第几位,和其他字符组成一个完整的单词。比如$MZz9092[9]就是最开头的第0位数到第九位的字符,也就是p。
第二步
我们加一个echo($AI2908);让浏览器运行的值显示出来,保险起见可以先把其他代码先注释掉。
操作如下:
显示结果如下:
这是一个PHP的替换函数。
第三步
解码下一个变量的值:$vVzI785
这串代码中有chr()函数,查ascll码表得知chr(101)是e,通过ascll码表的对应关系,可以解除chr()的字符,在这其中还存在着十六进制(hex)编码,整个就像是混合编码,机器是能够直接识别,人眼就不容易发现规律了。
编码原理:chr(101)意思就是ascll码表上101个字符 是e
\x61 对应的解码是 a
之后在变量前加个echo让机器自动解码,$vVzI785变量和$ePpo5652编码原理相同,就一起显示出来:
浏览器显示如下:
因为中间没有加换行符,所以显示的结果连在一起,主要加密的内容(X代替的部分)就放在这个括号中。
最后整理下得到如下:
最后一行加密部分解码出来是一个正则表达式:/.*/e 此处没实际作用就先不管它。
接下来看主体的编码方式。
第四步
存放主体的变量$kJVTr8520是base64加密后再压缩编码。所以解码的顺序就反着来,先解压缩然后base64解码。这里我们继续使用echo(echo大法好!)
把之前x替换的主体放进括号,然后用echo大法构造这行echo($kJVTr8520);这里要把原来的eval删去改成echo。文件尾部图片中已改。
文件头部:
文件尾部:
利用echo查看传给这个变量的值。
浏览器查看直接得到解码后的“原文”:
第五步
放到编辑器上整理一下:
代码头部:
代码尾部:
又是一层加密,而且感觉是多重加密,这个脚本的作者应该不是人!(估计是程序生成)
这段代码可以看成两个部分:密码验证部分和主体.
主体也分成了两个部分:代码尾部的base64加密的部分是一段多重base64加密,主体部分又是一大串加密编码后的字符传值给一个变量。
第六步
这里先从密码验证部分入手,作者之所以把这部分独立出来估计他也是怕忘记密码后没法改吧。所以我们正好可以利用这一点,既然猜不出你的密码,那就自己改咯。
先看到第一行代码:
密码是md5加密后的,我试过解这串md5但是现有的解码网站都解不出。
那就换一个思路,自己改密码值。
先查了下已知明文admin经过md5加密后的值是多少:
这里就用第一行的密文,替换掉原来的md5:
Ps:这里如果直接输$auth_pass=”admin”是不行的。
第七步
之后再回到之前最开始访问的登录界面,密码处敲入admin。
进去了!现在就可以使用这个木马做想做的事情咯~而且功能还挺全的,是个大马。
字符编码是:窗口1251,属于斯拉夫语系,俄语正是斯拉夫语系的,看来是俄罗斯的木马没跑了。
现在到这一步就可以把这个木马收归己有了~
第八步
再从这里查看源码:
诶?发现只是一个静态的界面,执行这段代码没有任何功能,所以从这里我们获得的不是真正的源码。
主体内容破解
精彩的内容来了!接下还是要分析主体部分。规律掌握了,就不再慌张。上面说了主体也是可以看成两个部分,代码部分和加密函数部分。加密函数就是解密代码部分的内容。
1、先从加密函数开始
这串密文果然是经过多次base64加密的(真的很麻烦呐),利用多次echo大法解出整理后得到如下:
脚本的作者还把变量名起的很复杂难以理解,看来是使用程序生成的,手工破解的我就用简单的字符替换了:
现在就比较清晰了。
这里主要关注for循环的内容,就能理解加密规则。
php中的strlen函数可以获取代码的字符串长度。for循环中i从0开始,也就是第一个字符开始,每循环一次,i自加1跳到下一个字符,直到最后一个字符为止。
从第一个字符开始,然后让它和后面的2129405204进行异或(^)的位运算。
(1)拿n这个字符举例:
得到的是110(ord就是求n再ascll码中对应的数值)。
(2)再让n进行位运算:
得到的是:
(3)再通过chr函数得到最后的结果为: z
这样n就替换成了z。
这样整篇大段的字符都被相同的方式替换。最后传值给$a。
知道这个原理后我们就继续用echo显示出传给$a的值:
得到以如下代码:
又双叒是一层加密。
让我想到了杨宗纬的《洋葱》一层一层拨开你的心~
稍微欣慰点的是这个变量名不那么奇怪了。
2、了解两个函数
先来了解substr和hexdec这两个函数的功能(毕竟对php不熟,磨刀不误砍柴工嘛。)
Substr:
Hexdec:
接下来继续看加密函数,现在这个脚本整体编码的思想就是替换,密码学算法知识尚未涉及,不过花样确实够多,只有这样既能绕过防火墙检测还能被电脑继续执行。
这个替换函数的规则是用substr提取字符,并把取出的字符当做是十六进制再转换为十进制,最后再用chr转换为字符进行替换,而且是一次性提取两个。
比如“0123456789abcde中”(因为是作为十六进制的,上面一大串代码中就不会出现其它字符了)
取到了cd,把cd当成一个十六进制的值转为十进制就是205:
如此进行替换。
这一部分函数的功能明白后开始继续用echo大法。
得到下一串代码:
又是一层加密!!不过能预感到这是最后一层了,底部出现了似曾相识的正则替换,
但在这里意义同样不大。
3、继续echo大法:
Duang~浏览器运行直接出现网页了,不过这个报错的弹窗是什么鬼?
但经历过这么多的我看到这里,内心没有丝毫波动,甚至还有点想笑,一眼看出这是运行JavaScript的结果,真相就在这里了!
4、查看源码
源码就在这里,但是怎么才能查看呢?
我们可以写一个解码用的脚本,让它把让echo显示的值直接写到文件上:
1 |
|
把之前要解码的字符放上去,最后在同一个目录下生成了一个test.php的文件。文本编辑器打开就是心心念念的源码了,不再是之前得到的静态”源码”!
然后找到了刚刚弹窗报错的那段代码。呵,小把戏。一切都一目了然了~
剥完这个洋葱后,留下了“欣喜”的泪水。