Godzilla-流量特征

PHP类型 

PHP连接,拦截到三个流量包 

第⼀个数据包 

第⼀个包设置了 session:set-cookie

图片

把pass参数后的值进⾏url解码:

图片

shells.cryptions.phpXor.PhpEvalXor.java 追踪 inti()

图片

进⼊函数:this.evalContent = generateEvalContent();

图片

对key参数后⾯的内容⽤⼀下脚本进⾏解密:


<?php
function encode($D,$K){
for($i=0;$i<strlen($D);$i++) {
$c = $K[$i+1&15];
$D[$i] = $D[$i]^$c;
}
return $D;
}
function isGzipStream($bin){
if (strlen($bin)>=2){
$bin=substr($bin,0,2);
$strInfo = @unpack("C2chars", $bin);
$typeCode = intval($strInfo['chars1'].$strInfo['chars2']);
switch ($typeCode) {
case 31139:
return true;
break;
default:
return false;
}
}else{
return false;
}
}
$pass = "填充";
$key='3c6e0b8a9c15224a';
$data=encode(base64_decode($pass),$key);
if(isGzipStream($data)){
echo "666\n";
echo gzdecode($data);
}
else{
echo $data;
}
?>

得到结果如下,就是右边的⼤⻢:

图片

第⼆个数据包

数据包返回“ok” 则表⽰连接成功

图片

burp返回的数据如下:16位和后16位是md5值,中间标⻩的才是服务端返回的数据

图片

依旧⽤上述脚本进⾏解密:得到结果如下

图片

第三个数据包

对key参数的值进⾏解密,得到参数名:getBasicInfo → 字面意思,就是获取服务端的基本信息

图片

分析下Response,对前后16个值进⾏拆分,⽤上述脚本解密,得到如下:

图片

特征分析 

PHP类型:

  1. 第⼀个包很⻓,注⼊⼤⻢,⽤来进⾏后续的操作,包含 run、bypass_open_basedir、formatParameter、evalFunc 等⼆⼗多个功能函数,具备 代码执⾏、⽂件操作、数据库操作等诸多功能;且⽤于设置session,返回包存在:set-cookie

  2.  第⼆个包之后都存在cookie值,是第⼀包设置的

    图片

  3. Response 的值都是前后16位md5值包裹真正的返回内容,如果载荷是PHP_XOR_BASE64,md5的计算⽅式为:substr(md5($pass.$key),0,16);

    其中,pass=设置的连接密码,key是设置的md5值前16位

    而 md5 值落在 0123456789ABCDEF范围内,因此很容易去匹配,正则匹配类似于(?i:[0-9A-F]{16})[\w+/]{4,}=?=?(?i:[0-9A-F]{16}) 需要注意的是md5需要同时匹配字⺟⼤⼩写两种情况,因为在JAVA版webshell响应中为⼤写字⺟,在PHP版中为⼩写字⺟。

    图片

    图片

  4. cookie中最后的分号

  5.  请求字段[弱特征]:

    5.1 所有请求中Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8

    5.2 所有响应中Cache-Control:no-store, no-cache, must-revalidate

    图片

JAVA格式 

观察webshell的⽣成 

进入代码 core.ui.component.dialog.GenerateShellLoder

存在⽅法: generateButtonClick()

图片

先判断 密码、密钥、有效载荷以及加密器是否都已填写。

如果都填写之后则通过 Application.getCryption() 函数获取到⼀个Cryption 加密器的实例, 然后调⽤该实体的 generate ⽅法⽣成webshell⽂件的字节数组

Cryption 是⼀个接⼝,找到继承该接⼝的实体类:

图片

实现⽅法:generate() 传⼊password和key

图片

接着调⽤ 

Generate.GenerateShellLoder(password, functions.md5(secretKey).substring(0, 16), false); 

这⼉对key进⾏md5加密,并取前16个字符。还有形参:isBin 接着追踪,来到 shells.cryptions.JavaAes.Generate 调⽤⽅法:GenerateShellLoder(String pass, String secretKey, boolean isBin)

图片

该⽅法⼜调⽤:GenerateShellLoder("", pass, secretKey, isBin) 这⼉的形参isBin是⽤来指定读取的模板 

为true,则获取raw,flase就是base64

图片

模板⽂件如下⽬录:

图片

在读取完 base64GlobalCode.bin 以及 base64Code.bin ⽂件内容后, ⾸先⽤传⼊ Generate.GenerateShellLoder ⽅法时的 password 和处理过的 secretKey 来替换从base64GlobalCode.bin 模板读取出来的 {pass} 以及 {secretKey} 字符 

接着根据⽤户选择的格式⽣成对应的shell⽂件 

之后程序⽤处理过后的 base64GlobalCode.bin内容以及读取到的base64Code.bin 内容来分别替换shell.jsp⽂件中的{globalCode} 以 及 {code}字符, 替换成功后就会在⽤户指定的⽬录下⽣成真正的哥斯拉jsp版本的webshell⽂件。 

模板⽂件:shell.jsp

图片

通信特征

来到对应⽬录⽂件:core.ui.component.frame.ShellSetting

图片

testButtonClick() ⾸先调⽤ updateTempShellEntity() 对类ShellEntity 进⾏初始化;shellContext 就是ShellEntity的实例对象

图片

再调⽤ initShellOpertion() ⽅法作⽤如下: 

  1. 从shellEntity 获取http对象 (每个ShellEntity对象都有⾃⼰的http成员变量, ⽤于各⾃ShellEntity的Http请求)

  2.  通过payload名称获得Payload接⼝的实例类

  3. 通过payload和Cryption名称获得Cryption接⼝的实例类

图片

Payload接⼝类型负责定义webshell管理⼯具的功能动作, ⽽ Cryption接⼝类型负责定义webshell管理⼯具的加解密⾏为。上⽂中 Cryption接⼝的实现类型是JavaAesBase64类型, 这⾥的Payload接⼝的实现类型为JavaShell类型 

接着代码会调⽤ cryptionModel.init() 和 cryptionModel.check()先来到 init() ⽅法,这个⽅法会将属性state设置为true,以此通过 check() ⽅法的逻辑判断

图片

到43⾏ this.payload = this.shell.getPayloadModule().getPayload();

图片

获取class⽂件,然后调⽤ dynamicUpdateClassName("payload", data); 步⼊⽅法查看

图片

综上代码简单理解:获取到 payload.class类的字节码内容后, 该init⽅法将获取到的字节码内容通过http请求发送到服务端

我们来到45⾏:this.http.sendHttpResponse(this.payload); ⽤来发送数据,其中包含了加密的算法

图片

继续向下分析,再通过 this.cryptionModel.check() 的逻辑判断后,来到⽅法: 

this.payloadModel.init(this); 

this.payloadModel 指的就是 JavaShell 做了些成员变量赋值的操作,不具体分析

图片

还是回到ShellEntity的 initShellOpertion() ,调⽤完 payloadModel.init(this) 后,继续调⽤ this.payloadModel.test() 

这个⽅法会对返回的内容进⾏判断,如果返回ok 则判断连接成功,执⾏下⼀步操作

图片

这个⽅法对应建⽴连接的第⼆个数据包,⽤⼯具进⾏解密操作:ok

图片

我们再细看下这个 test() ⽅法,究竟是怎么实现的,他调⽤了 evalFunc() ⽅法,传⼊三个参数 

调⽤ fillParameter() ⽅法,由于我们传⼊的第⼀个参数为null,因此跳过if语句,执⾏ parameter.add(”methodName”,funcName);

当然从客户端发送的数据都会gzip压缩,然后再通过 sendHttpResponse() ⽅法发送给服务端

图片

对其配对的形式有点类似于:key-value 我们⽤⼯具进⾏解密,如下所⽰

图片

当然了,第三个数据包是⽤来获取服务端的基础信息:⽅法名 getBasicsInfo

图片

java的流量细节和php差不多的,能把代码捋下来 研究他的流量细节都没问题

欢迎大家关注麋鹿安全,我们的文章会第一时间发布在公众号平台,如果不想错过我们新鲜出炉的好文,那就请扫码关注我们的公众号!

  • 13
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值